메뉴 건너뛰기

조회 수 3763 추천 수 0 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄

바이트 기반의 스트림


1. 바이트 기반 스트림

(1) InputStream과 OutputStream

InputStream과 OutputStream은 모든 바이트기반의 스트림의 조상이며 같은 메서드가 선언되어 있다.

cp.)

void close(): 스트림을 닫음으로써 사용하고 있던 자원을 반환한다.

abstract int read(): 1byte를 읽어온다.(0~255 사이의 값), 더 이상 읽어 올 데이터가 없으면 -1을 반환한다. abstract메서드라서 InputStream의 자손들은 자신의 상황에 알맞게 구현해야 한다.

int read(byte[] b): 배열 b의 크기만큼 읽어서 배열을 채우고 읽어 온 데이터의 수를 반환한다. 반환하는 값은 항상 배열의 크기보다 작거나 같다.

int read(byte[] b, int off, int len): 최대 len개의 byte를 읽어서, 배열 b의 지정된 위치(off)부터 저장한다. 실제로 읽어올 수 있는 데이터가 len개보다 적을 수 있다.

flush() 버퍼가 있는 출력 스트림의 경우에만 의미가 있으며, OutputSteam에 정의된 flush()는 아무런 일도 하지 않는다.

프로그램이 종료될 때, 사용하고 닫지 않은 스트림을 JVM이 자동적으로 닫아 주기는 하지만, 스트림을 사용해서 모든 작업을 마치고 난 후에는 close()를 호출해서 반드시 닫아 주어야 한다.

cf.) ByteArrayInputStream과 같이 메모리를 사용하는 스트림과 System.in, System.out과 같은 표준입출력은 닫아 주지 않아도 된다.


(2) FileInputStream과 FileOutputStream
FileInputStream과 FileOutputStreamdms 파일에 입출력을 하기 위한 스트림이다.


cp.) FileInputStream(File fileObj): 파일의 이름이 String이 아닌 File 인스턴스로 지정해주어야 하는 점을 제외하고 FileInputStream(String filePath)와 같다.


import java.io.*;


class FileViewer {
public static void main(String args[]) throws IOException{
FileInputStream fis = new FileInputStream(args[0]);
int data =0;
while((data=fis.read())!=-1) {
char c = (char)data;
System.out.print(c);
}
}
}

FileInputStream과 FileOutputStream을 사용해서 FileCopy.java파일의 내용을 그대로 복사하는 내용의 예제이다.
import java.io.*;

