728x90
반응형
SMALL

----------------------학교에서 배운 내용, 여기서부터 이해가 필요한거 같아서 정리해서 올립니다----------------------

이해안가서 다른 책 내용도 같이 적어서 올려요!!

 

<<<<<<<<<<<<<<입출력>>>>>>>>>>>>>>>>>>>>>

 

6-1) 콘솔 입출력

 

예시) 문자열 출력 => 생년월일(YYYY/MM/DD)을 입력해주세요

 

콘솔 출력 : 사용자에게 문자열을 보여주는 것

 

※ 콘솔은 환경에 따라 변경될 수 있다.

만약 이 프로그램을 이클립스에서 실행했다면 이클립스의 콘솔창이 콘솔이 될 것이고

도스명령창에서 이 프로그램을 실행했다면 도스명령창이 콘솔이 된다.

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

 

콘솔출력 질문에 대한 답은 사용자가 키보드로 답변을 입력한다.

 

YYYY/MM/DD

 

이렇게 사용자가 입력한 문자열이 콘솔입력이다

 

JAVA의 System.in을 이용하면 콘솔 입력을 얻을 수 있다.

System.in을 이용하기 위해서는 제일 상위에 import java.io.InputStreem을 선언해주어야 한다.

 

import java.io.InputStream;

     public class StreamTest {

          public static void main(String[] args) throws Exception {

               InputStream in = System.in;

               

               int a;

               a = in.read();

 

               System.out.println(a);

}

}

위의 예시 코드에서 사용한 InputStream은 자바의 내장 클래스다.

JAVA의 내장 클래스중에 java.lang 패키지에 속해 있지 않은 클래스는 필요할 때 항상 import 해서 사용해야 한다.

그동안 사용해 왔던 System이나 String등의 클래스는 java.lang 패키지에 속해 있는 클래스이므로 별도의 import 과정이 필요없었다.

 

 System.in은 InputStream의 객체임을 알 수 있다.

InputStream in = System.in;

 

InputStream의 read메소드는 다음처럼 1 byte의 사용자의 입력을 받아들인다.

 

   int a;

   a = in.read();

 

read메소드로 읽은 1 byte의 데이터는 byte 자료형으로 저장되는 것이 아니라 int 자료형으로 저장된다. 저장되는 int 값은 0-255 사이의 정수값으로 아스키 코드값이다.

 

 InputStream의 read()메소드가 호출되면 사용자의 입력을 받을 때까지 프로그램이 대기하기 때문에

프로그램은 종료되지 않고 사용자의 입력을 대기하고 있게 된다.

 

스트림이란?

스트림을 가장 쉽게 이해하려면 수도꼭지를 생각하면 된다. 수도꼭지를 틀면 물이 나오고 수도꼭지를 잠그면 물이 나오지 않는다. A라는 곳에서부터 B라는 곳까지 수도관이 연결되어 있고 A에서 계속 물을 보낸다면 B에서 수도꼭지를 틀때마다 물이 나오게 될 것이다. 여기서 스트림은 A수도관에서 B수도관으로 이동하는 물의 흐름이라고 할 수 있다.

프로그래밍에서는 다음과 같은 것들을 스트림이라고 할 수 있다.

  • 파일 데이터 (파일은 그 시작과 끝이 있는 데이터의 스트림이다.)
  • HTTP 응답 데이터 (브라우저가 요청하고 서버가 응답하는 HTTP 응답 데이터도 스트림이다.)
  • 키보드 입력 (사용자가 키보드로 입력하는 문자열은 스트림이다.)

사용자가 3 byte를 입력했을 때 3 byte를 전부 읽고 싶다면 어떻게 해야 할까?

 

<예제>

import java.io.InputStream;

 

public class StreamTest {

     public static void main(String[] args) throws Exception {

          InputStream in = System.in;

          

          int a;

          int b;

          int c;

 

          a = in.read();

          b = in.read();

          c = in.read();

 

          System.out.println(a);

          System.out.println(b);

          System.out.println(c);

}

}

 

read() 메소드를 3번 실행하도록 수정하고 프로그램을 다시 실행해 보면

"abc" 입력시 총 3 byte를 읽어들이는 것을 확인할 수 있다

 

abc (입력)

97 (출력)

98 (출력)

99 (출력)

 

또는 다음과 같이 좀 더 개선된 방법을 사용할 수 있다.

import java.io.InputStream;

public class StreamTest {

