# I/O 모델
ㄴ I/O란, Input과 Output의 약자로 입출력을 의미한다.
1. I/O 모델의 핵심은 스트림을 이해하는데 있다.
스트림이란 '데이터의 흐름' 또는 '데이터의 흐름을 형성해주는 통로'를 의미한다.
2. 스트림을 2개로 나누면
- 입력스트림(Input Stream) : 프로그램으로 데이터를 읽어 들이는 스트림
- 출력스트림(Output Stream) : 프로그램으로부터 데이터를 내보내는 스트림
3. InputStream 클래스는 바이트 단위로 데이터를 읽어 들이는 모든 입력 스트림이 상속하는 최상위 클래스이다
(Object 클래스 다음으로).
4. 3번 클래스의 대표적인 메소드를 2개 꼽는다면?
public abstract int read() throws IOException
public void close() throws IOException
5. read 메소드는 1바이트의 데이터를 읽어서 반환하는 메소드이다.
6. read 메소드는 더 이상 읽어 들일 데이터가 존재하지 않으면 -1을 반환한다.
7. 입력 스트림의 형성을 위해 정의된 클래스와 출력 스트림의 형성을 위해 정의된 클래스는 서로 쌍(fair)을 이룬다.
InputStream에 대응하는 클래스는 OutputStream이다.
즉, OutputStream은 모든 출력 스트림이 상속하는 최상위 클래스이다.
그리고 FileOutputStream은 이를 상속하는 클래스이다.
8. OutputStream의 대표적인 메소드 둘을 꼽는다면?
public abstract void write(int b) throws IOException
public void close() throws IOException
9. 파일을 1바이트씩 복사하는 프로그램을 짜시오.
그리고 복사된 바이트를 출력하시오.
A. IO의 기본 구조
import java.io.FileNotFoundException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class IOTest9 {
public static void main(String[] args) {
try {
FileInputStream in = new FileInputStream("src.txt");
FileOutputStream out = new FileOutputStream("cpy.txt"); // 해당 파일명으로 복사되어 만들어짐
int r = 0;
while((r = in.read()) != -1) // 매개변수 없이 실행시킴
out.write(r);
in.close();
out.close();
System.out.println("바이트 단위의 파일 복사완료");
} catch(FileNotFoundException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}
}
}
10. 1KB 정도되는 byte 배열을 생성해서 1KB 단위의 복사를 진행해 보려고 한다.
그 때 필요한 InputStream의 메소드는 아래와 같다.
public int read(byte[] b) throws IOException
이 메소드의 인자로는 byte형 배열의 참조를 전달한다.
그러면 입력 스트림을 통해서 읽어 들여진 데이터들이 배열에 저장된다.
그리고 위 메소드는 실제 읽어 들인 데이터의 크기를 반환한다.
더 이상 읽을 데이터가 존재하지 않으면 -1이 반환된다.
11. 1KB 단위의 복사를 진행하려면 OutputStream 클래스의 어떤 메소드를 사용하나?
public void write(byte[] b, int off, int len) throws IOException
위 메소드는 매개변수 b로 전달된 배열을 대상으로
off의 인덱스 위치서부터 시작해서 len 바이트를 출력 스트림을 통해서 전송하는 메소드이다.
12. 1KB 단위로 복사하는 파일 복사 프로그램을 완성하시오.
그리고 복사된 바이트를 출력하시오.
A. 파일 크기가 더 큰 경우
import java.io.FileNotFoundException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class IOTest9 {
public static void main(String[] args) {
byte[] r = new byte[1024];
int len = 0;
try {
FileInputStream in = new FileInputStream("eclipse-inst-win64.txt");
FileOutputStream out = new FileOutputStream("eclipse-inst-win64_cpy.txt");
while((len = in.read(r)) != -1)
out.write(r, 0, len);
in.close();
out.close();
System.out.println("바이트 배열 단위의 파일 복사가 완료되었습니다.");
} catch(FileNotFoundException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}
}
}
ex) 복사된 바이트 크기를 알고 싶을 때
import java.io.FileNotFoundException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class IOTest9 {
public static void main(String[] args) {
byte[] r = new byte[1024];
int len = 0, total =0;
try {
FileInputStream in = new FileInputStream("eclipse-inst-win64.txt");
FileOutputStream out = new FileOutputStream("eclipse-inst-win64_cpy.txt");
while((len = in.read(r)) != -1)
total +=len;
out.write(r, 0, len);
in.close();
out.close();
System.out.println(total + "바이트 배열 단위의 파일 복사가 완료되었습니다.");
} catch(FileNotFoundException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}
}
}
13. 필터 스트림은 그 자체로 파일과 같은 소스로부터 데이터를 읽는 기능을 지니고 있지 않다.
다만 입력 스트림으로부터 읽혀진 데이터를 다양하게 가공하는 기능만 있을 뿐이다.
이러한 필터 스트림도 다음과 같이 두 부류로 나뉜다.
- 필터 입력 스트림 : 입력 스트림에 연결하는 필터 스트림
- 필터 출력 스트림 : 출력 스트림에 연결하는 필터 스트림
14. int, double과 같은 기본 자료형 데이터를 읽고 쓰는 게 생각만큼 간단한 일은 아니지만,
필터 스트림인 DataInputStream과 DataOutputStream을
각각 입력 스트림과 출력 스트림에 연결하면,
기본 자료형 데이터의 입출력을 간단하게 할 수 있다.
15. 정수 275와 실수 45.79를 파일에 저장하고 다시 읽어들여 출력해보자.
A.
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class JavaIO15 {
public static void main(String[] args) {
FileOutputStream out;
DataOutputStream dataOut;
FileInputStream in;
DataInputStream dataIn;
String fileName="data.txt";
try
{
out = new FileOutputStream(fileName);
dataOut = new DataOutputStream(out);
dataOut.writeInt(275);
dataOut.writeDouble(45.79);
dataOut.close();
in = new FileInputStream(fileName);
dataIn = new DataInputStream(in);
int dataInt = dataIn.readInt();
double dataDouble = dataIn.readDouble();
System.out.println(dataInt + " " + dataDouble);
dataIn.close();
}
catch(FileNotFoundException e)
{
e.printStackTrace();
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
16. 필터 스트림은 다음 클래스를 상속한다.
- 필터 입력 스트림 클래스 : FilterInputStream 클래스를 상속한다.
- 필터 출력 스트림 클래스 : FilterOutputStream 클래스를 상속한다.
FilterInputStream 클래스와 FilterOutputStream 클래스도
각각 InputStream과 OutputStream을 상속하나, 최상위 클래스는 아니다.
17. 버퍼링 기능을 제공하는 필터 스트림
- BufferedInputStream : 버퍼 필터 입력 스트림
- BufferedOutputStream : 버퍼 필터 출력 스트림
//Tip : 벽돌 한장씩 옮기는 것보다 벽돌을 나르는 손수레가 있다면 훨씬 빠르듯이
버퍼 스트림을 연결하게 되면 속도가 크게 향상된다.
18. 버퍼 필터 스트림을 이용하여 파일 복사하는 프로그램 작성하고, 복사된 바이트도 출력해보자.
A.
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class JavaIO18 {
public static void main(String[] args) {
String inFileName = "org.txt";
String outFileName = "cpy.txt";
FileInputStream in;
BufferedInputStream bIn;
FileOutputStream out;
BufferedOutputStream bOut;
int readByte = 0;
int byteCnt = 0;
try
{
in = new FileInputStream(inFileName);
bIn = new BufferedInputStream(in);
out = new FileOutputStream(outFileName); // FileOutputStream이 가장 마지막 순서!
bOut = new BufferedOutputStream(out);
while( (readByte=bIn.read()) != -1)
{
bOut.write(readByte); // 버퍼를 연결시켰기 때문에 속도가 빨라진다.
byteCnt++;
}
bIn.close();
bOut.close();
System.out.println(byteCnt+ "byte의 파일 복사가 완료되었습니다.");
}
catch(FileNotFoundException e)
{
System.out.println("파일이 존재하지 않습니다.");
e.printStackTrace();
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
위 예제에서는 버퍼의 크기를 지정하지 않았기 때문에
디폴트 크기의 버퍼(디폴트 크기는 2MB이다)가 만들어지지만,
다음의 생성자들을 이용하면 버퍼의 크기도 원하는 대로 지정할 수 있다.
public BufferedInputStream(InputStream in, int size)
public BufferedOutputStream(OuputStream out, int size)
// Tip : 최종적으로 연결된 곳만 close 메소드를 호출하게 되면
자동적으로 다른 곳도 close 메소드가 호출되어 리소스가 해제된다.
19. BufferedInputStream 데이터를 읽어 들이는 메소드 두개는?
public int read() throws IOException
public int read(byte[] b, int off, int len) throws IOException
20. 데이터의 중요도가 높거나, 버퍼가 꽉차지 않아도
출력 스트림을 통해서 파일에 저장해야 할 데이터가 존재한다면 다음의 메소드를 호출해야 한다.
public void flush() throws IOException
21. 파일에 275와 45.79를 저장하는데, 버퍼링 기능도 추가하자.
그리고 다시 저장한 것을 읽어 들이자.
A. ex) 호스 - 필터 - 샤워헤드
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class JavaIO21 {
public static void main(String[] args) {
String fileName="fbdTest.txt";
FileOutputStream out = null;
FileInputStream in = null;
BufferedOutputStream bOut = null;
BufferedInputStream bIn = null;
DataInputStream dataIn = null;
DataOutputStream dataOut = null;
int intData = 0;
double dblData = 0;
try
{
out = new FileOutputStream(fileName);
bOut = new BufferedOutputStream(out);
dataOut = new DataOutputStream(bOut);
dataOut.writeInt(275);
dataOut.writeDouble(45.79);
dataOut.close();
in = new FileInputStream(fileName);
bIn = new BufferedInputStream(in);
dataIn = new DataInputStream(bIn);
intData = dataIn.readInt();
dblData = dataIn.readDouble();
System.out.println(intData + " " + dblData);
dataIn.close();
dataOut.close();
}
catch(FileNotFoundException e)
{
System.out.println("파일이 존재하지 않습니다.");
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
22. 성능차이를 체크해보자.
처음에는 12.345를 중첩된 반복문 10000 번씩을 통해 저장하고,
두 번째로는 같은 동작을 하는데 버퍼링 필터 스트림이 추가된 상태로 체크해보자.
그래서 두 개의 성능차이를 비교해보자.
import java.io.*;
class DataBufferedFilterPerformance
{
public static void performanceTest(DataOutputStream dataOut) throws IOException
{
long startTime=System.currentTimeMillis();
for(int i=0; i<10000; i++)
for(int j=0; j<10000; j++)
dataOut.writeDouble(12.345);
dataOut.flush();
long endTime=System.currentTimeMillis();
System.out.println("경과시간: "+ (endTime-startTime));
}
public static void main(String[] args) throws IOException
{
OutputStream out1=new FileOutputStream("data1.bin");
DataOutputStream dataOut=new DataOutputStream(out1);
performanceTest(dataOut);
dataOut.close();
OutputStream out2=new FileOutputStream("data2.bin");
BufferedOutputStream bufFilterOut
=new BufferedOutputStream(out2, 1024*10);
DataOutputStream dataBufOut=new DataOutputStream(bufFilterOut);
performanceTest(dataBufOut);
dataBufOut.close();
}
}
+ 개별문제
Q. 파일 내 int형 데이터를 1부터 100까지 더하여 저장해보시오.
A.
package practice0718;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class WriteInt {
public static void main(String[] args) {
try {
FileOutputStream out = new FileOutputStream("NG.txt");
DataOutputStream dataOut = new DataOutputStream(out);
for(int i=1; i<=100; i++) {
dataOut.writeInt(i);
}
dataOut.close();
FileInputStream in = new FileInputStream("NG.txt");
DataInputStream dataIn = new DataInputStream(in);
int sum = 0;
for(int i = 0; i<100; i++) {
int dataInt = dataIn.readInt();
sum += dataInt;
}
dataIn.close();
System.out.println("sum : " + sum);
} catch(FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
'SW > Java' 카테고리의 다른 글
[필기정리] Day25 - IO 모델 셀프 핵심정리 (0) | 2020.07.14 |
---|---|
[필기정리]Day25 - I/O모델 문제 (0) | 2020.07.14 |
[필기정리]Day23 - 컬렉션 프레임워크 문제 (0) | 2020.07.10 |
[필기정리]Day22 - 문제 전화번호부 단계 7 (0) | 2020.07.09 |
[필기정리]Day22 - 컬렉션 프레임워크 (0) | 2020.07.09 |