File I/O

2023. 12. 3. 11:07
728x90

: 자바에서 만드는 변수는 한정적이므로 프로그램이 종료되면 사라진다.

입력받고 조작한 데이터를 저장하고 싶다면? 파일로 저장해두어야 한다.! >> File I/O

csv파일 사용 (컴마,를 기준으로 데이터 구분) +  이 데이터를 담을 클래스 만들기.

people.csv                      Data 형식                                                                                        Text 형식                                                     

1. FileReader & FileWriter

: 문자 기반의 파일을 읽어들이는 기본이 되는 클래스

- 파일 이름만 알고 있으면 사용 가능.

- 열고 나서 할 작업을 다 하면 닫아주는게 좋음 (닫지 않으면 자원 소모, 파일 사용불가 등의 사태가 발생한다)

>> 자바 7 이전에는 reader.close()를 직접 해주어야 했다. 

// finally에서 닫아줄 수 있도록 try-catch문 밖에 변수를 선언한다.
FileReader reader = null;

try {
    // 파일을 열어준다.
    reader = new FileReader(filePath);
    // 파일로 작업을 진행한다.
} catch (IOException e) {
    System.out.println(String.format(
        "Exception reading file: %s", e.getMessage()));
} finally {
    if (reader != null) {
        // 닫는 중에도 문제는 발생할 수 있다...
        try {
            reader.close();
        } catch (IOException e) {
            // ...
        }
    }
}

 

>> 자바 7 이후 : 자동으로 닫아줄 수 있는 자원(AutoCloseable)을 만들어준다. (try-with-resources)

// try에서 변수를 선언하고 자동으로 닫을 자원을 만든다. (try-with-resources)
try (FileReader reader = new FileReader(filePath)) {
    // 파일로 작업을 진행한다.
} catch (IOException e) {
    System.out.println(String.format(
        "Exception reading file: %s", e.getMessage()));
}
// 닫아주는 역할만 하던 finally는 필요없다.

 

<FileReader 사용하기>

- FileReader는 한글자씩 파일을 int자료형으로 읽는다.

- 파일 읽을 때 사용하는 메서드는 reader.read()

- reader.read()의 결과가 -1이면 파일의 끝에 도달했다는 뜻. > 종료 조건으로 설

- 개행문자도 직접 읽어서 한줄씩 끊어야 한다... > StringBuilder로 입력을 한줄에 모을 수 있다.

List<Character> charsList = new ArrayList<>();

try (FileReader reader = new FileReader("people.csv")) { // csv파일은 , 기준으로 데이터 구분
	int character;
    StringBuilder line = new StringBuilder(); //입력을 한줄에 모으기.
    while ((character == reader.read()) != -1) { //reader.read()로 파일 읽기 
    // 종료 조건 : read의 결과가 -1이면 파일을 다 읽었다는 뜻임)
    	System.out.print((char) character);
        charsList.add((char) character); //읽은 글자 하나하나 List에 넣어주기.
    }
} catch (IOException e) {
	//예외처리
    System.out.println("파일 읽기 에러");    
}

 

- 만약 Character List가 아니라 Person 클래스 객체에 담고 싶다면...?

public class Person {
    private String name;
    private String email;
    private int age;
    private String gender;
    
    // + 기본생성자, 전체인자 포함 생성자, getter&setter, toString, equals&hashCode

 

요기에 넣어보겠습니다.

List<Person> people = new ArrayList<>();

try (FileReader reader = new FileReader("people.csv")) {
	int character; //현재 파일에서 읽은 문자를 저장할 변수 character를 선언
    StringBuilder line = new StringBuilder();
    while((character == reader.read()) != -1) {
    	if (character == '\n' || character == '\r') { 
        //현재 문자가 개행 ('\n')이거나 캐리지 리턴 ('\r')인지 확인. 이 조건은 한 줄의 끝을 나타냄.
        	String[] values = line.toString().split(","); //컴마 기준으로 나누어 배열에 저장
            people.add(new Person(values[0], values[1], Integer.parseInt(values[2]), values[3]));
            // Person객체로 만들어 list에 저장
            line.setLength(0); //다음 줄을 위해 StringBuilder를 초기화
        } else {
        	line.append((char) character); //현재 문자가 개행이나 캐리지 리턴이 아니면, 현재 줄을 위한 StringBuilder에 문자를 추가
        }
    } 
} catch (IOException e) {
    	//예외처리
        System.out.println("파일 읽기 에러");
}


// 저장이 잘 되었는지 foreach로 확인
for (Person person: people) {
	System.out.println(person);
}

 

<FileWriter 사용하기>

과정은 거의 똑같습니다. 

- 덧붙이기 옵션 : 생성 시 true 조건 걸기 (ex. FileWriter writer = new FileWriter("output.txt", true)))

