Ⅰ. Input/Output
1-1. 입출력(IO)
컴퓨터 내부-외부의 장치와 프로그램이 정보를 주고받는 행위.
자바에서는 입출력을 처리하기 위해 Stream이라는 API를 사용한다. 관련 패키지는 java.io.*
Ⅱ. stream
2-1. Stream
Stream이란?
프로그램이 외부매체와 입출력을 하기 위해 열어준 통로를 말한다.
단방향 통신이기 때문에, 입력과 출력 중 하나의 기능만 한다.
FIFO(First In First Out).
2-2. Stream 종류
2-2-1. 기반스트림
-바이트(1byte) 기반 : input/output 계열 : FileInputStream / FileOutputStream
-문자(2byte) 기반 : Reader/Writer 계열 : FileReader / FileWriter
2-2-2. 보조스트림
//-문자 변환 : InputStreamReader / OutputStreamWriter
-성능 향상 : BufferedInputStream / BufferedOutputStream
-객체 입출력 : ObjectInputStream / ObjectOutputStream (직렬화/역직렬화)
-문자 입력 : BufferedReader, / BufferedWriter
Ⅲ. File 클래스
파일이나 폴더를 만드는 클래스. java.io패키지의 File을 import 해서 사용한다.
3-1. 생성
File file1 = new File("test.txt");
file1.createNewFile();//현재 프로젝트 폴더에 파일 생성
File forder1 = new File("test");
forder1.mkdir();//현재 프로젝트 폴더에 폴더 생성(make directory)
File file2 = new File("C:\\test.txt");
file2.createNewFile();//경로 지정하여 파일 생성
3-2. File 클래스에서 자주 사용하는 method
메소드 | 의미 | 반환형 |
.isFile() | 파일이면 true, 폴더면 false | boolean |
.getName() | 파일 이름 | String |
.getParent | 상위 폴더 | String |
.length() | 파일 용량 | long |
.list() | String[] 배열로 받기 | String[] |
Ⅳ. 기반 스트림
3-1. 바이트 기반 스트림
1byte만 지나갈 수 있는 Stream. 1byte = 8bit
자바는 특별한 경우를 제외하고 Number type은 Sined다.
따라서 바이트 기반 스트림을 통과할 수 있는 크기는 -128~127.
따라서 해당 숫자의 아스키코드 값으로 옮겨진다.
※ 아스키코드
10진수 | 아스키코드 값 | 10진수 | 아스키코드 값 | 10진수 | 아스키코드 값 |
48 | 0 | 65 | A | 97 | a |
49 | 1 | 66 | B | 98 | b |
50 | 2 | 67 | C | 99 | c |
3-1-1. FileOutputStream
파일와 연결 Stream을 만들어 데이터를 출력. 사용이 종료되면 .close()로 자원 반납.
File을 못찾는 경우 예외가 발생하기 때문에 예외처리를 해준다.
FileOutputStream fileOut = new FileOutputStream("test.txt");//직접 경로 입력 가능
파일 생성 | 통로 연결 | |
해당 경로의 파일이 없음 | O | O |
해당 경로의 파일이 있음 | X | O |
- 이어쓰기 옵션
파일에서 출력해도 같은 파일명으로 출력하면 뒤의 내용이 덮어씀. 이어쓰기 옵션으로 파일에 덧붙이기가 가능하다.
FileOutputStream fOut = new FileOutputStream("test.txt",true);//이어쓰기 옵션 true.
fOut.write(65);
fOut.write(97);
//결과 : Aa
- 사용하는 메소드
메소드 | 의미 |
.write() | 1바이트를 출력 |
.flush() | 버퍼 모두 출력. 버퍼 비우기 |
.close() | 자원 반납 후 스트림 닫기 |
※ .write() 메소드의 경우 인자에서 오류날 수 있으므로 IOException 예외처리를 해준다.
※자원반납
그대로 두어도 사용이 종료된 자원은 Garbage Collector가 memory 영역을 돌아다니면서 처리하지만, 메모리의 누수를 야기하기 때문에 사용이 끝난 자원은 반납해주는 편이 매우매우 좋다.
- 방법
1. finally 구문 : 해당 객체를 닫는 .close() 메소드 호출을 예외처리의 finally 구문에 넣어 자원반납 실행.
try{
FileOutputStream fOut=new FileOutputStream("test.txt")
fOut.write(12);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try{
fOut.close();//자원반납 도중 예외가 발생할 수 있으므로 예외처리
} catch (IOException e) {
e.printStackTrace();
}
}
}
2. try with resource : try에 예외가 발생할 수 있는 객체 생성을 넣어 처리. 여러개가 있다면 ;으로 연결하여 기술한다.
try의 {}에서 벗어나면 자동으로 자원반납. JDK 7 버전 이상부터 가능.
try(FileOutputStream fOut=new FileOutputStream("test.txt")){
fOut.write(12);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
3-1-2. FileInputStream
파일에서 프로그램으로 데이터를 입력. 사용이 종료되면 .close()로 자원 반납.
FileInputStream fileIn = new FileInputStream("test.txt");//직접 경로 입력 가능
- 사용하는 메소드
메소드 | 의미 |
.read() | 1바이트를 읽고 해당 값 날리기 |
.close() | 자원 반납 후 스트림 닫기 |
- ※ .read() 값이 비어있으면 -1이 출력된다.
- 사용 로직
FileInputStream fIn = new FileInputStream("test.txt");
int value = 0;
while ((value = fIn.read()) != -1) {//대입으로 .read()한번만 처리
System.out.println(value);
}
4-2. 문자 기반 스트림
2byte까지 지나갈 수 있는 Stream.
4-2-1. FileWriter
2byte가 이동하기 때문에 문자 단위 이동 가능. 이어쓰기 옵션도 가능하다.
try(FileWriter fw =new FileWriter("test.txt")){
char[] ch = { 'a', 'b', 'c', '\n' };
String str = "def";
fw.write(ch);
fw.write(str);//.write()는 오버로딩된 메소드라 여러 자료형 입력 가능
} catch (IOException e) {
e.printStackTrace();
}
- 사용하는 메소드
메소드 | 의미 |
.append() | 뒤에 연결하여 출력 |
.write() | 문자를 출력 |
.flush() | 버퍼 모두 출력. 버퍼 비우기 |
.close() | 자원 반납 후 스트림 닫기 |
4-2-2. FileReader
2byte가 이동하기 때문에 문자 단위 이동 가능.
출력되는 내용은 아스키코드 값으로 나온다. 따라서 변환 과정이 필요하다.
try(FileReader fr = new FileReader("test.txt")){
int value = 0;
while ((value = fr.read()) != -1) {
System.out.print((char)value);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
- 사용하는 메소드
메소드 | 의미 |
.read() | 1바이트를 읽고 해당 값 날리기 |
.close() | 자원 반납 후 스트림 닫기 |
Ⅴ. 보조 스트림
기반 스트림의 부족한 부분을 보조해주는 역할로, 단독 사용은 불가능하다.
바이트 기반 스트림(InputStream / OutputStream)의 보조 스트림은 InputStream / OutputStream,
문자 기반 스트림(Reader / Writer)의 보조 스트림은 Reader / Writer 이 붙어있다.
5-1. Buffer
기반 스트림은 1byte씩 옮겨지면서 지연시간이 생기지만, Buffer 보조 스트림으로 버퍼에 모았다가 한번에 처리.
처리 속도가 향상된다.
5-1-1. BufferedReader
문자로 읽어온다.
- 기반메소드 FileReader 사용 : 파일에서 입력받기
BufferedReader br = new BufferedReader(new FileReader("test.txt"));
- 기반메소드 InputStreamReader 사용 : 사용자에게서 입력받기
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int num = Integer.parseInt(br.readLine());
- 사용 로직
//방법 1. while을 통해서 null 전까지 돌리기
try(BufferedReader br=new BufferedReader(new FileReader("c_buffer.txt"))){
String str=null;
while((str=br.readLine())!=null) {
System.out.println(str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//방법 1-1. while 대신 for문에서 break로 탈출하는 구문 만들기
try (BufferedReader br = new BufferedReader(new FileReader("c_buffer.txt"));) {
for (;;) {
String str = br.readLine();
if (str == null)
break;
System.out.println(str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//방법 2. stream.collect(Collectors.joining(문자열))을 사용
try(BufferedReader br=new BufferedReader(new FileReader("c_buffer.txt"))){
String s=br.lines().collect(Collectors.joining("\n"));//stream 요소들을 joining으로 결합
System.out.println(s);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//방법 2-2. List 인스턴스에 집어넣기. 꺼내먹기
try(BufferedReader br=new BufferedReader(new FileReader("c_buffer.txt"))){
List<String> list = br.lines().collect(Collectors.toList());
//String형 list를 만들고 stream 요소들을 리스트에 하나씩 할당
for(String str:list) {
System.out.println(str);//리스트를 하나씩 출력
}
System.out.println("리스트에 넣으면 이렇게 따로도 사용할 수 있게 됨 : "+list.get(2));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//방법 3. Path 클래스, ArrayList를 이용하여 파일의 내용을 출력하기.
Path path = Paths.get("c_buffer.txt");// Path를 이용하여 해당 파일의 경로를 반환해온다
Charset cs = StandardCharsets.UTF_8;// UTF_8 포멧(지정가능)으로 받아오는 문자셋
List<String> list = new ArrayList<String>();// String형의 ArrayList를 생성
try {
list = Files.readAllLines(path, cs);
// path 경로의 파일을 cs 문자셋으로 리스트에 모든 라인을 받는다.
} catch (IOException e) {// IOException 예외처리(readAllLines에 대한 예외처리)
e.printStackTrace();//오류가 나는 지점의 단계별로 에러를 출력.
}
for (String readLine : list) {//for each문.
System.out.println(readLine);// readLine에 list의 내용물을 하나씩, list의 끝까지 돌린다.
}
}
5-1-2. BufferedWriter
문자로 읽어온다. .newLine()으로 개행 추가 가능.
- 기반 스트림 FileWriter 사용
BufferedWriter bw = new BufferedWriter(new FileWriter("test.txt"));
- 기반 스트림 OutputStream 사용
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
5-1-3. BufferedInputStream / BufferedOutputStream
바이트 기반인 것, 출력에서 .newLine()이 안되는 것을 제외하고는 Reader/Writer 보조스트림과 동일하다.
5-2. Object
객체 단위로 처리.
5-2-1. ObjectOutputStream
객체 단위로 파일에 출력할 수 있게 돕는 보조스트림. 기반 스트림이 OutputStream 계열이므로 바이트 스트림이다.
따라서 객체가 1byte 통로를 통과할 수 있도록 직렬화가 필요하다.
public void saveFile(String fileName){
Student st = new Student("name",22,"운동부");
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(fileName))) {
oos.writeObject(st);// NotSerializableException->Student(model.vo)클래스에 직렬화
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
※ 직렬화란?
방법 : 넘기려는 객체의 클래스에 Serializable 인터페이스를 implements하여 구현.
직렬화를 하면 모든 필드를 byte로 변환한다. transient 키워드를 사용한 필드는 직렬화에서 제외.
public class Student implements Serializable{
//코드들...
}
5-2-2. ObjectInputStream
객체 단위로 읽어들이는 보조 스트림. InputStream임으로 byte단위 이동. 역직렬화가 필요하다.
public void readFile(String fileName) {
try(ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fileName))) {
Student st = (Student) ois.readObject();//역직렬화
System.out.println(ph);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
※ 역직렬화란?
바이트단위로 불러들인 파일을 객체로 복원한다.
Student st = (Student) ois.readObject();//역직렬화
보조스트림의
기본 타입 입출력 : DataInputStream / DataOutputStream (항상 문자형으로 받으므로 다른 타입으로 변환)
-> parse해서 변환하는거랑 비슷한가?
'BACK-END > Java' 카테고리의 다른 글
[JAVA] Sevlet, JSP (1) | 2022.01.16 |
---|---|
[JAVA] API-JDBC (1) | 2021.12.07 |
[Java] API-Collection과 Map (0) | 2021.11.23 |
[Java] API 기초와 java.lang (1) | 2021.11.22 |
[Java] 객체지향의 활용 (0) | 2021.11.21 |