Java고급문법_4_File I/O

소정·2023년 2월 6일
0

Java

목록 보기
22/23

Data의 영구적인 저장

프로그램은 실행하면 Ram에 올라오고 그 안에서 임시저장되는데 Ram은 휘발성이라 프로그램을 종료하면 데이터 날아감 그래서 데이터를 영구적으로 저장할 필요가 있음 프로그램과 외부데이터가 연결된 길Stream이라고 부른다
데이터를 읽어오는 길은 입력스트림이라 부르고 출력을 위한 길은 출력스트림이라고 하는데 이처럼 두가지로 분류하는 이유는 스트림은 단방향이기 때문이다. 또한 스트림은 일회용이다

저장 관점 2가지 데이터를 다른사람과 공유 할 것인가? 아님 나만 가질것인가 나만 볼거면 내 컴퓨터에 저장하면 되지만 공유할거면 서버에 저장해야됨

[1] 내 컴퓨터에 저장하기


다른 사람과 공유할 필요없이 내 컴퓨터에 저장하기

램은 Data를 가지고 있지만 하드디스크는 데이타를 '파일'로 보관함 => 하드디스크에 접근 할 땐 File 클래스 사용

바이트 스트림

1. FileInputStream

byte단위로 작업한다

1) 읽어오는 파일의 파일명을 관리하는 File 객체 생성
2) 파일과 연결된 무지개로드(Stream) 객체 만들기 그 중에서도 file전용이며 데이터를 읽어오는 스트림
=> FileInputStream
3) 스트림을 통해 파일에서 데이터 읽어오기 (바이트 단위로 읽어옴)

파일 데이터 읽어오는 메소드
read() 안에는 다음을 읽는 포인트가 있어서 next를 쓰지않아도 읽어온다.

  1. read() : 1byte만 읽어옴, 아스키값으로 가져온다 근데 더이상 읽을것이 없으면 -1리턴
    이 방식으로 읽어오면 아스키번호에 없는 것들은 이상하게 출력됨 - 바이트 단위출력이라
  2. read(byte[] b) : 바이트 배열 덩어리로 한방에 읽어오기 바이트배열 덩어리를 저장할 빈 배열이 준비되어야함
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FileInputTest {

	public static void main(String[] args) {
	
		import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FileInputTest {

	public static void main(String[] args) {
	
		//읽어오는 파일의 파일명을 관리하는 객체 생성
		File file = new File("aaa.txt"); //파일 자동 만들지않음

		//파일과 연결된 무지개로드(Stream) 만들기
		
		//그 중에서도 file전용이며 데이터를 읽어오는 스트림
		//FileInputStream
		
		try {
			
			// 1. 
			
			FileInputStream fis = new FileInputStream(file);
			
			//스트림을 통해 파일에서 데이터 읽어오기 - 바이트 단위로 읽어옴
			byte b = (byte)fis.read(); //파일에서 오로지 1byte만 읽어옴..반복문이 필요함 
			//read() 는 아스키값으로 가져옴 근데 더이상 읽을것이 없으면 -1리턴해줌
			
			while (b != -1) {
				//System.out.println(b); //글씨의 아스키 값이 찍힘
				
				System.out.print((char)b); 
				b = (byte)fis.read(); // read() 안에는 다음을 읽는 포인트가 있어서 next를  쓰지않아도 읽어옴

			}
			
			//2.
			
			//위 방식으로 읽어오면 아스키번호에 없는 것들은 이상하게 출력됨 - 바이트 단위출력이라
			//ex) 한글 
			//1 바이트씩 읽지말고 바이트 배열 덩어리로 한방에 읽어오기
			//스트링으로 읽어옴 바이트배열 덩어리를 저장할 빈 배열이 준비되어야함
			byte[] bytes = new byte[1024]; //1kb 짜리 빈사자
			fis.read(bytes); // bytes배열안에 데이터 넣어줌

			//바이트 배열을 String으로 변환
			String s = new String(bytes);
			System.out.println(s);
			
			System.out.println("\n파일 로드 종료");
			
			//스트림 close
			fis.close();
			
		} catch (FileNotFoundException e) { //해당 파일이 없으면 Exception 발생
			System.out.println("파일이 없다");
		} catch (IOException e) {
			System.out.println("읽기 과정중에 오류 발생");
		}
		
		
		
	}
	
}

2. FileOutputStream

사용자로부터 데이터를 입력받아 파일에 저장
1) 데이터를 영구적으로 저장할 하드디스트는 file형태로 데이터를 저장함 File class 객체 생성

  • File file = new File("파일 경로\파일이름");
  • file 경로(폴더) 지정하지 않으면 자동 현재 프로젝프폴더에 저장됨

2) 파일객체가 관리하는 경로의 파일에 데이터를 보내기위해 무지개 로드(Stream) 생성 : fileOutputStream
-> 만약 파일이 없다면 자동 생성함[단, 폴더는 자동생성 안함] (덮어쓰기 모드)

