자바에서의 입출력, I/O

2023. 3. 28. 10:17Lang/Java

728x90
반응형

1. 자바에서의 입출력

  • I/O (input, output)
    • 컴퓨터 내부 또는 외부의 장치와 프로그램 간의 데이터를 주고받는 것
    • System.our.println 등
  • Stream
    • 입출력, 즉 어느 한쪽에서 다른쪽으로 데이터를 전달
    • 두 대상을 연결하고 데이터를 전송할 수 있는 통로 = 스트림
    • 단방향 통신만 가능
    • 하나의 스트림으로 입력과 출력을 동시에 할 수 없다

      데이터 소스 - 입력스트림 - 자바프로그램 - 출력스트림 - 데이터목적지

스트림의 구분

  • 다루는 데이터에 따라
    • byte 기반 스트림 (1byte 단위로 데이터 이동)
      • InputStream / OutputStream
    • 문자(char)기반 스트림 (2byte단위로 데이터 이동)
      • Reader / Writer
  • 데이터 가공에 따라
    • Node 스트림
      • 데이터 소스와 직접 연결 가능한 스트림
    • Filter 스트림
      • 데이터 소스에 직접 연결 불가
      • 노드스트림을 가공하는 역할
      • 스트림의 기능을 보완하기 위한 보조스트림
      • 노드스트림과 연결해서 써야한다
        구분

2. 바이트 기반 스트림

바이트기반스트림

  • 스트림은 바이트 단위로 데이터를 전송한다
  • inputStream, OutputStream의 자손클래스들 보유
  • 읽고 쓰는데 필요한 추상메서드를 자신에 맞게 구현
  • flush()
    • 버퍼가 있는 출력스트림의 경우에만 의미가 있으며, outputStram에 저장된 flush()는 아무런 일도 하지 않는다
  • 프로그램이 종료될 때. 사용하고 닫지 않은 스트림을 jvm이 자동적으로 닫아준다
    • 권장 : 작업을 마친후 close()를 호출해 반드시 닫아준다
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class iotest1 {

    public static void main(String[] args) {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream("text/poetry2.txt");
            int data = 0;

            //int read() throws IOException
            // - inputStream 에서 1바이트씩 읽어온다
            // - 아스키코드를 리턴한다
            // - 더이상 읽어올 것이 없으면 -1을 리턴한다

            while((data=fis.read())!=-1) {
                char ch = (char)data;
                System.out.println(ch);//char 단위로 출력
        //1바이트씩 읽어오지만, 한글은 2바이트라 한글은 깨진다
                //System.out.println(data); //아스키코드 출력
            }

        } catch (FileNotFoundException e) {

            e.printStackTrace();
        } catch (IOException e) {

            e.printStackTrace();
        }finally {
            try {
                if(fis!=null) fis.close();
            }catch(IOException e) {
                e.printStackTrace();
            }
        }


    }

}

InputStream

인풋스트림

package com.io.day1;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class InputStream {

    public static void main(String[] args) {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream("text/poetry2.txt");
            int data = 0, count = 0;
            while((data=fis.read())!=-1) {
                char ch = (char)data;
                System.out.println(ch);
                count++;
            }
            System.out.println("반복횟수:"+count);
            File file = new File("text/poetry2.txt");
            System.out.println("파일의 바이트수 : " +file.length());
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            if(fis!=null)
                try {
                    fis.close();
                }catch(IOException e) {
                    e.printStackTrace();
                }
        }

    }

}

OutputStream

아웃풋스트림

