ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java] 기본 입출력 작업
    IT/개발(자바, 서블릿, 스프링 등) 2020. 1. 30. 00:41

    파일 입력

     

    FileInputStream과 FileReader는 생성자의 매개변수로 전달받은 파일로부터 데이터를 읽어오는 입력스트림 역할을 한다.

     

    파일에서 데이터를 읽어오는 메서드 

    • int read(): 한 글자 읽어 정수로 반환
    • int read(byte[] b): 매개변수로 전달받은 바이트 배열의 개수만큼 읽은 후 b 배열에 저장
    • int read(byte[] b, int off, int len): len 개수만큼 읽은 후 b 배열의 off 번지부터 저장

     

    파일 출력

     

    파일로 데이터를 출력하는 기능을 가진 객체는 FileOutputStream과 FileWriter다. 생성자의 매개변수로 전달받은 파일에 데이터를 출력하는 출력스트림 역할을 한다.

     

    예시

     

    fi.read()는 fi 입력스트림에 연결된 a.txt 파일에서 1바이트를 읽어 정수로 반환한다. 예를들어 문자 'A'를 읽었다면 'A' 문자의 코드값인 65를 반환한다. 

     

    파일에는 포인터라는 개념이 있다. 파일 포인터는 파일에서 데이터의 위치를 가리킨다. 프로그램에서 파일을 읽거나 쓸 때 파일 포인터가 가리키는 곳부터 작업을 시작한다. 작업이 끝나면 작업한 만큼 파일 포인터가 이동한다. 초기의 포인터는 시작 지점(첫 글자)에 위치하고, read() 메서드가 실행될 때마다 다음 문자로 이동한다. 모든 문자를 읽으면 파일 포인터는 파일의 끝을 가리킨다. 파일 포인터가 파일 끝을 가리킬 때 fi.read() 메서드를 실행하면 -1을 반환한다. while문으로 fi.read() 메서드가 -1이 아닐 때까지 반복하여 파일의 모든 데이터를 읽어온다.

     

    fo는 b.txt 파일과 연결된 출력스트림이다. fo.write(c) 명령문을 실행하면 인자로 전달한 c 변숫값이 b.txt 파일에 문자로 출력된다. 

     

    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    
    public class Test1 {
    
      public static void main(String[] args) {
        try(FileInputStream fi = new FileInputStream("a.txt"); 
              FileOutputStream fo = new FileOutputStream("b.txt");) {
          int c = 0;
          while((c = fi.read()) != -1) {
            fo.write(c);
          }
    
        } catch(Exception e) {
          e.printStackTrace();
        }
      }
    }

     

    표준 입출력

     

    표준 입출력이란 입출력 대상을 지정하지 않았을 경우 사용되는 입출력 대상을 의미한다. 프로그램에서 표준 입력은 키보드, 표준 출력은 모니터다. 자바 프로그램에서는 키보드와 모니터도 외부로부터 데이터를 입력받고 외부로 데이터를 출력하는 것이므로 입출력 스트림을 사용해야 한다. Java SE API는 키보드와 연결된 표준 입력스트림과 모니터와 연결된 표준 출력스트림을 제공한다.

     

    java.lang 패키지에 포함된 System 클래스의 필드다. 모두 static으로 선언되었으므로 System.in, System.out 형식으로 사용한다.

     

    제어자 및 타입 필드 설명
    static PrintStream err 표준 에러 출력스트림
    static InputStream in 표준 입력스트림
    static PrintStream
    out 표준 출력스트림

     

    System.in은 키보드와 연결된 표준 입력스트림이다. System.out은 모니터 정확히는 콘솔에 연결된 출력스트림이다. 객체를 별도로 생성하지 않고도 바로 사용할 수 있다.

     

    import java.io.InputStream;
    import java.io.OutputStream;
    
    public class Test2{
    	public static void main(String[] args){
        	try(InputStream keyboard = System.in; PrintStream console = System.out;){
            	int c =0;
                while((c = keyboard.read()) != -1){
                	console.write(c);
                }
            }catch(Exception e){
            	e.printStackTrace();
            }
        }
    }

     

    필터 스트림 활용

    java.io의 입출력 스트림들은 '기본 스트림'과 '필터 스트림'으로 분류할 수 있다. 기본 스트림은 읽거나 출력하는 외부 데이터와 직접 연결되는 스트림, 필터 스트림은 외부 데이터와 직접 연결되는 것이 아니라 기본 스트림에 추가로 사용할 수 있는 스트림이다. 기본 스트림인지 필터 스트림인지 생성자를 보면 알 수 있다.

     

    기본 스트림 생성자

    FileReader(String fileName)

    생성자의 매개변수로 파일 이름을 받는다. 즉, 매개변수로 전달받은 파일과 직접 연결되는 스트림이다. 

     

    필터 스트림 생성자

    BufferedReader(Reader in)

    생성자의 매개변수로 입력스트림 타입을 받는다. BufferedReader는 매개변수로 전달받은 Reader 계열의 스트림에 추가로 사용하는 스트림이다. 이런 스트림을 필터 스트림이라고 한다. 외부 데이터와 직접 연결되는 것이 아니므로 독립적으로 사용할 수 없다.

     

    필터스트림을 사용하는 이유는 외부 데이터와 입출력 작업을 할 때 좀 더 편리한 기능을 사용하기 위해서다. 예를들어 FileReader에는 데이터를 읽을 때 read() 메서드로 사용한다. FileReader의 read() 메서드는 한 바이트 또는 인자로 전달한 바이트 배열의 수만큼 읽는다.

     

    필터 스트림인 BufferedReader는 외부 데이터와 프로그램 중간에 버퍼(buffer)라는 것을 사용한다. 버퍼는 외부로부터 일은 데이터가 잠시 저장되는 공간이다. 프로그램에서는 버퍼에 있는 데이터를 읽어오므로 처리 속도도 빠르고 바이트 단위가 아니라 줄 단위로 데이터를 읽을 수 있는 readLine() 메서드를 제공한다. 필터 스트림은 이처럼 편리한 기능을 부가적으로 사용하기 위해 사용한다.

     

    몇가지 예를 더 보자.

     

    계열의 스트림에 DataInputStream을 추가해서 사용할 수 있다.

    DataInputStream(InputStream in) InputStream

     

    PrintWriter는 필터 스트림과 기본 스트림 둘 다 가능하다. 생성자의 매개변수로 OutputStream과 Writer 계열을 받으면 필터 스트림으로 사용되고, 문자열로 받으면 파일 이름으로 처리되어 파일과 직접 연결되는 기본 스트림으로 사용된다.

    PrintWriter(OutStream out)

    PrintWriter(Writer out)

    PrintWriter(String fileName)

     

     

    BufferedReader / BufferedWriter

     

    BufferedReader / BufferedWriter는 Reader 계열과 Writer 계열의 스트림에 추가해서 사용할 수 있는 필터 스트림이다. 외부의 데이터를 읽거나 출력할 때 버퍼를 사용하여 문자를 처리한다는 특징이 있다.

     

     

    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    
    public class Test3 {
    
    	public static void main(String[] args) {
    		try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
    			System.out.println("이름을 입력하세요");
    			String name = br.readLine();
    			System.out.println("Hello " + name);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    }

     

    System.in은 키보드로부터 문자를 읽어들이는 표준 입력장치이다. 키보드로부터 문자를 읽을 때 줄 단위로 읽으려면 BufferedReader의 readLine() 메서드를 사용해야 한다.

     

    그러나 System.in은 BufferedReader의 인자로 사용할 수 없다. BufferedReader는 Reader 타입만 받을 수 있기 때문이다. System.in의 타입은 InputStream이다. 그래서 new InputStreamReader(System.in) 명령문으로 Reader 계열의 System.in을 인자로 전달해 InputStreamReader 객체를 생성한 후 이 객체를 BufferedReader 생성 시 인자로 전달했다. 

     

    readLine() 메서드는 한 줄을 읽어 String 타입으로 반환하는 메서드다.

     

    BufferedInputStream / BufferedOutputStream

     

    BufferedInputStream / BufferedOutputStream은 InputStream과 OutputStream 계열의 스트림에 추가해서 사용할 수 있는 필터 스트림이다. 역시 데이터 입출력시 버퍼를 사용한다.

     

     

    import java.io.BufferedInputStream;
    import java.io.BufferedReader;
    import java.io.ByteArrayOutputStream;
    import java.io.FileInputStream;
    
    public class Test4 {
    
    	public static void main(String[] args) {
    		try (BufferedInputStream in = new BufferedInputStream(new FileInputStream("a.txt"));
    				ByteArrayOutputStream out = new ByteArrayOutputStream();) {
    			byte[] buf = new byte[1024];
    			int len = 0;
    			while ((len = in.read(buf)) != -1) {
    				out.write(buf, 0, len);
    			}
    			byte[] arr = out.toByteArray();
    			String s = new String(arr);
    			System.out.println(s);
    
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    }

     

     

    ByteArrayOutputStream은 바이트 배열에 출력할 수 있는 출력스트림이다. byte[] buf = new byte[1024]; 1024 크기의 바이트 배열 buf를 생성한다.

     

    in.read(buf)는 in 입력스트림에서 buf 배열 크기만큼 읽어들여 buf 배열에 저장한다. len 변수에 in.read() 메서드에서 읽어들인 전체 바이트 수가 저장된다. 만일 더는 읽을 데이터가 없으면 -1이 저장된다.

     

    out.write(buf, 0, len); out은 ByteArrayOutputStream 객체다. 바이트 배열 출력 스트림에 buf에 있는 데이터를 0번지부터 len 개수만큼 출력한다.

     

     

Designed by Tistory.