     public static void main(String[] args) throws Exception {

          InputStream in = System.in;

          

          byte[] a = new byte[3];

          in.read(a);

 

          System.out.println(a[0]);

          System.out.println(a[1]);

          System.out.println(a[2]);

}

}

 

길이 3 짜리 byte배열을 만든 후 read메소드 호출시 입력값으로 전달하면 콘솔 입력이 해당 배열에 저장이 된다. 

 

abc (입력)

97 (출력)

98 (출력)

99 (출력)

 

아스키코드 값으로 해석하는 방법 : 바이트 대신 문자로 입력 스트림을 읽으려면 InputStreamReader를 사용하면 된다.

 

import java.io.InputStream;

import java.io.InputStreamReader;

 

public class StreamTest {

     public static void main(String[] args) throws Exception {

          InputStream in = System.in;

          InputStreamReader reader = new InputStreamReader(in);

           char[] a = new char[3];

          reader.read(a);

 

          System.out.println(a);

}

}

 

InputStreamReader를 사용하기 위해 import 문이 하나 더 추가되었다.

InputStreamReader 객체를 생성할 때는 생성자의 입력으로 InputStream의 객체가 필요하다.

 

InputStreamReader reader = new InputStreamReader(in);

 

InputStreamReader를 이용하면 다음처럼 byte대신 char배열을 사용할 수 있게된다.

 

char[] a = new char[3];

 

프로그램을 실행하고 "abc" 입력 후 엔터키로 사용자 입력을 전달하면 다음과 같이 "abc"라는 문자열이 한꺼번에 출력되는 것을 확인할 수 있다.

 

abc (입력)

abc (출력)

 

위 예제는 항상 3 byte만 읽도록 고정되어 있다.

 

사용자가 엔터를 입력할 때까지 입력을 받아들이는 방법 : BufferedReader를 이용하면 가능하다

 

import java.io.BufferedReader;

import java.io.InputStream;

import java.io.InputStreamReader;

 

public class StreamTest {

     public static void main(String[] args) throws Exception {

          InputStream in = System.in;

          InputStreamReader reader = new InputStreamReader(in);

          BufferedReader br = new BufferedReader(reader);

 

          String a = br.readLine();

          System.out.println(a);

}

}

BufferedReader를 이용하기 위해 import 문이 추가되었다.

BufferedReader는 객체 생성시 생성자의 입력값으로 InputStreamReader의 객체가 필요하다.

 

BufferedReader의 readLine메소드를 이용하면 사용자가 엔터키를 입력할 때까지 입력했던 문자열 전부를 읽을 수 있게 된다.

 

프로그램을 실행하고 "Hello World"라고 입력한 후 엔터키를 입력하면 "Hello World"라는 문자열이 그대로 Echo되어 출력되는 것을 확인할 수 있을 것이다.

 

HelloWorld (입력)

HelloWorld (출력)

 

<<<<<<<<<<<<<<<<<<<<<<기억하기>>>>>>>>>>>>>>>>>>>>>>>>>>

  • InputStream - byte
  • InputStreamReader - character
  • BufferedReader - String

 

Scanner

J2SE 5.0 부터 Scanner 라는 java.util.Scanner 클래스가 새로 추가되었다. Scanner 클래스를 이용하면 콘솔입력을 보다 쉽게 처리 할 수 있다.

다음의 예제를 보자.

import java.util.Scanner;

 

public class Test {

     public static void main(String[] args) {

          Scanner sc = new Scanner(System.in);

          System.out.println(sc.next());

}

}

Scanner 를 사용하기 위해서는 먼저 java.util.Scanner 클래스를 import 해야 한다.

 

import java.util.Scanner;

 

Scanner 클래스는 생성자의 입력으로 System.in, 즉 콘솔입력인 InputStream 을 필요로 한다.

Scanner 객체의 next() 메소드는 단어 하나(Token)를 읽어들인다.

Scanner클래스에는 단어 뿐만 아니라 숫자, 문자열등 다양하게 읽어 들일 수 있는 여러 메소드들이 준비되어 있는데 몇가지만 알아보면 다음과 같은 것들이 있다.

 

<<<<<<<<<<<<<<<<알아두기>>>>>>>>>>>>>>>>>>>

  • next - 단어
  • nextLine - 라인
  • nextInt - 정수

콘솔 출력

 

우리는 예제들에서 System.out.println 이라는 것을 계속해서 사용해 왔다.

 

