jhhan의 블로그

Java의 정석을 시작하자(6)(2/10) 본문

JAVA

Java의 정석을 시작하자(6)(2/10)

jhhan000 2020. 2. 14. 16:57

15장. 입출력

-입출력과 스트림

  • I/O : Input & Output의 약자 - 간단하게 입출력이라 한다.
  • 입출력 : 컴퓨터 내부 또는 외부 장치와 프로그램간의 데이터를 주고받는 것
  • 스트림 : 데이터를 운반하는데 사용되는 연결통로
    • cf) 여기서 나오는 스트림은 14장의 스트림과 다른 개념이다. 글자만 같다.

-바이트기반 스트림 : InputStream, OutputStream

  • 스트림은 바이트단위로 데이터를 전송
  • 여러 종류의 입출력스트림 존재
  • 모두 InputStream, OutputStream의 자손들
  • java.io패키지를 통해 많은 입출력관련 클래스들을 제공

-보조스트림

  • 스트림의 기능 향상 or 새로운 기능 추가
  • 보조스트림만으로 입출력을 처리할 수는 없다.
  • 스트림을 먼저 생성 후 이를 이용해서 보조스트림 생성
입력 출력 설명
FilterInputStream FileterOutputStream 필터를 이용한 입출력 처리
BufferedInputStream BufferedOutputStream 버퍼를 이용한 입출력 성능 향상
DataInputStream DataOutputStream 기본형 단위로 데이터 처리
SequenceInputStream 없음 두 개의 스트림을 하나로 연결
LineNumberInputStream 없음 읽어 온 데이터의 라인 번호 카운트
(JDK1.1부터 LineNumberReader로 대체)
ObjectInputStream ObjectOutputStream 데이터를 객체단위로 읽고 씀
객체 직렬화와 관련됨
없음 PrintStream 추가적인 print관련 기능
PushbackInputStream 없음 버퍼를 이용해서 읽어온 데이터를 다시 되돌리는 기능

-문자기반의 스트림 : Reader, Writer

  • 바이트기반은 입출력 단위가 1Byte이다.
  • Java는 char형이 2Byte이기 때문에 처리하는데 어려움이 있다.
  • 이를 보완하기 위해 나온 개념
  • InputStream -> Reader ,  OutputStream -> Writer
  • 이름만 다를 뿐 활용방법은 거의 같다.
바이트기반 스트림 문자기반 스트림
FileInputStream
FileOutputStream
FileReader
FileWriter
ByteArrayInputStream
ByteArrayOutputStream
CharArrayReader
CharArrayWriter
PipedInputStream
PipedOutputStream
PipedReader
PipedWriter
StringBufferInputStream
StringBufferOutputStream
StringReader
StringWriter

 

-InputStream & OutputStream

  • 모든 바이트 기반 스트림의 조상

예제 1,2,3 의 출력 결과

  • 예제를 한번에 다 합쳤다.
  • 예제1은 inSrc를 outSrc로 복사했다. - read(), write() 사용법을 보였다.
  • 예제2는 inSrc를 temp에 넣은 다음 그 일부를 outSrc로 복사했다.
  • 예제3은 inSrc에 내용을 temp에 넣는데 temp의 크기가 작아서 그 과정을 여러번 해야한다.
  • InputStream과 OutputStream을 이해하는데 도움이 된다고 생각한다.

-FileInputStream & FileOutputStream

  • 파일에 입출력을 하기 위한 스트림
  • 언어를 하나 배울 때마다 항상 들어있는 부분이고 중요하다고 생각한다.

  • 커맨드라인으로부터 입력받은 파일의 내용을 읽어서 그대로 화면에 출력하는 예제이다.

  • Filecopy.java의 내용을 그대로 Filecopy.bak로 복사하는 일을 한다.
  • 텍스트파일을 다룰 때는 FileReader/FileWriter를 쓰는게 더 낫다.

-FilterInputStream & FilterOutputStream

  • 모든 보조스트림의 조상
  • FilterInputStream의 자손 : BufferedInputStream, DataInputStream, PushbackInputStream 등
  • FilterOutputStream의 자손 : BufferedOutputStream, DataOutputStream, PrintStream 등

-BufferedInputStream & BufferedOutputStream

  • 스트림의 입출력 효율을 높이기 위해 사용
  • BufferedInputStream : read메서드 호출 시 버퍼크기만큼 데이터를 읽어서 내부 버퍼에 저장
  • BufferedOutputStream : write메서드를 이용해 버퍼에 저장
  • 버퍼가 가득 차면 내용출력 -> 버퍼를 비우고 다시 저장 준비
  • 마지막 출력 부분이 출력소스에 쓰이지 못하고 종료될 수 있다 -> 주의!
  • flush()를 호출해 모든 내용이 출력소스에 출력되게 해야 한다.

  • 크기가 5인 BufferedOutputStream을 이용했다.
  • 결과는 123.txt에 123456789가 적히게 된다.
  • 여기서 bos.flush()를 하지 않으면 12345만 적힌 상태로 종료된다.
  • 마지막 출력부분이 출력소스에 쓰이지 않고 종료되기 때문이다.
  • 그렇기 때문에 flush() 반드시 해줘야함.

-SequenceInputStream

  • 여러 개의 입력스트림을 연속적으로 연결 -> 하나의 스트림으로 데이터를 읽는 것과 같이 처리하게 도와준다.
  • 큰 파일을 여러개로 나누었다가 다시 합치는 작업에 수행하면 좋다.

  • SequenceInputStream에 대한 예제이다.
  • Vector에 저장된 순서대로 입력되므로 그 점을 주의하자.