3) 문자열 데이터 보내기

4) 스트림 통신 하다 경우에따라선 멈춰 있을 수 있음 스트림버퍼에 찌꺼기가 남아있을 수 있어서 비우도록하는 메서드 => .flush()

5) 스트림 작업이 끝나면 스트림연결 닫는 작업 => .close();

디렉토리는 자동 생성되지 않는다
.mkdirs() : 코드내에서 디렉토리를 생성해 주는 메소드

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;

public class FileOutputTest {

	public static void main(String[] args) {

		//사용자로부터 데이터를 입력받아 파일에 저장하는 프로그램
		
		Scanner sc = new Scanner(System.in);
		
		System.out.print("저장할 데이터를 입력 : ");
		String data  = sc.next();
		data = data+"\n"; //줄바꿈하고 싶으면 +"\n" 해줘야함
		
		//데이터를 영구적으로 저장할 하드디스트는 file형태로 데이터를 저장함
		//먼저 File을 제어하는 class부터 객체로 생성
		
		//저장할 파일 이름 , 어디에 저장 할지 등 하는 놈
		File file = new File("aaa.txt"); //file 경로(폴더) 지정하지 않으면 자동 현재 프로젝프폴더에 저장됨 
		
		//2. 파일 저장할 경로를 지정
		file = new File("kkk\\aaa.txt"); //windows에서는 역슬래시가 폴더 구분자
		file = new File("kkk/aaa.txt"); 
		
		//단ㄷ 문자열 안에서는 \ 를 특수문자로 보지 않으니 \\ 두번쓴다
		//MacOS or Linux는 경로구분자로 슬래시를 사용함
		//단, windows는 슬래시도 됨!!
		
		//폴더가 없으면 자동생성이 안되기에
		//프로그램으로 폴더를 만드러보기
		File path = new File("kkk"); 
		if(!path.isDirectory()) {
			path.mkdirs(); //폴더 다중 구조도 쌉가능 다만들어줌
			//path.mkdir() // 폴더 단 하나만 만듦
			
		}
		
		// 3. 내 프로젝트 폴더가 아니라 HDD의 특정 영역 사용
		path = new File("D:\\fileTest\\kkk");
		if(!path.isDirectory()) path.mkdirs();
		
		//만들어진 폴더와 파일명 결합
		file = new File(path,"data.txt");
		
		
		//파일객체가 관리하는 경로의 파일에 데이터를 보내기위해
		//무지개 로드(Stream) 생성
		//근데 스트림은 단방향임
		//Stream 중에서 내보내는 방향의 OutputStream을 사용
		
		//그 중에서도 파일전용으로 설계된 fileOutputStream클래스로 객체 생성
		try {
			//특징 : 만약 파일이 없다면 자동 생성함[단, 폴더는 자동생성 안함]
			// 얜 기본 덮어쓰기 모드
			//FileOutputStream fos = new FileOutputStream(file); 
			
			FileOutputStream fos = new FileOutputStream(file, true);//append 모드 : true
			
			//스트림을 통해 데이터 내보내기(파일 저장)
			//fos.write(68); //유니코드번호 전달한 것 : 'A'
			
			//문자열 데이터 보내기
			byte[] bytes  = data.getBytes(); //String --> byte[]
			fos.write(bytes);
			
			//스트림 통신 하다 경우에따라선 멈춰 있을 수 있음
			//그래서 억지로 밀어줘야함
			fos.flush(); //스트림버퍼에 찌꺼기가 남아있을 수 있어서 비우도록하는 메서드
			
			//언제나 스트림 작업이 끝나면 스트림연결 닫는 작업 필요!!!**************
			fos.close();
			
			System.out.println("저장 완료");
			
		} catch (FileNotFoundException e) {
			//경로가 없는데 파일 만들어라 하면 오류메세지 출력
			System.out.println("파일을 찾을 수 없다");
		} catch (IOException e) { //읽기 전용 파일일 경우의 예외처리
			System.out.println("쓰기 작업 중 오류 발생");
		}
		
		
	}

}