System.out은 PrintStream 클래스의 객체이다.

PrintStream은 콘솔에 값을 출력할 때 사용되는 클래스이다.

보통 System.out.println은 콘솔에 문자열을 출력할 경우나 디버깅 시 많이 사용된다.

 

System.err라는 것도 있는데 System.out과 동일한 역할을 한다.

다만 System.err는 오류메시지를 출력할 경우에 사용하게 되어 있다.

 

6-2) 파일 입출력

 

파일 쓰기


<예제>

FileWrite.java

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

public class FileWrite {
    public static void main(String[] args) throws IOException {
        FileOutputStream output = new FileOutputStream("c:/out.txt");
        output.close();
    }
}
위 예제를 실행해 보면 c:/ 디렉토리 바로 밑에 새로운 파일(out.txt)이 하나 생성되는 것을 확인할 수 있다.

파일을 생성하기 위해서 우리는 FileOutputStream 클래스를 사용했다. 

FileOutputStream 객체를 생성하기 위해서는 생성자의 입력으로 파일명을 넘겨주어야 한다. 

위 예제에서는 경로를 포함하여 c:/out.txt라는 파일명을 생성자의 입력으로 전달하였다.

output.close()라는 문장이 있는데 이것은 사용한 파일 객체를 닫아주는 것이다. 사실 이 문장은 생략해도 된다.

왜냐하면 자바 프로그램이 종료할 때 사용한 파일 객체를 자동으로 닫아주기 때문이다.

하지만 직접 사용한 파일을 닫아주는 것이 좋다.

사용했던 파일을 닫지 않고 다시 사용하려고 할 경우에는 에러가 발생할 수 있기 때문이다.

파일에 내용쓰기

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

public class FileWrite {
    public static void main(String[] args) throws IOException {
        FileOutputStream output = new FileOutputStream("c:/out.txt");
        for(int i=1; i<11; i++) {
            String data = i+" 번째 줄입니다.\r\n";
            output.write(data.getBytes());
        }
        output.close();
    }
}
InputStream과 마찬가지로 OutputStream 역시 바이트 단위로 데이터를 처리하는 클래스이다. 

FileOutputStream은 OutputStream클래스를 상속받아 만든 클래스다.

바이트 단위로 데이터를 처리하게끔 되어 있다.

FileOutputStream에 값을 쓸 때는 byte배열로 써야 한다.

String을 byte배열로 바꾸어 주는 getBytes() 메서드를 이용해야만 했다.

\r\n은 줄바꿈 문자이다. (※ 유닉스인 경우는 \n 만 있으면 된다.


문자열을 파일에 쓸 때에는 FileOutputStream이 좀 불편하다. 

String을 byte배열로 변환해야 하기 때문이다.

<더 편리한 방법, 예제>
import java.io.FileWriter;
import java.io.IOException;

public class FileWrite {
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("c:/out.txt");
        for(int i=1; i<11; i++) {
            String data = i+" 번째 줄입니다.\r\n";
            fw.write(data);
        }
        fw.close();
    }
}
위 예제와 같이 FileOutputStream 대신에 FileWriter 를 이용하면 byte 배열 대신 문자열을 직접 파일에 쓸 수가 있다.

\r\n을 문자열 뒤에 덧 붙여야 하는 불편함은 FileWriter대신 PrintWriter를 사용하면 해소할 수 있다

PrintWriter를 이용하면 \r\n을 덧붙이는 대신 println이라는 메서드를 사용할 수 있게 된다.

 


<PrintWriter를 이용하여 파일을 작성하는 예제>

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

public class FileWrite {
    public static void main(String[] args) throws IOException {
        PrintWriter pw = new PrintWriter("c:/out.txt");
        for(int i=1; i<11; i++) {
            String data = i+" 번째 줄입니다.";
            pw.println(data);
        }
        pw.close();
    }
}


위의 프로그램을 다음의 프로그램과 비교해 보자.

for(int i=1; i<11; i++) {
    String data = i+" 번째 줄입니다.";
    System.out.println(data);
}
두 프로그램의 서로 다른 점은 data를 출력시키는 방법이다. 

두 번째 방법은 우리가 지금껏 계속 사용해 왔던 콘솔 출력 방법이고 

첫 번째 방법은 콘솔대신에 파일로 출력하는 방법이다. 

차이점이 금방 눈에 들어 올 것이다. 

System.out대신에 PrintWriter를 이용했을 뿐이다.

