File I/O
: 자바에서 만드는 변수는 한정적이므로 프로그램이 종료되면 사라진다.
입력받고 조작한 데이터를 저장하고 싶다면? 파일로 저장해두어야 한다.! >> File I/O
csv파일 사용 (컴마,를 기준으로 데이터 구분) + 이 데이터를 담을 클래스 만들기.
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만시간의 법칙 !! 모든 것은 차근차근 해야할 것들을 하다보면 깊어진다.
'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 |