January 10, 2021
자바는 입출력 스트림을 통해 다양한 경로로의 입출력을 구현하는 일관된 방식 제공
스트림(Stream)이란 순서가 있는 일련의 데이터를 의미한다.
Source
: 키보드, 파일, 네트워크 등 데이터 근원지Input Stream
: 근원지에서 흘러 들어오는 데이터Destination
: 모니터, 파일, 네트워크 등 데이터 목적지∴ 동일한 방법으로 프로그램이 작성될 수 있는 유연한 구조의 API를 가진다.
👉 자바는 입출력을 위해 스트림을 생성하고 다루는 클래스들을 java.io 패키지를 통해 제공
자바로 입출력 기능을 구현하는 프로그램을 개발하는 데에 필요한 다양한 클래스를 포함하는 패키지
File 클래스로 파일, 디렉토리를 모두 표현하고 관리할 수 있다.
파일 클래스로부터 객체를 생성하는 일반적인 방법
//C:₩Program Files 디렉토리에 해당하는 파일 객체 생성
File file = new File("C:₩Program Files");
//현재 작업 디렉토리에 해당하는 파일 객체 생성. '.'은 현재 작업 디렉토리 의미
File file = new File(".");
//현재 작업 디렉토리 밑에 위치한 파일에 대한 파일 객체 생성
File file = new File("./systemLog.log");
주요 메소드
boolean delete()
: 폴더가 비어있다면, 파일이나 폴더를 삭제boolean exists()
: 파일의 존재여부 returnString getAbsolutePath()
: 파일의 절대 경로를 문자열로 returnString getName()
: 파일이나 폴더의 이름 returnboolean isDirectory()
: 폴더인지의 여부 return파일에 무작위적인 접근을 가능하게 함
입출력 스트림을 가능하게 함
분류
입출력 단위에 의한 분류
데이터 이동 통로에 의한 분류
즉, 자바에서 입출력에 사용하는 스트림 클래스의 형태는 크게 4가지로 분류할 수 있다.
❗️바이트 단위와 캐릭터 단위는 서로 호환하지 않는 것을 원칙으로 한다.
스트림 클래스
Java에서는 두 개 이상의 클래스를 연결한 입출력 스트림을 생성해서 입출력을 하는 경우가 매우 일반적이다.
try{
FileOutputStream output = new FileOutputStream("message.txt");
BufferedOutputStream buffOutput = new BufferedOutputStream(output);
buffOutput("Message Output..");
}catch(IOException e){
e.printStackTrace();
}
∴ InputStream을 상속한 자식 클래스는 InputStream 클래스에 존재하는 모든 추상 메소드를 적절하게 오버라이딩해야한다. & InputStream 클래스를 상속한 자식 클래스의 객체를 생성하여 입력 관련 로직을 구현 가능
주요 메소드
void close() throws IOException
: 입력 스트림 닫기int read() throws IOException
: 입력 스트림에서 한 바이트를 읽어서 int 값으로 return
int read(byte buf[]) throws IOException
: 입력 스트림에서 buf[] 크기만큼을 읽어 buf에 저장하고, 읽은 바이트 수를 return
이중 가장 중요한 메소드는 read() 메소드
EOF(End Of File)이란?
파일의 끝을 의미한다. 윈도우에서는 Ctrl-Z, 리눅스나 유닉스에서는 Ctrl-D를 사용한다. 이 값을 -1로 표현할 수 있다. 하지만 read()의 리턴값은 int이다. 그래서 양수를 기준으로 표현하는데 0~127까지만 사용할 수 있다. 이를 해결하기 위해 더 큰 자료형을 리턴으로 사용하여 0~255까지 사용할 수 있게 하고, -1을 특수한 입력 값으로 처리하도록 구성하기 위해 int형을 return 값 형식으로 사용하는 것이다.
주요 메소드
void close() throws IOException
: 출력 스트림 닫기void flush() throws IOException
: 버퍼에 남은 출력 스트림 출력void write(int i) throws IOException
: 정수 i의 하위 8비트 출력void write(byte buf[]) throws IOException
: buf의 내용 출력이중 가장 중요한 메소드는 write(int i) 메소드
write(int i)메소드에는 세 개의 메소드가 오버로딩됨
출력이 끝났음을 알려주는 flush()메소드
👉 자바에서는 표준 입출력 기능을 System 클래스에서 제공
∵ 모든 프로그램에서 기본적으로 표준 입출력을 사용할 수 있도록 하기 위해서이다.
System.in
영문과 한글의 처리를 분리해서 구성해야 제대로 인식함
//키보드 입력을 위한 구문 System.in.read();
System.out
표준 출력 장치 객체System.out.println()
, System.out.print()
등의 메소드가 데이터 타입 별로 오버로딩 되어있음.InputStream 클래스를 상속한 자식 클래스로 하드디스크 상에 존재하는 파일로부터 바이트 단위의 입력을 처리하는 클래스. 즉, 스트림을 생성하는 클래스
FileNotFoundException
에 대한 예외 처리를 해야한다.OutputStream 클래스를 상속한 자식 클래스로 파일로 바이트 단위의 출력을 처리하는 클래스
보다 효율적인 프로그램 작성을 위해서는, 기계적인 동작의 횟수를 줄이는 것이 가장 좋은 방법이다. 입출력 횟수를 줄이면 프로그램의 효율을 높일 수 있고 더 빠른 프로그램으로 개선할 수 있다.
🗝 1바이트씩 읽어들이는 read()메소드 👉 한꺼번에 많은 데이터를 바이트의 배열로 읽어들이는 read(byte[])메소드를 사용하는 것이 좋다!
//읽어들일 가용량을 파악하여 size를 지정
int size = input.available();
// 입출력을 최소화하기 위해 한 번의 입력으로 파일의 모든 내용을 버퍼로 가져온 후,
// 한번의 출력으로 다른 파일로 저장
📍버퍼의 크기가 무조건 파일 크기만큼 크면 성능이 좋아질까?
❌ 버퍼의 크기가 아주 작으면 효율은 급격히 떨어지고, 버퍼의 크기가 크다면 메모리 낭비를 유발할 수 있다. 또한 파일의 크기가 예상하는 것보다 훨씬 큰 경우 충분한 메모리를 준비할 수 없는 상황도 발생 가능
∴ 버퍼의 크기는 적정선에서 만족할 수 있도록 잡는 것이 필요(일반적으로 1024, 2048, 4096 같이 배수 형식으로 준비하는 것이 일반적)
FileInputStream
: 1차 스트림
BufferedInputStream
: 2차 스트림
👍 BufferedInputStream / BufferedOutputStream을 사용하여 프로그램을 작성 시
👍 문자 스트림을 통해 특별한 문자 인코딩에 독립적인 프로그램을 작성할 수 있고, 좀 더 효율적으로 구현 가능
try{
FileWriter fw = new FileWriter("test");
PrintWriter pw = new PrintWriter(fw);
pw.println("abc");
pw.close();
fw.close();
}catch(IOException e){ }
JAVA는 영미권에서 만들어졌기 때문에 영어를 입출력할 때에는 문제가 없지만 다른 나라에서 자국의 언어로 입출력을 할 때에는 문제가 발생한다.
📍각 나라의 언어를 표현아는 인코딩(Encoding)이 다르기 때문이다.
120개(알파벳 소문자, 대문자 52개, 10진수 숫자 10개, 문장부호 50~60개)의 자를 표현하기 위해 2^7(7비트)로 표현된 문자 체계인 ASCII 문자 코드를 사용
초성 자음 19개, 중성 모음 21개, 종성 모음 28개 == 15비트가 있어야 하나의 한글 표현 가능 - 2바이트를 묶어서 한 글자를 표현(Multi Byte Character Set) : KSC5601, EUC-KR, MS949
이렇게 각 나라별로 자신만의 고유한 언어를 표현하기 위해서 Extended ASCII를 사용하는데, 이는 전세계의 데이터가 서로 다르게 해석되는 문제를 야기한다. 이를 해결하기 위해 국제 표준화 기구에서 표준 인코딩을 제안했다.
IOS(International Organization for Standardization)에서의 표준화 작업(2바이트 기준 새로운 인코딩 제안) 진행
❗️바이트 데이터의 값과 그 값이 해석된 인코딩이 서로 맞아 떨어질 때 정확한 글자가 나타난다.
바이트 데이터를 기준으로 문자를 만들어 내는 부분
ex) char, String 클래스 또는 바이트 스트임에서 문자 스트림으로 변환되는 클래스
👍 자바에서 글자가 깨지는 현상이 발생한다면?
👉 깨진 글자를 getBytes()로 분해했다가 새롭게 String 객체를 만들어 출력하는 방법으로 해결 but 다양한 인코딩을 시도해 봐야한다.
Reader 클래스 주요 메소드
abstract void close() throws IOException
: 문자 입력 스트림 닫음void mark(int limit) throws IOException
: 문자 입력 스트림의 현재 위치 표시int read(char buf[]) throws IOException
: 문자 입력 스트림에서 buf[] 크기만큼을 읽어 buf에 저장하고 읽은 문자 수를 returnWriter 클래스 주요 메소드
abstract void close() throws IOException
: 문자 출력 스트림 닫음abstract void flush() throws IOException
: 버퍼에 남은 출력 스트림 출력void write(String s) throws IOException
: 주어진 문자열 s를 출력void write(char buf[]) throws IOException
: buf의 내용을 출력
데이터를 표준 출력하기 위해서 사용하는 스트림 클래스
👉 PrintWriter를 사용하는 것이 유니코드를 표현하는 측면에서 더 효율적
이 클래스들에 있는 메소드들은 다른 스트림과 달리 IOException을 던지지 않는다. If 출력 에러가 발생하면,
에러가 발생하면 checkError()는 true return
System.out.println("Hi");
if(System.out.checkError())