점프투자바

SUADI·2022년 5월 17일

6. 입출력

(1) 콘솔 입출력

ㄱ) 콘솔

콘솔이란 사용자에게 입력을 받거나 사용자에게 문자열 등을 출력해주는 역할을 통칭하는 말이다.

ㄴ) 콘솔 입력

J2SE 5.0 버전 이후로 java.util.Scanner 라는 클래스가 생성되어서 이전의 콘솔 입력보다 쉽게 처리할 수 있다. 점프투자바를공부하기 전에는 입력 방법이 Scanner 클래스를 이용하는 방법 하나 밖에 없는줄 알았는데 다른 방법이 있다는 사실을 알게 되었다. 쉬운 방법이 있는데 두가지를 모두 알아야 하는지는 아직 판단이 안되지만 두가지 모두 공부하도록 하겠다.

* 스트림(Stream)

프로그램은 외부로부터 데이터를 입력받거나 외부로 데이터를 출력하는 작업이 빈번하게 일어난다. 이 때 데이터는 어떠한 통로를 통해 이동하게 되는데, 이 통로를 스트림이라고 한다. 자바에는 이러한 기능을 수행하기 위해 InputStream과 OutputStream이 존재하며 단일 방향으로 연속적으로 흘러간다.

* 인풋스트림(InputStream)

InputStream이란 바이트(byte) 기반 입력스트림의 최상위 추상 클래스(abstract class)이다. 모든 바이트 기반 입력스트림은 InputStream을 상속받는다. InputStream은 파일 데이터를 읽거나 키보드에서 입력한 데이터를 읽을 때 사용된다.

import java.io.IOException;
import java.io.InputStream;

public class Sample {
    public static void main(String[] args) throws IOException {
        InputStream in = System.in;

        int a = in.read();

        System.out.println(a);
    }
}
  • InputStream 클래스는 자바의 내장클래스이다. 자바의 내장 클래스 중에 java.lang 패키지에 속해 있지 않은 클래스는 모두 import해서 사용해야만 한다. 자바에서 기본적으로 제공하는 I/O 기능은 java.io 패키지에서 제공된다.
  • System.in은 InputStream의 객체이다. System.in을 통해 키보드로부터 데이터를 입력받는데 잘못된 데이터가 입력되는 것을 방지하기 위해 예외처리를 꼭 해주어야 한다. 예외처리를 하지 않으면 에러가 난다. java.io 패키지 내의 IOException 클래스를 import해와서 main 메소드에 IOException(입출력 예외)를 throws를 이용해서 예외처리를 했다. 전에 학습했을때 100% 이해하지는 못했지만 throws는 예외를 뒤로 미루는 방법이다.
  • 정수형 타입의 변수 a를 선언한 후 InputStream 클래스 내의 read 메소드를 사용해서 키보드로 데이터를 입력받아 변수 a에 저장한다. read 메소드는 바이트 자료형이 아닌 정수형으로 입력받는다. 문자열을 입력할 예정인데 변수 자료형이 int인 이유는 read 메소드는 문자열의 아스키 코드값(0~255)을 저장하기 때문이다.
  • read 메소드는 1byte의 문자열만 읽기 때문에 1byte 이상의 문자열을 입력해도 맨 앞의 1byte만 저장된다. 예를 들어 abc를 입력하면 a에 해당하는 아스키 코드만 출력된다. 그렇다면 2byte 이상의 문자열을 입력했을 때 모두 읽어들이고 싶다면
        int a = in.read();
        int b = in.read();
        int c = in.read();

        System.out.println(a);
        System.out.println(b);
        System.out.println(c);
		byte[] a = new byte[3];
        in.read(a);
        
        System.out.println(a[0]);
        System.out.println(a[1]);
        System.out.println(a[2]);        
abc
97
98
99
  • 위 두가지 방법을 통해 원하는 길이의 데이터를 입력받았을 경우 모두를 출력해낼 수 있다. 그렇다면 우리가 입력한 문자열 그대로를 출력하려면 어떻게 해야할까? InputStreamReader 클래스를 사용하면 된다.

* 인풋스트림리더(InputStreamReader)

