본문 바로가기

프로그래밍/Java

Java_Input/Output 스트림(Stream)

반응형

자바의 입출력을 위한 스트림

: 자바는 다양한 입출력 장치에 독립적으로 일관성 있는 입출력을 입출력 스트림을 통해 제공한다. 
자바 I/O란 데이터를 읽고 쓰는 작업을 말한다.
 

입출력 스트림 구분

대상 기준 입력 스트림 / 출력 스트림
자료의 종류 바이트 스트림 / 문자 스트림 
기능 기반 스트림 / 보조 스트림

 

입력 스트림과 출력 스트림

입력 스트림 : 대상으로부터 자료를 읽어들이는 스트림
출력 스트림 : 대상으로 자료를 출력하는 스트림

 

스트림의 종류

종류 예시
입력 스트림 FileInputStream, FileReader, BufferedInputStream, BufferedReader 등
출력 스트림 FileOutputStream, FileWriter, BufferedOutputStream, BufferedWriter 등

 

바이트 단위 스트림과 문자 단위 스트림

바이트 단위 스트림 : 동영상, 음악 파일, 실행 파일 등의 자료를 읽고 쓸 때 사용
문자 단위 스트림 : 바이트 단위로 자료를 처리하면 문자는 깨짐, 인코딩에 맞게 2바이트 이상으로 처리하도록 구현된 스트림

종류 예시
바이트 스트림 FileInputStream, FileOutputStream, BufferedInputStream, BufferedOutputStream 등
문자 스트림 FileReader, FileWriter, BufferedReader, BufferedWriter 등

 

기반 스트림과 보조 스트림

기반 스트림 : 대상에 직접 자료를 읽고 쓰는 기능의 스트림 
보조 스트림 : 직접 읽고 쓰는 기능은 없이 성능 향상이나 추가적인 기능을 더해주는 스트림
 
 

- FileInputStream 예제

input.txt에 asdf라고 적혀있다는 전제 하에 결과 화면은 다음과 같이 나타난다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package ch02;
 
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
 
public class FileInputStreamTest2 {
 