3. 파일 입출력 한번에 해보기

파일 복사 프로그램 만들어보기

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileIOTest {

	public static void main(String[] args) {

		//파일 입출력 한번에 연습
		
		//파일 복사 프로그램 만들어보기
		
		//원복파일의 경로와 확장자 정해놓기
		String srcPath = "D:\\fileTest\\aaa.txt";
		
		//원본 파일과 연결하는 스트림 생성 - inputStream
		
		try {
			FileInputStream fis = new FileInputStream(srcPath);
			
			//읽어들인 파일을 바로 다른 파일에 내보내기 위해
			//새로 만들어질 파일의 저장 경로
			File path = new File("D:/copy");
			
			if(!path.isDirectory()) path.mkdirs(); //없으면 만들어줘
			
			//저장될 경로와 파일명 확장자 결합
			File dstfile = new File(path, "bbb.txt");
			
			//위 만들어진 파일에 저장하기 위해연결하는 oupputStream 만들기
			FileOutputStream fos = new FileOutputStream(dstfile);
			
			//원본파일(aaa.txt)에서 데이터를 1바이트씩 반복적으로 읽어오면서
			//바로바로 목적지파일(bbb.txt)에 1바이트씩 저장
			while (true) {
				byte b = (byte)fis.read();
				if(b == -1) break;
				
				fos.write(b);
			}
			
			//스트림을 통해 write() 찌꺼기 남을 수 있으니 밀어주기
			fos.flush();
			
			//복사 종료 후 스트림 close
			fis.close();
			fos.close();
			
			System.out.println("복사 완료");
			
		} catch (FileNotFoundException e) {
			
			System.out.println("파일이 존재하지않아");
		} catch (IOException e) {
			System.out.println("복사중에 오류 발생");
		}
		
		
	}

}



문자 스트림

char형으로 보낸다 2byte씩 처리
문자열데이터를 한줄씩 또는 한단어씩 읽거나 쓸때 사용한다 기존 바이트스트림 방식은 InputStream을 통해서 몇바이트로 읽어야할지 파악하기 어렵다 그래서 조금 더 편하게 문자열단위로 데이터를 IO를 처리하는 문자스트림 사용 => Reader , Writer

1. FileReder

1) 입력된 문자열을 저장을 위한 File 객체 생성

2) 파일과 연결하는 Stream생성

  • 파일이 없으면 만들고 , 있으면 열기만함

3) 그냥 .write() 를 하게 되면 문자열로 처리하기 번거로움

  • 보조스트림 클래스 (PrintWriter) 사용
  • .println() : 자동 줄바꿈 하면서 등록

4) 스트림 통신 하다 경우에따라선 멈춰 있을 수 있음 스트림버퍼에 찌꺼기가 남아있을 수 있어서 비우도록하는 메서드 => .flush()

5) 스트림 작업이 끝나면 스트림연결 닫는 작업 => .close();


import java.io.*;
import java.util.*;


public class StringIOTest {