InputStreamReader는 아스키코드가 아닌 입력한 그대로의 데이터를 출력하게끔 해주는 클래스이다.

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class Sample {
    public static void main(String[] args) throws IOException {
        InputStream in = System.in;
        InputStreamReader reader = new InputStreamReader(in);

        char[] a = new char[3];
        reader.read(a);

        System.out.println(a);
    }
}
  • InputStreamReader 또한 java.io 패키지 내의 클래스 이기 때문에 import 해주어야 한다. InputStreamReader의 객체를 생성할 때는 생성자의 입력으로 InputStream의 객체가 필요하다.

  • InputStreamReader을 사용하면 변수의 자료형을 byte 배열이 아닌 char 배열로 하여 문자열 그대로를 입력받아 문자열을 출력할 수 있다.

* 버퍼리더(BufferedReader)

버퍼리더는 고정된 길이의 데이터를 입력 받는게 아니라 원하는 길이만큼 데이터를 입력해도 읽을 수 있는 클래스이다.

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

public class Sample {
    public static void main(String[] args) throws IOException {
        InputStream in = System.in;
        InputStreamReader reader = new InputStreamReader(in);
        BufferedReader br = new BufferedReader(reader);

        String a = br.readLine();

        System.out.println(a);
    }
}
  • BufferedReader 클래스 역시 import를 해야하고 객체를 생성할 때 생성자의 입력값으로 InputrStreamReader의 객체를 필요로 한다.

  • BufferedReader 클래스의 readLine 메소드는 원하는 길이만큼의 데이터를 입력받을 수 있다.

* Scanner

처음으로 접했던 입력 클래스는 Scanner였고 이렇게 복잡하게 객체를 감싸고 감싸지 않아도 됐었다.

import java.util.Scanner;

public class Sample {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        String a = scanner.nextLine();

        System.out.println(a);
    }
}

ㄷ) 콘솔 출력

지금까지 배웠던 System.out.println 메소드의 System.out은 PrintStream 클래스의 객체이다. PrintStream은 콘솔에 데이터를 출력할 때 사용되는 클래스이다.

		System.out.println("일반출력");
		System.err.println("에러출력");

두 문장은 동일한 역할을 하지만 System.err은 에러 메세지를 출력하는 역할을 하고, 출력 문자도 빨간색이다.

(2) 파일 입출력

파일 입출력이란 콘솔 입출력과 달리 콘솔창에 입출력을 하는 것이 아니라 파일을 하나 생성해서 파일 내에 입력과 출력을 하는 방법이다.

ㄱ) 파일 쓰기

* FileOutstream

import java.io.FileOutputStream;
import java.io.IOException;

public class Sample {
    public static void main(String[] args) throws IOException {
        FileOutputStream output = new FileOutputStream("C:\\Users\\kcs91\\Desktop\\workspace\\Programming\\src\\out.txt");

        for (int i=1; i<11; i++) {
            String data = i + "번째 줄입니다.\r\n";
            output.write(data.getBytes());
        }

        output.close();
    }
}
  • FileOutputStream 클래스는 file을 생성해주는 클래스이다. 생성자의 입력으로 파일명을 넘겨주면 해당 위치에 파일을 생성해준다. 이 클래스 역시 java.io 패키지 내의 클래스이기 때문에 import하여 사용한다. 클래스 내의 write 메소드를 통해 파일 내에 데이터 입력이 가능하다.

  • for문으로 문장을 입력한다. \r\n은 Windows에서 쓰이는 줄바꿈 기호이다. String 타입의 변수에 문장을 저장한 후 write 메소드의 입력인자에는 String 타입의 변수를 Byte 타입으로 바꾸어서 입력한다.

  • close 메소드를 통해 객체 파일을 닫아준다. 생략해도 자동으로 닫아주지만 에러가 날 경우를 대비해 적어주는 것이 좋다.

* FileWriter

import java.io.FileWriter;
import java.io.IOException;

public class Sample {
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("C:\\Users\\kcs91\\Desktop\\workspace\\Programming\\src\\out.txt");

        for (int i=1; i<11; i++) {
            String data = i + " 번쨰 줄입니다.\r\n";
            fw.write(data);
        }

        fw.close();
    }
}
  • FileWriter는 FileOutputStream과 달리 String 타입을 사용할 수 있기 때문에 굳이 String에서 byte로 자료형 변환을 하지 않아도 된다.

* PrintWriter

import java.io.IOException;
import java.io.PrintWriter;