첫 번째 예제를 작성해서 실행시키면 c:/out.txt 파일이 생성된다.

파일에 어떤 내용이 저장되었는지 확인 해 보자.

out.txt의 내용

1 번째 줄입니다.
2 번째 줄입니다.
3 번째 줄입니다.
4 번째 줄입니다.
5 번째 줄입니다.
6 번째 줄입니다.
7 번째 줄입니다.
8 번째 줄입니다.
9 번째 줄입니다.
10 번째 줄입니다.
두 번째 방법을 사용했을 때 콘솔에 출력될 내용이 파일에 고스란히 들어가 있는 것을 알 수 있다.

파일에 내용 추가하기
프로그램을 만들다 보면 파일에 내용을 쓰고 난 후에 또 새로운 내용을 추가하고 싶을 때가 생긴다. 이럴 경우에는 이미 작성된 파일을 다시 추가모드로 열어야 한다.

 

<예제>
import java.io.FileWriter;
import java.io.IOException;

public class FileWrite {
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("c:/out.txt");
        for(int i=1; i<11; i++) {
            String data = i+" 번째 줄입니다.\r\n";
            fw.write(data);
        }
        fw.close();

        FileWriter fw2 = new FileWriter("c:/out.txt", true);
        for(int i=11; i<21; i++) {
            String data = i+" 번째 줄입니다.\r\n";
            fw2.write(data);
        }
        fw2.close();
    }
}
fw2라는 객체는 FileWriter("c:/out.txt", true) 와 같이 두번째 입력값이 추가로 입력되어 생성되었다. 

두번째 boolean 입력 파라미터는 파일을 추가모드(append)로 열것인지에 대한 구분값이다. 

파일을 추가모드로 열면 기존파일의 내용이후부터 파일이 쓰여지게 된다.

new FileWriter(파일명, 추가모드구분)
이제 위 예제를 실행하면 out.txt파일에 내용이 추가되는 것을 확인할 수 있을 것이다.

<<<<<<FileWriter대신 PrintWriter를 이용하고 싶은 경우 예제>>>>>>
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class FileWrite {
    public static void main(String[] args) throws IOException {
        PrintWriter pw = new PrintWriter("c:/out.txt");
        for(int i=1; i<11; i++) {
            String data = i+" 번째 줄입니다.";
            pw.println(data);
        }
        pw.close();


        PrintWriter pw2 = new PrintWriter(new FileWriter("c:/out.txt", true));
        for(int i=11; i<21; i++) {
            String data = i+" 번째 줄입니다.";
            pw2.println(data);
        }
        pw2.close();
    }
}
PrintWriter의 생성자의 입력으로 파일명 대신 추가모드로 열린 FileWriter의 객체를 사용하면 된다.

파일 읽기

<예제>
FileRead.java

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

public class FileRead {
    public static void main(String[] args) throws IOException {
        byte[] b = new byte[1024];
        FileInputStream input = new FileInputStream("c:/out.txt");
        input.read(b);
        System.out.println(new String(b));
        input.close();
    }
}
파일을 읽기 위해서는 위 예처럼 FileInputStream 클래스를 이용하면 된다. 

byte 배열을 이용하여 파일을 읽어야 하기 때문에 읽어야 하는 정확한 길이를 모를 경우에는 좀 불편한 방법이다.

위 예에서는 1024 바이트를 읽도록 코딩했다.

<<<<<<만약 파일을 라인단위로 예제를 수정>>>>>>
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class FileRead {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("c:/out.txt"));
        while(true) {
            String line = br.readLine();
            if (line==null) break;
            System.out.println(line);
        }
        br.close();
    }
}
FileInputStream 대신 FileReader와 BufferedReader의 조합을 사용하면 라인단위로 파일을 읽을 수 있다. 

BufferedReader의 readLine 메소드는 더이상 읽을 라인이 없을 경우 null을 리턴한다.

파일을 라인단위로 읽어서 출력하고 더 이상 읽을 라인이 없는 경우 while문을 빠져나간다.

728x90
반응형
LIST

'명품자바프로그래밍' 카테고리의 다른 글

명품 JAVA programming 9장  (0) 2021.09.29
명품 JAVA programming 7장  (0) 2021.09.28
명품 JAVA programming 5장  (0) 2021.09.28
명품 JAVA programming 4장  (0) 2021.09.28
명품 JAVA programming 3장  (0) 2021.09.28

+ Recent posts