	public static void main(String[] args) {
		
		//사용자 입력을 받아 그 데이터를 파일에 지속적으로 저장하는 프로그램
		Scanner sc = new Scanner(System.in);
		
		while (true) {
			
			System.out.print("저장할 단어를 입력하세요 - exit 입력하면 종료 : ");
			String s = sc.next();
			
			if(s.equalsIgnoreCase("exit")) {
				System.out.println("입력 종료");
				break;
			}
			
			//입력된 문자열을 저장을 위한 File 객체 생성
			//목표 위치 : 내 프로젝트 폴더/files/data.txt
			File path = new File("files");
			if(!path.exists()) path.mkdirs(); //exists() 앤 파일까지 검사함 
			
			//경로와 파일명.확장자
			File file = new File(path, "data.txt");
			
			//파일과 연결하는 Stream생성
			//데이터 내보내는것  : outputStream(byte스트림) --> Writer(문자 스트림)
			try {
				//파일이 없으면 만들고 , 있으면 열기만함 
				//덮어쓰기가 기본
				FileWriter fw = new FileWriter(file, true); //append 모드
//				fw.write(s); //즐바꿈문자도 신경써야하고 특정 format으로 문자열을 만들기도 번서로움
//				fw.flush();
//				fw.close();
				
				//System.out.println() . print() 이런기능 메소드는 출력을 편하게 도와줌
				//위 그능처럼 편하게 파일에 데이터를 작성하는(저장하는) 능력의 보조스트림 클래스가 존재
				PrintWriter writer = new PrintWriter(fw); //얘 혼자 못써서 FileWriter fw의 참조변수를 넣어줌
				
				writer.println(s); //자동 줄바꿈 하면서 등록
				
				writer.flush();
				writer.close();
				
			} catch (IOException e) {
				System.out.println("파일 실패");
			}
			
			
		}
		//반복문 종료 -> 입력 완료

		
	}

}



2. FileWriteStream

1) 읽어온 단어들이 여러개 이기에 대량의 데이터를 저장하는 Collection 사용하여 받아오기

2) 파일로 부터 데이터 읽어오기

  • .read() : 한문자를 받아옴 (문자 스트림 / 문자열 스트립이 아님!) 언어마다 바이트수 다름
  • BufferedReader : 모든 데이터를 미리 다 읽어놓고 한줄씩 빼내주는 기능을 가진 보조스트림 활용 (Buffer = 작은 저장공간)
    BufferedReader reader = new BufferedReader(읽어올파일);

3) .readLine() 메서드를 이용하여 데이터 읽어옴

4) 대량의 데이터를 저장하는 arrList에 요소추가(.add()) 후 데이터 출력 (.get())

5) 스트림 닫아주기 작업 📍 필수

import java.io.*;
import java.util.*;


public class StringIOTest {

	public static void main(String[] args) {

		//입력이 잘 되어 있는지 저장된 파일 데이터 읽어오기
		//읽어온 단어들이 여러개 이기에 대량의 데이터를 저장하는 Collection 사용하여 받아오기
		List<String> arrList = new ArrayList<>();
		
		//파일로 부터 데이터 읽어오기
		try {
			FileReader fr = new FileReader("files/data.txt");
			
			//한문자를 받아옴 (문자 스트림 / 문자열 스트립이 아님!) : 영어 1byte 한글 2~3byte 
			//언어마다 바이트 수 다름
			//int a = fr.read(); 
			
			//한 문자씩 읽어오기 귀찮음
			//그래서 모든 데이터를 미리 다 읽어놓고 한줄씩 빼내주는 기능을 가진 보조스트림 활용
			//BufferedReader
			//Buffer = 작은 저장공간
			BufferedReader reader = new BufferedReader(fr);
			
			//한줄씩 나옴 --> 반복문
			//String line = reader.readLine();
			//System.out.println(line); 
			
			while (true) {
				String line = reader.readLine(); // => 줄바꿈 문자는 제외됨
				
				if(line == null) break; //글자가 더이상 없으면 break
				
				System.out.print(line); // => Hellobananaapplr 줄바꿈 문자(엔터아스키번호) 없이 한줄로 나옴
				
				//대량의 데이터를 저장하는 arrList에 요소추가
				arrList.add(line);
			}
			
			System.out.println("단어의 개수 : "+ arrList.size());

			System.out.println(arrList.toString());
			
			for (int i = 0; i < arrList.size(); i++) {
				System.out.println(i + " : " + arrList.get(i));
			}
			
			reader.close();
			
			
		} catch (FileNotFoundException e) {
			System.out.println("파일 없어");
		} catch (IOException e) {
			System.out.println("읽기 과정 중 오류발생");
		}
		
		
		
	}

}
profile
보조기억장치

0개의 댓글