try (FileWriter writer = new FileWriter("output.txt")) {
	for (Person person: people) {
    	writer.writer(person.toString));
        writer.write("\n");
    	}
} catch (IOException e) {
       System.out.println(e.getMessage());
       System.out.println("파일 쓰기 에러");
}

 

- 만약 csv 형태로 만들고 싶다면? String.format이나 StringBuilder 사용

(반복적인 문자열 작업은 StringBuilder가 효율이 좋음).

try (FileWriter writer = new FileWriter("output.csv")){
    StringBuilder line = new StringBuilder();
    for (Person person : people) {
        line
                .append(person.getName())
                .append(',')
                .append(person.getEmail())
                .append(',')
                .append(person.getAge())
                .append(',')
                .append(person.getGender())
                .append('\n');
        writer.write(line.toString());
        line.setLength(0);
    }
} catch (IOException e) {
    // 예외처리
}

 

 

2. BufferedReader & BufferedWriter

: 버퍼링(한번에 모아서 데이터를 가져오는 기능)을 통해서 실제 하드디스크 읽기/쓰기 작업 횟수를 줄여 더 효율적으로 활용할 수 있다.

- BufferedReader, BufferedWriter 자체는 파일 입출력을 위한 용도가 아닌 Reader와 Writer 클래스에 버퍼링 기능을 제공하는 역할이기 때문에 FileReader&FileWriter가 필요함.

- readLine()으로 한줄씩 읽을 수 있음. 

 

<BufferedReader 사용하기>

try (FileReader fileReader = new FileReader("people.csv"); 
		BufferedReader br = new BufferedReader(fileReader)) {
	String line; 
    while((line = br.readLine()) != null) {
    	String[] values = line.split(",");
        people.add(new Person(values[0], values[1], Integer.parseInt(values[2]), values[3]));
    }
} catch (IOException e) {
	// 예외처리
}

// 확인 foreach
for (Person person:people) {
	System.out.println(person);
}

 

<BufferedWriter 사용하기>

try (FileWriter fileWriter = new FileWriter("output.txt", false); 
	BufferedWriter bw = new BufferedWriter(fileWriter)) {
	for (Person person: people) {
    	bw.wrtie(person.toString());
        bw.newLine(); // bw에는 newLine()메서드 있음. 새로운 라인 추가
    }
} catch (IOException e) {
	//예외처리
}

- csv 형태로 저장하기

try (FileWriter fileWriter = new FileWriter("output.txt", false);
      BufferedWriter writer = new BufferedWriter(fileWriter)) {
    StringBuilder line = new StringBuilder();
    for (Person person : people) {
        line
                .append(person.getName())
                .append(',')
                .append(person.getEmail())
                .append(',')
                .append(person.getAge())
                .append(',')
                .append(person.getGender());
        writer.write(line.toString());
        writer.newLine();
        line.setLength(0);
    }
} catch (IOException e) {
    // 예외처리
}

 

 

 

- 지난번에 배울 때는 아예 이해도 못하고 왜 쓰나~~ 라는 생각을 했는데 

또 배우니 이해가 되긴 된다...! 활용도 그만큼 해보려는 노력을 하자.

1만시간의 법칙 !! 모든 것은 차근차근 해야할 것들을 하다보면 깊어진다. 

728x90

'Programming > Java' 카테고리의 다른 글

프로그래밍을 통한 문제해결  (2) 2023.12.13
String | StringBuffer | StringBuilder  (1) 2023.12.04
Stream API  (1) 2023.11.30
제너릭 (Generics)  (1) 2023.11.29
예외처리 (Exception Handling)  (1) 2023.11.28

BELATED ARTICLES

more