class FileCopy {
public static void main(String args[]) {
try {
FileInputStream fis = new FileInputStream(args[0]);
FileOutputStream fos = new FileOutputStream(args[1]);

int data =0;

while((data=fis.read())!=-1) {
fos.write(data); // void write(int b)
}

fis.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}


import java.io.*;

class FileViewer {
public static void main(String args[]) throws IOException{
FileInputStream fis = new FileInputStream(args[0]);
int data =0;
while((data=fis.read())!=-1) {
char c = (char)data;
System.out.print(c);
}
}
}
read()의 반환값이 int형(4byte)이긴 하지만, 더 이상 입력값이 없음을 알리는 -1을 제외하고는 0~255(1byte)의 범위의 정수값이기 때문에, char형(2byte)으로 변환한다해도 손실되는 값이 없다.
read()가 한 번에 1byte씩 파일로부터 데이터를 읽어 들이긴 하지만, 데이터의 범위가 십진수로 0~255(16진수로는 0x00~0xff)범위의 정수값이고, 또 읽을 수 있는 입력값이 더 이상 없음을 알릴 수 있는 값도 필요하다.
그래서 다소 크긴 하지만 정수형 중에서는 연산이 가장 효율적이고 빠른 int형 값을 반환하도록 한 것이다.

2. 바이트기반의 보조스트림
(1) FilterInputStream과 FilterOutputStream

FilterInputStream과 FilterOutputStream은 InputStream/OutputStream의 자손이면서 모든 보조 스트림의 조상이다. 
보조 스트림은 자체적으로 입출력을 수행할 수 없기 때문에 기반 스트림을 필요로 한다.

- FilterInputStream과 FilterOutputStream의 생성자이다.
Protected FilterInputStream(InputStream in)
public FilterOutputStream(OutputStream out)
FilterInputStream과 FilterOutputStream의 모든 메서드는 단순히 기반 스트림의 메서드를 그대로 호출할 뿐이다. FilterInputStream과 FilterOutputStream 자체로는 아무런 일도 하지 않음을 의미한다.
FilterInputStream과 FilterOutputStream 자체로는 아무런 일도 하지않고 상속을  통해 원하는 작업을 수행하도록 읽고 쓰는 메서드를 오버라이딩 해야 한다.

(2) BufferedInputStream과 BufferedOutputStream
BufferedInputStream과 BufferedOutputStream은 스트림의 입출력 효율을 높이기 위해 버퍼를 사용하는 보조 스트림이다. 한 바이트씩 입출력하는 것 보다 버퍼(바이트배열)를 사용해서 한 번에 여러 바이트를 입출력하는 것이 빠르기 때문에 대부분의 입출력 작업에 사용된다.

BufferedInputStream과 BufferedOutputStream의 버퍼크기는 입력소스로부터 한 번에 가져올 수 있는 데이터의 크기로 지정하면 좋다. 보통 입력소스가 파일인 경우 보통 작게는 1024부터 2048 또는 4096 정도의 크기로 하는 것이 보통이며, 버퍼의 크기를 변경해가면서 테스트하면 최적의 버퍼 크기를 알아낼 수 있다.

프로그램에서 입력 소스로부터 데이터를 읽기 위해 처음으로 read 메서드를 호출하면, BufferedInputStream은 입력 소스로 부터 버퍼 크기만큼의 데이터를 읽어다 자신의 내부 버퍼에 저장한다. 이제 프로그램에서는 
BufferedInputStream의 버퍼에 저장된 데이터를 읽으면 되는 것이다. 외부의 입력 소스로 부터 읽는 것보다 내부의 버퍼로 읽는 것이 훨씬 빠르기 때문에 그만큼 작업 효율이 높아진다.
프로그램에서 버퍼에 저장된 모든 데이터를 다 읽고 그 다음 데이터를 읽기 위해 read 메서드가 호출되면, BufferedInputStream은 입력 소스로부터 다시 버퍼 크기만큼의 데이터를 읽어다 버퍼에 저장해 놓는다.


BufferedOutputStream 역시 버퍼를 이용해서 작업을 하게 되는데, 입력 소스로부터 데이터를 읽을 때와는 반대로, 프로그램에서 write 메서드를 이용한 출력이 BufferedOutputStream의 버퍼에 저장된다. 
버퍼가 가득 차면, 그 때 버퍼의 모든 내용을 출력 소스에 출력한다.
버퍼가 가득 찼을때만 출력소스에 출력을 하기 때문에, 마지막 출력 부분이 출력소스에 쓰여지지 못하고, BufferedOutputStream의 버퍼에 남아있는 채로 프로그램이 종료될 수 있다는 점을 주의해야 한다.
그래서 프로그램에서 모든 출력 작업을 마친 후 BufferedOutputStream에 close()나 flush()를 호출해서 마지막에 버퍼에 있는 모든 내용이 출력소스에 출력되도록 해야 한다.

import java.io.*;

class BufferedOutputStreamEx1 {
public static void main(String args[]) {
try {
    FileOutputStream fos = new FileOutputStream("123.txt");      
             BufferedOutputStream bos = new BufferedOutputStream(fos, 5);
     // BufferedOutputStream의 버퍼 크기를 5로 한다.
   
    for(int i='1'; i <= '9'; i++) {   
    bos.write(i);
     // 파일 123.txt에  1 부터 9까지 출력한다.
    }
    fos.close();
} catch (IOException e) {
    e.printStackTrace();
}
}
}
크기가 5인 BufferedOutputStream을 이용해서 파일 123.txt에 1부터 9까지 출력하는 예제인데 결과를 보면 5까지만 출력된 것을 알 수 있다. 그 이유는 버퍼에 남아있는 데이터가 출력되지 못한 상태로 프로그램이 종료되었기 때문이다.
이 예제에서 fos.close()를 호출해서 스트림을 닫아주기는 했지만, 이렇게 해서는 BufferedOutputStream의 버퍼에 있는 내용이 출력되지 않는다. bos.close();와 같이 해서 BufferedOutputStream의 close()를 호출해 주어야 버퍼에 남아있던 모든 내용이 출력된다. BufferedOutputStream의 close()는 기반 스트림인 FileOutputStream의 close()를 호출하기 때문에 FileOutputStream의 close()는 따로 호출해주지 않아도 된다.
--> 보조스크림을 사용한 경우에는 기반스트림의 close()나 flush()를 호출할 필요없이 단순히 보조스트림의 close()를 호출하기만 하면 된다.

(3) PrintStream
PrintStream은 데이터를 기반스트림에 다양한 형태로 출력할 수 있는 print, println, printf와 같은 메서드를 오버로딩하여 제공한다.
PrintStream은 데이터를 적절한 문자로 출력하는 것이기 때문에 문자기반 스트림의 역할을 수행한다.
cf.) PrintStream은 우라기 지금까지 알게 모르게 많이 사용해 왔다. System 클래스의 static 멤버인 out과 err, 다시 말하자면 System.out, System.err이 PrintStream이다.


import java.util.Date;

class PrintStreamEx1 {
public static void main(String[] args) {
int i = 65;
float f = 1234.56789f;

Date d = new Date();

System.out.printf("문자 %c의 코드는 %d\n", i, i);
System.out.printf("%d는 8진수로 %o, 16진수로 %x\n", i ,i, i);
System.out.printf("%3d%3d%3d\n", 100, 90, 80);
System.out.println();
System.out.printf("123456789012345678901234567890\n");
System.out.printf("%s%-5s%5s\n", "123", "123", "123");
System.out.println();
System.out.printf("%-8.1f%8.1f %e\n",f,f,f);
System.out.println();
System.out.printf("오늘은 %tY년 %tm월 %td일 입니다.\n", d,d,d,d );
System.out.printf("지금은 %tH시 %tM분 %tS초 입니다.\n", d,d,d,d );
System.out.printf("지금은 %1$tH시 %1$tM분 %1$tS초 입니다.\n", d );
}
}
실행결과)
문자 A의 코드는 65
65는 8진수로 101, 16진수로 41
100 90 80

