• I/O와 Stream

    File Handling in Java (Java FileReader & FileWriter) With Example -  DataFlair

    • I/O

      • 데이터의 입력(input)과 출력(output)
    • 노드(Node)

      • 입력과 출력의 끝단

      • 키보드, 모니터, 메모리, 파일, 데이터베이스, 네트워크 등

  • 스트림(Stream)

    • 두 노드를 연결하고 데이터를 전송할 수 있는 개념

    • 단방향으로만 통신이 가능하며 하나의 스트림으로 입력과 출력을 같이 처리할 수 없음

    • 바이트 스트림( Byte Stream )

      • binary 데이터를 입출력하는 스트림입니다.

      • 이미지, 동영상 등을 송수신할 때 주로 사용합니다.

      • InputStream / OutputStream

        • byte 기반 input / output stream의 최고 조상
      • ByteArrayInputStream / ByteArrayOutputStream

        • byte array( byte[] )에 대한 데이터를 입출력 하는 클래스
      • FileInputStream / FileOutputStream

        • 파일( File )에 대한 데이터를 입출력 하는 클래스
    • 문자 스트림( Character Stream )

      • 말 그대로 text 데이터를 입출력하는데 사용하는 스트림입니다.

      • HTML 문서, 텍스트 파일을 송수신할 때 주로 사용합니다.

      • Reader / Writer

        • Character 기반 input / output stream의 최고 조상
      • FileReader / FileWriter

        • 문자 기반의 파일을 입출력 하는 클래스
  • 스트림(Stream) 주요 메서드

    • InputStream의 주요 메서드

      • read()

        • 바이트 한 개씩 읽음

        • Buffer만큼 씩 읽음

      • close()

        System.out.println("입력하세요");
        byte[] buffer = new byte[10];
        try(InputStream input = System.in){
          int read = -1;
          while((read = input.read(buffer)) > 0){
              System.out.println("읽은 값: "+read+", 문자열로: "+ new String(buffer, 0, read));
          }
        }catch(IOException e){
          e.printStackTrace();
        }
        //입력값
        자바는 객체지향 언어입니다
        //출력값
        읽은 값: 10, 문자열로: 자바는 객?
        읽은 값: 10, 문자열로: 셉置? 언어
        읽은 값: 8, 문자열로: 입니다
        
      • buffer : 데이터를 한 번에 읽을 수 있기위해 생성한 배열.

      • read(byte[]), read(byte[], int, int) : 버퍼단위로 데이터를 읽음.

      • 한계 : InputStream은 byte단위의 전송때문에 한글자가 2byte이상인 한글은 깨짐 => Reader사용

    • OutputStream의 주요 메서드

      • write()

      • close()

        • 내부적으로 flush()를 호출한다
      • flush()

        • 버퍼가 있는 스트림에서 버퍼의 내용을 출력하고 버퍼를 비운다
        try(Writer wr = new OutputStreamWriter(System.out)){
          String msg = "안녕";
          wr.write(msg);
          wr.append("피곤한").append("월요일");
        }catch(IOException e){
          e.printStackTrace();
        }
        //출력값
        안녕피곤한월요일
        
    • InputStream / OutputStream - ByteArrayStream

        public class IOExample {
            public static void main(String[] args) {
                byte[] src = {0, 1, 2, 3};
                byte[] dest = null;
      
                try{
                    InputStream is = new ByteArrayInputStream(src);
                    OutputStream os = new ByteArrayOutputStream();
      
                    int data = -1;
                    while( (data = is.read()) != -1 ){
                        os.write(data);
                    }
      
                    dest = ((ByteArrayOutputStream)os).toByteArray();
                    System.out.println(Arrays.toString(dest));      // [0, 1, 2, 3]
                }
                catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
      
    • InputStream / OutputStream - FileStream

        public class FileCopy {
            public static void main(String[] args) {
                InputStream is = null;
                OutputStream os = null;
      
                try{
                    // ./는 현재경로를 의미합니다.
                    is = new FileInputStream("./asd.jpg");
                    os = new FileOutputStream("./sad.jpg");
      
                    int data = -1;
                    while( (data = is.read()) != -1 ){
                        os.write(data);
                    }
                }
                catch (FileNotFoundException e){
                    System.out.println("파일 없음");
                    e.printStackTrace();
                }
                catch (IOException e){
                    System.out.println("I/O 에러");
                    e.printStackTrace();
                }
                finally {
                    // 예외가 발생했을 때도 스트림을 닫아야 하므로 finally에서 스트림을 닫아줍니다.
                    try {
                        if( is != null ){
                          is.close();  
                        }
                        if( os != null ){
                            os.close();
                        }
                    }
                    catch ( IOException e){
                        e.printStackTrace();
                    }
                }
            }
        }
      
    • Reader의 주요 메서드

      • read()

        • char 한 개씩 읽음

        • Buffer만큼 씩 읽음

      • close()

        char[] buffer = new char[10];
        try(Reader rd = new InputStreamReader(System.in)){
          int read =-1;
          while((read = rd.read(buffer)) > 0){
              System.out.println("읽은 값: "+read+", 문자열로: "+ new String(buffer, 0, read));
          }
        }catch(IOException e){
          e.printStackTrace();
        }
        //입력값
        자바는 객체지향 언어입니다
        //출력값
        읽은 값: 10, 문자열로: 자바는 객체지향 언
        읽은 값: 6, 문자열로: 어입니다
        
    • Writer의 주요 메서드

      • write()

      • append()

      • close()

      • flush()

        try(Writer wr = new OutputStreamWriter(System.out)){
          String msg = "안녕";
          wr.write(msg);
          wr.append("피곤한").append("월요일");
        }catch(IOException e){
          e.printStackTrace();
        }
        //출력값
        안녕피곤한월요일
        
    • File의 주요 메서드

      • 파일의 수정 불가

      • File()

      • createNewFile()

      • mkdir()

      • mkdirs()

      • delete()

      • getName()

      • getPath()

      • getAbsolutePath()

      • isDirectory()

      • isFile()

      • length()

      • listFiles()

        import java.io.File;
        
        public class MainClass07 {
          public static void main(String[] args) {
              //new File("새로 만들거나 제어하고 싶은 파일이나 폴더의 경로")
              File f = new File("c:/");
              String[] names = f.list();
              //배열에 있는 내용을 반복문 돌면서 콘솔창에 모두 출력할 수 있을까요?
        
              for(int i=0;i<names.length;i++) {
                  String tmp = names[i];
                  System.out.println(tmp);
              }
              System.out.println("확장 for 문을 이용하면");
              for(String tmp:names) {
                  System.out.println(tmp);
              }
          }
        }
        
        import java.io.File;
        
        public class MainClass08 {
          public static void main(String[] args) {
              File cDrive = new File("c:/");
              //c 드라이브에 각각의 폴도나 파일을 제어 할 수 있는 객체의 참조값을 배열로 얻어내기
              File[] files = cDrive.listFiles();
              for(File tmp:files) {
                  //만일 디렉토리라면
                  if(tmp.isDirectory()) {
                      System.out.println("<DIR>\t"+tmp.getName());
                  }else {
                      System.out.println("     \t"+tmp.getName());
                  }
              }
        
          }
        }
        
    • FileReader

        import java.io.File;
        import java.io.FileReader;
        import java.io.IOException;
      
        public class MainClass10 {
            public static void main(String[] args) {
                File memoFile = new File("c:/developer/myFolder/memo.txt");
                try {
                    if(!memoFile.exists()) {
                        System.out.println("파일이 존재하지 않습니다.");
                        return; //메소드 끝내기
                    }
                    //파일에서 문자열을 읽어들일 객체
                    FileReader fr = new FileReader(memoFile);
                    //무한 루프 돌면서
                    while(true) {
                        //글자의 코드값을 하나씩 읽어온다.
                        int code = fr.read();
                        //더이상 읽을게 없다면 반복문 탈출
                        if(code==-1) break;
                        //코드값에 해당하는 char 값 얻어내기
                        char ch = (char) code;
                        //콘솔에 한글자씩 출력하기
                        System.out.print((char)code);
      
                    }
      
                }catch(IOException ie) {
                    ie.printStackTrace();
                }
            }
        }
      
    • FileWriter

        import java.io.File;
        import java.io.FileWriter;
        import java.io.IOException;
      
        public class MainClass09 {
           public static void main(String[] args) {
              //문자열을 저장할 파일을 만들기 위한 File 객체
              File memoFile=new File("c:/developer/myFolder/memo.txt");
      
              try {
                 //파일이 이미 만들어 졌는지 여부
                 boolean isExist=memoFile.exists();
                 if(!isExist) {
                    //파일을 만들어준다.
                    memoFile.createNewFile();
                    System.out.println("memo.txt 파일을 만들었습니다.");
                 }
                 //파일에 문자열을 출력할 수 있는 객체 생성
                 FileWriter fw = new FileWriter(memoFile);
                 fw.write("이00\n");
                 fw.write("\t김00\n");
                 fw.write("\t\t박00");
                 fw.flush();//방출하기
                 fw.close();//닫아주기(마무리)
                 System.out.println("파일에 문자열을 저장했습니다.");
              }catch(IOException ie) {
                 ie.printStackTrace();
              }
      
           }
        }
      
  • 보조 스트림(FilterStream)

    • 다른 스트림에 부가적인 기능을 제공하는 스트림

    • "프로그램에서" 파일을 읽기/쓰기 할 수 있도록 해준다

    • 스트림 체이닝

      • 필요에 따라 여러 보조 스트림을 연결해서 사용 가능
    • FilterInputStream / FilterOutputStream

      • byte 기반 보조 스트림의 최고 조상
    • InputStreamReader / OutputStreamReader

      • byte 기반 스트림을 character 기반 스트림처럼 쓸 수 있도록 함

      • 인코딩 변환 가능

      • 문자열을 관리하기 위해서는 byte 단위보다 char 단위가 유리

      • 키보드에서 입력(byte stream) 받은 데이터를 처리할 경우 등

    • BufferedInputStream / BufferedOutputStream

      • 입출력 효율을 높이기 위해 버퍼( byte[] )를 사용하는 보조스트림
    • BufferedReader / BufferedWriter

      • 입출력 효율을 높이기 위해 버퍼( char[] )를 사용하는 보조스트림

      • 라인 단위의 입출력에 용이

    • ObjectInputStream / ObjectOutputStream

  • 참고 자료