-PrintStream

  • print, println, printf 같은 메서드를 오버로딩하여 제공
  • 데이터를 적절한 문자로 출력 -> 문자기반 스트림의 역할 수행

-Reader & Writer

  • 2Byte로 스트림을 처리한다.
  • 여러 종류의 인코딩과 유니코드간의 변환을 자동으로 처리

-FileReader & FileWriter

  • FileInputStream & FileOutputStream 과 다를 것이 별로 없다.

  • test.txt파일에 "Hello 안녕하세요?" 라고 저장했을 때
  • 결과가 저렇게 나온다.
  • FileInputStream은 한글의 경우 결과가 깨져서 나온다.

-StringReader & StringWriter

  • 입출력 대상이 메모리인 스트림

  • 문자열을 처리할 때 자주 쓰이는 것 같다.

-BufferedReader & BufferedWriter

  • 버퍼를 이용해서 입출력의 효율을 높인다.
  • BufferedReader - readLine() : 데이터를 라인단위로 읽을 수 있다.
  • BufferedWriter - newLine() : 줄바꿈 하는 메서드

-InputStreamReader & OutputStreamWriter

  • 바이트기반 스트림을 문자기반 스트림으로 연결시키는 역할
  • 바이트기반 스트림의 데이터를 지정된 인코딩의 문자데이터로 변환

-표준 입출력(Standard I/O)

  • 표준 입출력 : 콘솔을 통한 데이터 입력, 출력을 의미
  • System.in ,  System.out ,  System.err 제공
  • System.in : 콘솔로부터 데이터를 입력받는데 사용
  • System.out : 콘솔로 데이터를 출력하는데 사용
  • System.err : 콘솔로 데이터를 출력하는데 사용
  • JDK1.5부터 Scanner클래스 제공 -> System.in으로 입력받는 작업이 편리해짐.
  • System.out , System.err 모두 출력대상이 콘솔이어서 어느 것을 사용해도 같은 결과를 얻음

-File

  • 기본적이면서 가장 많이 사용되는 입출력 대상
  • File클래스를 통해 파일과 디렉토리를 다룰 수 있도록 한다.
  • 절대경로 : 루트로부터 시작하는 파일의 전체경로
  • 둘 이상의 절대경로가 있을 수 있다.
  • 정규경로 : 기호나 링크 등을 포함하지 않는 유일한 경로
  • user.dir : 현재 프로그램이 실행중인 디렉토리를 알 수 있다.
  • File인스턴스를 생성했다고 파일이나 디렉토리가 생성되는 것은 아니다.
  • 새로운 파일 생성 : File인스턴스 생성 -> 출력스트림 생성 or createNewFile() 호출

  • File클래스를 다뤄보는 예제이다.
  • 다양한 메서드를 사용해봤다. 알아두면 좋을 것이다.

-직렬화

  • 객체를 데이터 스트림으로 만드는 것
  • 역직렬화 : 스트림으로부터 데이터를 읽어서 객체를 만드는 것
  • 다시 한번 객체에 대해 집고 넘어가자!

-객체

  • 객체 : 클래스에 정의된 인스턴스변수의 집합 -> 클래스변수, 메서드 포함 안함
  • 메서드는 변하지 않기 때문에 인스턴스마다 포함시킬 이유가 없기 때문이다.
  • 클래스변수도 마찬가지... 일 것이다.
  • 그래서 객체에는 메서드가 포함되지 않는다.
  • 객체를 저장한다 == 객체의 모든 인스턴스변수 값을 저장한다는 의미

-다시 직렬화

  • ObjectOutputStream : 직렬화에 사용
  • ObjectInputStream : 역직렬화에 사용
  • 직렬화/역직렬화 : 모든 객체에 대한 것이어서 상당히 복잡하고 오래걸린다.

-직렬화가 가능한 클래스

  • implements java.io.Serializable을 붙인다.
  • Serializable은 인터페이스이다.
  • 실제로는 빈 인터페이스
  • 직렬화를 고려하여 작성한 클래스인지 판단하는 기준이 됨

-직렬화 대상에서 제외하기 : 제어자 transient 붙이기

-역직렬화는 직렬화 할 때의 순서로 진행해야 한다.
  ex) a,b,c 순서로 직렬화 했다면 a,b,c 순서로 역직렬화 할 것

  • 직렬화와 역직렬화를 실행한 예제이다.
  • 직렬화 : FileOutputStream -> BufferedOutputStream -> ObjectOutputStream 순서로 진행된다.
  • 그리고 wirteObject()를 이용해서 객체를 직렬화 했다.
  • 역직렬화 : FileInputStream -> BufferedInputStream -> ObjectInputStream 순서로 진행된다.
  • 그리고 readObject()를 이용하여 객체를 읽는다.
  • 직렬화 할 때 u1, u2, list 순서였기 때문에 역직렬화 역시 u1, u2, list 순서로 한다.

'JAVA' 카테고리의 다른 글

BufferedReader & BufferedWriter  (0) 2020.06.18
Java의 정석을 시작하자(7)(2/11)  (0) 2020.02.14
Java의 정석을 시작하자(5)(2/8)  (0) 2020.02.14
Java의 정석을 시작하자(4)(2/7)  (0) 2020.02.14
Java의 정석을 시작하자(4)(2/7)  (0) 2020.02.13