    // main 함수
    public static void main(String[] args) {
 
        FileInputStream fis = null;
 
        try {
            fis = new FileInputStream("input.txt");
            int data;
            // 마지막에 읽을 값이 없다면 -1을 반환
            System.out.println(">>> 기사 시작 <<<");
            while ((data = fis.read()) != -1) {
                System.out.print((char) data);
            }
            System.out.println("\n>>> 기사 종료 <<<");
 
        } catch (FileNotFoundException e) {
            System.out.println("파일을 찾을 수 없어요.");
        } catch (IOException e) {
            System.out.println("입력 스트림 동작시 오류 발생했어요.");
        } finally {
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
 
    } // end of main
 
// end of class
 
결과 화면
>>> 기사 시작 <<<
asdf
>>> 기사 종료 <<<
cs

 
→ FileInputStream은 바이트 입력 스트림이다. 
→ while문에서 i = fis.read() 의 뜻은 FileInputStream을 읽어온 값을 i에 저장한다는 뜻이고, 
!= -1은 그 값의 마지막에 읽을 값이 없다면 -1을 반환하기 때문에 -1이 아닐 때까지 값을 입력하도록 한 방식이다. 
→ 값을 읽어올 때 (char)로 형 변환을 해서 읽어와야 한다. 
→ 선언부에서 null을 저장하고 초기화 해주는 이유는 선언과 동시에 초기화를 하면 finally문에서 fis.close();가 되지 않기 때문이다. 
 
아 너무 어려운데 ?

- FileInputStream 예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package ch03;
 
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
 
public class FileOutputStream2 {
 
    // main 함수
    public static void main(String[] args) {
 
        FileOutputStream fos = null;
        try {
            byte[] bs = new byte[26];
            byte myData = 65;
            fos = new FileOutputStream("output2.txt");
            // 파일에다가 A - Z 까지 알파벳을 출력하고 싶다면 코드 작성 방법은 ?
            // 반복 횟수 - for
            for (int data = 0; data < bs.length; data++) {
                fos.write(myData);
                myData++;
                // 65 - A, 66 - B
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
 
    } // end of main
 
// end of class
<결과 화면>
ABCDEFGHIJKLMNOPQRSTUVWXYZ
cs

 
→ FileOutputStream은 바이트 기반 출력으로 파일을 생성해주는 스트림이다.
→ 파일에 A - Z 까지 알파벳으로 출력하기 위해 배열을 알파벳 갯수만큼 26개 저장한다. 
→ 바이트 기반 출력 스트림이므로 유니코드 65가 'A'이므로 myData에 65를 저장하고 for문을 이용하여 output2.txt 파일에 출력하였다. 
 
 

- FileReader 예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package ch04;
 
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
 
//FileInputStream, FileOutputStream --> 바이트 기반
// FileReader, FileWriter --> 문자열 기반 
public class FileReaderTest1 {
 
    // main 함수
    public static void main(String[] args) {
 
        // 문자 단위로 읽어들이는 스트림
        FileReader fr = null;
 
        try {
            fr = new FileReader("output2.txt");
            
            int data;
            while ((data = fr.read()) != -1) {
                System.out.print((char) data);
            }
 
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
 
    } // end of main
 
// end of class
cs

 
→ FileReader는 문자열 기반으로 파일을 읽어오는 스트림이다.
→ InputStream은 한글이 깨지지만, FileReader는 한글이 깨지지 않고 파일을 읽어 올 수 있다.
→ while문에서 data = fr.read() 의 뜻은 FileReader를 읽어온 값을 i를 저장하고, 
!= -1은 그 값의 마지막에 읽을 값이 없다면 -1을 반환하기 때문에 -1이 아닐 때까지 값을 읽어오도록 하는 방식이다. 
 
 

FileReader로 파일 읽어와서 FileWriter로 파일 생성하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package ch04;
 
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
 
public class MyArticle {
 
    public static void main(String[] args) {
 
        // 입력 대상 : article1.txt
        // 출력 대상 : today_article.txt
 
        FileReader fr = null;
        FileWriter fw = null;
 
        try {
            fr = new FileReader("article1.txt");
            fw = new FileWriter("today_article.txt");
            
            int data;
 
            fw.write("MCN 뉴스\n");
            while ((data = fr.read()) != -1) {
                fw.write(data);
            }
            fw.write("\n작성자 : 홍길동");
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                fr.close();
                fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
 
    } // end of main
 
}
cs

 
→ FileReader로 article1.txt의 파일을 읽어와서 FileWriter의 today_article.txt에 출력하는 예제이다.
→ FileWriter로 반복문을 이용하여 FileReader파일을 읽어온 후 fw.write(data)를 해주어 today_article.txt 파일에 출력하였다.
 
 
 

보조 스트림(BufferedInputStream, BufferedOutputStream)을 활용하여 성능 높이기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package ch05;
 
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 MainTest3 {
 
    // main 함수
    public static void main(String[] args) {
 
        long milliSecond = 0;
 
        // 1
        FileInputStream fis = null;
        FileOutputStream fos = null;
 
        try {
            fis = new FileInputStream("chapter02.zip");
            fos = new FileOutputStream("chpater02copy.zip");
 
            // 보조 스트림 활용하기 ! (성능 향상을 위해서)
            BufferedInputStream bis = new BufferedInputStream(fis);
            BufferedOutputStream bos = new BufferedOutputStream(fos);
            
            int i;
            milliSecond = System.currentTimeMillis();
            while ((i = bis.read()) != -1) {
                bos.write(i);
            }
            milliSecond = System.currentTimeMillis() - milliSecond;
 
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                fis.close();
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
 
        System.out.println("파일 복사 시 소요시간 : " + milliSecond);
    } // end of main
 
// end of class
cs

 
→ 파일을 읽고 쓸 때 기반 스트림을 바로 쓰는 것보다 보조 스트림을 사용하면 성능이 더 향상된다.
→ 보조 스트림을 생성하고 생성자 안에 매개변수로 기반 스트림의 변수명을 넣어주면 된다.
 
 

DataOutputStream, DataInputStream을 이용하여 데이터 생성하고 읽어오기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package ch06;
 
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 MainTest1 {
 
    // main 함수
    public static void main(String[] args) {
 
        FileOutputStream fos = null;
 
        try {
            fos = new FileOutputStream("data.txt");
            // 보조 기반 스트림 활용
            DataOutputStream dos = new DataOutputStream(fos);
 
            // dos.write(100);
            dos.writeChar('A');
            dos.writeInt(10);
            dos.writeFloat(3.14F);
            dos.writeUTF("TEST UTF8");
            dos.flush(); // 잊지마 !
 
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
 
        FileInputStream fis = null;
 
        try {
            fis = new FileInputStream("data.txt");
            // 보조 스트림 + data
            DataInputStream dis = new DataInputStream(fis);
            
            char a = dis.readChar();
            
            System.out.println(a);
            System.out.println(dis.readInt());
            System.out.println(dis.readFloat());
            System.out.println(dis.readUTF());
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
 
    } // end of main
 
// end of class
 
<결과 화면>
A
10
3.14
TEST UTF8
cs

 
→ DataInputStream은 InputStream을 생성자의 매개변수로 받아 DataInputStream을 생성하고, DataOutputStream은 OuputStream을 생성자의 매개변수로 받아 DataOutputStream을 생성한다.
→ 자료형별 메서드를 가져서 read자료형(), write자료형()을 사용하여 입력하거나 출력할 수 있다.
→ flush()란 출력 버퍼를 비울 때 사용하는데 꼭 사용해주어야 한다.

반응형