123456789012345678901234567890
123123    123

1234.6    1234.6 1.234568e+03

오늘은 2014년 04월 23일 입니다.
지금은 01시 50분 29초 입니다.
지금은 01시 50분 29초 입니다.


List of Articles
번호 제목 날짜 조회 수
91 자바 정규식 마스킹처리 file 2018.06.26 2631
90 개인정보 마스킹처리 (휴대폰번호, 이메일) 2018.06.26 3941
89 자바 날짜 포맷 변환 방법 file 2018.06.21 1425
88 JDK 9에서 eclipse 실행이 안될때 2018.06.05 1596
87 숫자형식 포멧 방법 2018.02.09 2341
86 jquery 스크롤(scroll) 따라다니는 배너 레이어 / 위로 버튼 / 화면 상단으로 이동 / scroll layer 이벤트 file 2017.07.05 4057
85 BigDecimal타입의 사칙연산 2016.12.22 3713
84 다양한 문자 조합을 이용한 카운팅 구하기 2016.12.09 4941
83 자바 JXL 엑셀파일을 읽어 배열리턴 : JAVA EXCEL ArrayList 2016.12.09 4389
82 날짜 시간 포맷 제어 자바 클래스 : JAVA DateUtils Date time file 2016.12.09 5233
81 자바 다양한 형변환. 그리고 아스키 코드 String char int : JAVA 2016.12.09 4188
80 자바 XML 제어 라이브러리 XStream : JAVA 2016.12.09 4917
79 원하는 패턴의 날짜 구하기 : JAVA 2016.12.09 3598
78 iBATIS 동적으로 맵핑하기 2016.12.09 3949
77 GET 파라메타 쿼리문자열 컨트롤 : getQueryString 2016.12.09 4705
76 접근 제한자 private/ protected/ public / default file 2016.10.06 5136
75 예외처리(Exception handling)방법 file 2016.09.21 4585
74 My-SQL 을 이용한 JDBC file 2016.09.21 4282
73 static멤버와 관련된 예제 2016.09.21 3768
72 파일 읽고쓰는 암호화/복호화 2016.09.21 7385
Board Pagination Prev 1 2 3 4 5 6 7 8 Next
/ 8

하단 정보를 입력할 수 있습니다

© k2s0o1d4e0s2i1g5n. All Rights Reserved