public class Sample {
    public static void main(String[] args) throws IOException {
        PrintWriter pw = new PrintWriter("C:\\Users\\kcs91\\Desktop\\workspace\\Programming\\src\\out.txt");

        for (int i=1; i<11; i++) {
            String data = i + " 번쨰 줄입니다.";
            pw.println(data);
        }

        pw.close();
    }
}
  • PrintWriter는 줄바꿈(\r\n)을 하지 않아도 PrintWriter 클래스 내에 줄바꿈이 가능한 println 메소드가 있기 때문에 더욱 간편하다.
        for (int i=1; i<11; i++) {
            String data = i + " 번쨰 줄입니다.";
            pw.println(data);
        }
        for (int i=1; i<11; i++) {
            String data = i + " 번쨰 줄입니다.";
			System.out.println(data);
		}
  • 두 코드의 차이는 출력의 위치의 차이이다. 위 코드는 생성한 파일 내에 출력하는 코드이고 아래 코드는 콘솔창에 출력하는 코드이다.

* 파일에 내용 추가하기

import java.io.FileWriter;
import java.io.IOException;

public class Sample {
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("C:\\Users\\kcs91\\Desktop\\workspace\\Programming\\src\\out.txt");

        for (int i=1; i<11; i++) {
            String data = i + " 번쨰 줄입니다.\r\n";
            fw.write(data);
        }

        fw.close();

        FileWriter fw2 = new FileWriter("C:\\Users\\kcs91\\Desktop\\workspace\\Programming\\src\\out.txt", true);

        for (int i=11; i<21; i++) {
            String data = i + " 번쨰 줄입니다.\r\n";
            fw2.write(data);
        }

        fw2.close();
    }
}
  • 파일에 데이터를 저장한 후에 추가적으로 이어서 저장해야 할 일이 생기는 경우 FileWriter 클래스의 객체를 새로 생성한 후 FileWriter의 두번째 입력인자에 추가로 이어서 데이터를 저장한다는 의미의 true를 입력하면 이전에 저장한 데이터 이후에 데이터가 저장된다.
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class Sample {
    public static void main(String[] args) throws IOException {
        PrintWriter pw = new PrintWriter("C:\\Users\\kcs91\\Desktop\\workspace\\Programming\\src\\out.txt");

        for (int i=1; i<11; i++) {
            String data = i + " 번쨰 줄입니다.";
            pw.println(data);
        }

        pw.close();

        PrintWriter pw2 = new PrintWriter(new FileWriter("C:\\Users\\kcs91\\Desktop\\workspace\\Programming\\src\\out.txt", true));

        for (int i=11; i<21; i++) {
            String data = i + " 번쨰 줄입니다.";
            pw2.println(data);
        }

        pw2.close();
    }
}
  • PrintWriter 클래스를 사용하는 경우에는 File Writer와 유사하지만 새로운 객체를 만들 때 입력인자에 FileWriter 클래스의 객체를 입력해야한다.

ㄴ) 파일 읽기

* FileInputStream

import java.io.FileInputStream;
import java.io.IOException;

public class Sample {
    public static void main(String[] args) throws IOException {
        byte[] data = new byte[1024];
        FileInputStream input = new FileInputStream("C:\\Users\\kcs91\\Desktop\\workspace\\Programming\\src\\out.txt");

        input.read(data);
        System.out.println(new String(data));
        input.close();
    }
}
  • FileInputStream 클래스를 이용하여 파일을 읽는다. 생성자의 입력값으로 읽고자하는 파일명을 적고, byte 타입의 변수를 read 메소드의 입력값으로 넣으면 읽힌다. byte 배열을 이용해 파일을 읽어야 하므로 파일의 크기를 모를 경우엔 부정확하지만 충분히 큰 크기의 byte를 읽도록 해야한다. 콘솔창에 읽힌 데이터를 출력하기 위해서 byte 타입의 변수를 String 타입으로 변환하여 출력한다.

* BufferedReader

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

public class Sample {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("C:\\Users\\kcs91\\Desktop\\workspace\\Programming\\src\\out.txt"));

        while (true) {
            String line = br.readLine();

            if (line==null) break;
            System.out.println(line);
        }

        br.close();
    }
}
  • BufferedReader 클래스는 byte 단위가 아니라 line 단위로 파일을 읽기 때문에 편리하다. 생성자의 입력값으로 FileReader 객체를 입력하고 while 문으로 파일의 데이터 끝까지만 읽어낼 수 있도록 코드를 짠다.

0개의 댓글