package com.io.day1;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class OutputTest {

    public static void main(String[] args) {
        //파일에서 읽어서 파일로 출력, 바이트 기반
        /*
             입력 : FileInputStream
             출력 : FileOutputStream
         */

        FileInputStream fis = null;
        FileOutputStream fos = null;

        try {
            fis = new FileInputStream("text/poetry2.txt");
            fos = new FileOutputStream("text/poetry2.bak");

            int data = 0;
            while((data=fis.read())!=-1) {
                fos.write(data); //1바이트씩 출력
                //void write(int b) : 바이트 단위로 출력
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            try {
                if(fis!=null) fis.close();
                if(fos!=null) fos.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}
package com.io.day1;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class OutputTest2 {

    public static void main(String[] args) {
        FileInputStream fis = null;
        FileOutputStream fos = null;

        try {
            fis = new FileInputStream("text/poetry4.txt");
            fos = new FileOutputStream("text/poetry4.bak");

            int cnt = 0, count = 0, total = 0;
            byte[] buf = new byte[1024];
            while ((cnt=fis.read(buf))!=-1) { //inputStream에서 읽어서 byte배열에 넣는다
                System.out.write(buf,0,cnt); //바이트배열에서 시작위치 0에서 cnt개만큼 출력
                //buf배열에서 0부터 cnt개 읽어 출력소스에 쓴다
                fos.write(buf,0,cnt);

                System.out.println("cnt : "+cnt);
                total+=cnt;//1024+1009
                count++; //1
                System.out.println("total : "+total);
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}

3. 바이트기반 보조 스트림

  • 스트림의 기능을 보완하기 위한 보조스트림
  • 데이터를 입출력할 수 있는 기능이 없다
  • 스트림을 먼저 생성한 후 이를 이용해 보조스트림 생성

    데이터 소스 - 입력스트림 - 보조스트림(필터스트림) - 자바프로그램
    자바프로그램 - 보조스트림(필터스트림) - 출력스트림 - 데이터 목적지

보조스트림

  • Filter i/o Stream의 자손클래스들

Buffered I/O Stream

  • 스트림의 입출력 효율을 높이기 위해 버퍼를 사용하는 보조스트림
  • 한바이트씩 입력하는 거보다 버퍼를 이용해 한번에 여러 바이트를 입출력하는 것이 빠르다
  • BufferedInputStream (InputStream in, int size)
    • 주어진 in을 입력소스로 하며, 지정된 크기의 버퍼를 갖는 인스턴스를 생성
    • 사이즈의 기본값은 2048byte
    • 버퍼의 크기는 입력소스로부터 한번에 가져올 수 있는 데이터의 크기가 좋다
    • read() 호출시 소스로부터 버퍼크기만큼 데이터를 읽어 자신의 내부버퍼에 저장
    • 프로그램에서는 bufferedinputstream의 버퍼에 저장된 데이터를 읽는다
    • 외부가 아닌, 내부버퍼로부터 읽기 때문에 속도가 빠르다
  • BufferedOutputStream (OutputStream out, int size)
    • flush() : 버퍼의 모든 내용을 출력소스에 출력한 다음, 버퍼를 비운다
    • close() : flush()를 호출해 출력한 후 인스턴스가 사용하던 자원을 반환
    • write를 이용한 출력이 bufferedOutputStream의 버퍼에 저장된다
    • 버퍼가 가듣차면 그 때 버퍼의 모든 내용을 출력소스에 출력한다
    • 버퍼를 비우고 다시 프로그램의 출력을 저장할 준비를 한다
    • 가득찼을 때만 출력소스에 출력하기 때문에, close나 flush를 이용해야한다
package com.io.day2;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class BufferdTest1 {

    public static void main(String[] args) {
        /*
         *파일에서 데이터를 읽어와서 화면출력 - 보조스트림 이용, 바이트 기반
         * 
         */
        FileInputStream fis = null;
        BufferedInputStream bis = null;

        try {
            fis=new FileInputStream("text/poetry2.txt");
            bis = new BufferedInputStream(fis,1024);

            int data = 0;
            while((data=bis.read())!=-1) {
                System.out.println((char)data);
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                if(bis!=null) bis.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}
package com.io.day2;

import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class BufferedOutTest {

    public static void main(String[] args) {
        //파일 123.txt에 1부터 9까지 출력, 바이트기반, 버퍼이용
        /*
         * FileOutputStream
         * BufferedOutputStream
         */
        FileOutputStream fos = null;
        BufferedOutputStream bos = null;

        try {
            fos = new FileOutputStream("text/123.txt");
            bos = new BufferedOutputStream(fos, 5); //버퍼크기 5

            for(int i='1' ; i<= '9' ; i++) {
                bos.write(i);
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                bos.close(); //fos.close로 닫을 시 12345만 출력
                // 버퍼가 가득차야 출력하기 때문에, 12345 이후
                // 6789는 버퍼가 가득차지않아 출력핮 않는다
                //bos로 닫으며 버퍼에 남아있는 나머지 6789를 출력

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        System.out.println("파일저장");
    }

}

Data I/O Stream

  • byte가 아닌, 기본자료형의 단위로 읽고 쓸 수 있다
  • 각 기본자료형 값을 16진수로 표현하여 저장
    • int 값을 출력한다면 4byte의 16진수로 출력
  • 캡처
  • 캡처2
package com.io.day2;

import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class DataOutputTest {

    public static void main(String[] args) {
        // 파일에 출력, 기본자료형 단위로, 바이트기반
        // FileOutStream
        // DataOutputStream

        FileOutputStream fos = null;
        DataOutputStream dos = null;

        try {
            fos = new FileOutputStream("text/sample.dat");
            dos = new DataOutputStream(fos);

            dos.writeInt(20); //4byte
            dos.writeFloat(30.0f); //4byte
            dos.writeBoolean(true); //1byte
            dos.writeChar('A'); //2b
            dos.writeLong(123); //8b
            dos.writeUTF("Hello"); //유니코드의 utf-8형식으로 문자열을 출력
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                if(dos!=null) dos.close();
            }catch(IOException e) {
                e.printStackTrace();
            }
        }
        // 2진 데이타로 저장
        System.out.println("저장완료");

    }

}
package com.io.day2;

import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class DataInputTest {

    public static void main(String[] args) {
        FileInputStream fis = null;
        DataInputStream dis = null;

        try {
            fis = new FileInputStream("text/sample.dat");
            dis = new DataInputStream(fis);

            System.out.println(dis.readInt());
            System.out.println(dis.readFloat());
            System.out.println(dis.readBoolean());
            System.out.println(dis.readChar());
            System.out.println(dis.readLong()); //저장순서로 읽어온다

            String str = dis.readUTF();
            System.out.println(str);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                if(dis!=null) dis.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}
  • EOFException 활용
package com.io.day2;

import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class DataOutputTest2 {

    public static void main(String[] args) {
        int [] score = {99,85,77,62,50,100};

        FileOutputStream fos = null;
        DataOutputStream dos = null;

        try {
            fos = new FileOutputStream("text/score.dat");
            dos = new DataOutputStream(fos);

            for (int i=0; i<score.length; i++) {
                dos.writeInt(score[i]);
            }
        } catch (FileNotFoundException e) {

            e.printStackTrace();
        } catch (IOException e) {

            e.printStackTrace();
        } finally {
            try {
                if(dos!=null) dos.close();
            } catch (IOException e) {

                e.printStackTrace();
            }
        }
        System.out.println("저장");
    }

}
package com.io.day2;

import java.io.DataInputStream;
import java.io.EOFException;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class DataInputTest2 {

    public static void main(String[] args) {
        FileInputStream fis = null;
        DataInputStream dis = null;

        int sum = 0;
        try {
            fis = new FileInputStream("text/score.dat");
            dis = new DataInputStream(fis);

            while(true) {
                int score = dis.readInt();
                System.out.println(score + "\t");

                sum+=score;
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }catch(EOFException e) {
            System.out.println("점수 총합 : "+ sum);
            //readInt()와 같이 데이터를 읽는 메서드는
            //읽을 데이터가 업으면 EOFException을 발새시킨다

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 

    }

}

4. 문자 기반 스트림

  • 문자 데이터를 다루는데 사용
  • 여러 종류의 인코딩과 자바에서 사용하는 유니코드간의 변환을 자동으로 처리
    • Reader : 특정 인코딩을 읽어 유니코드로 변환
    • Writer : 유니코드를 특정 인코딩으로 변환하여 저장
  • Reader, Writer
    • 문자 기반 스트림의 조상클래스
    • byte 대신 char배열을 이용하는것 외에는 바이트기반과 동일

      FileReader, FileWriter

      package com.io.day2;
      

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class ReaderTest1 {

public static void main(String[] args) {
    String fileName = "text/test.txt";
    FileInputStream fis = null;

    int data = 0;
    try {
        fis = new FileInputStream(fileName);
        while((data=fis.read())!=-1) {
            System.out.print((char)data);
        }
    }catch (FileNotFoundException e) {
        e.printStackTrace();
    }catch (IOException e) {
        e.printStackTrace();
    }finally {
        try {
            if(fis!=null) fis.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    System.out.println("\n==문자기반==");

    FileReader fr = null;

    try {
        fr = new FileReader(fileName);

        while((data=fr.read())!=-1) {
            System.out.print((char)data);
        }

    }catch(FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block

    }finally {
        try {
            if(fr!=null) fr.close();
        } catch (IOException e) {

            e.printStackTrace();
        }
    }
}

}


- reader, writer   

```java
package com.io.day2;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class WriterTest1 {

    public static void main(String[] args) {
        //문자기반, 파일에서 읽어서 파일에 출력
        // FileReader
        // FileWriter

        FileReader fr = null;
        FileWriter fw = null;

        try {
            fr = new FileReader("text/poetry.txt");
            fw = new FileWriter("text/poetry.bak");

            int data = 0;
            while((data=fr.read())!=-1) {
                fw.write(data);
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                if(fr!=null) fr.close();
                if(fw!=null) fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("저장");

        FileReader fr2 = null;
        FileWriter fw2 = null;
        try {
            fr2 = new FileReader("text/poetry4.txt");
            fw2 = new FileWriter("text/poetry4.bak");

            char[] buf = new char[1024];
            int cnt = 0;
            while((cnt=fr2.read(buf))!=-1) {
                fw2.write(buf,0,cnt);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            try {
                if(fr2!=null) fr2.close();
                if(fw2!=null) fw2.close();
            } catch (IOException e) {

                e.printStackTrace();
            }
        }
    }

}

5. 문자기반 보조스트림

BufferedReader / BufferedWriter

  • 버퍼를 이용해 입출력 효율 증가
  • Reader 의 readLine()을 사용하면 데이터를 라인단위로 읽어올 수 있다
  • Writer의 newLine() : 줄바꿈 메서드
package com.io.day2;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class BufferedTest {

    public static void main(String[] args) {
        // 문자단위, 파일에서 읽어서 화면 출력, 버퍼이용
        // FileReader
        // BufferedReader
        String fileName = "text/WriterTest1.java";

        BufferedReader br = null;
        try {
            FileReader fr = new FileReader(fileName);
            br = new BufferedReader(fr);

            int data = 0;
            while((data=br.read())!=-1) { //문자 하나씩 읽어온다
                System.out.print((char)data);
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                if(br!=null) br.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        System.out.println("\n\n==============");
        FileReader fr;
        try {
            fr = new FileReader(fileName);
            br = new BufferedReader(fr);

            String line = "";
            while((line = br.readLine())!=null) { //한줄씩 입력
                System.out.print(line+"\n");
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                if(br!=null) br.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}

InputStreamReader / OutputStreamWriter

  • 바이트 기반 스트림을 문자기반 스트림으로 연결
  • 바이트기반 스트림의 데이터를 지정된 인코딩의 문자데이터로 변환
  • 한글 윈도우에서 중국어로 작성된 파일을 읽을 때
    • 일반적인 사용으론 파일이 깨진다
    • InputStreamReader (InputStream in, String encoding)
    • 인코딩이 중국어임을 지정
  • os에서 사용하는 인코딩의 종류 확인

    Properties prop = System.getProperties();
    System.out.println(prop.get("sun.jnu.encoding"));

캡처
캡처2

  • 기본
    package com.io.day2;
    

import java.io.IOException;

public class ReadTest {

public static void main(String[] args) {
    System.out.println("문자 입력");

    try {
        int data=0;
        //키보드로부터 입력받은 값 출력
        while((data = System.in.read())!=-1) { //1바이트씩 읽어옴
            System.out.println(data + ", char = " + (char)data); //한글은 2바이트라 깨져서 나온다
        }
    }catch(IOException e) {
        e.printStackTrace();
    }
}

}


```java
package com.io.day2;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class InReaderTest {

    public static void main(String[] args) {
        InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader br = null;

        br = new BufferedReader(isr);
        System.out.println("사용중인 os의 인코딩 : "+isr.getEncoding());

        System.out.println("\n문장 입력!");
        String line = "";
        try {
            while((line=br.readLine())!=null) {
                System.out.println("입력한 문장 : "+line);
            }
        }catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if(br!=null) br.close();
            }catch(IOException e) { 
                e.printStackTrace();
            }
        }
        System.out.println("종료");
    }

}

6. 비교

비교1
비교2

728x90
반응형

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

자바, 네트워크  (0) 2023.03.28
쓰레드의 동기화  (0) 2023.03.28
Swing, Jtable  (1) 2023.03.28
AWT - 이벤트처리  (0) 2023.03.28
AWT - 레이아웃 매니저  (0) 2023.03.28