상세 컨텐츠

본문 제목

스트림

프로그래밍/JAVA

by 라제폰 2009. 1. 23. 16:55

본문

스트림

 

입력 자료가 오는곳 혹은 출력 자료가 가는곳을 갖는 순서화된 일련의 자료를 나타내는 추상적인 입출력 모델이다.

 

스트림 입출력 클래스의 종류

 

 입출력 자료 종류에 따른 스트림의 분류

- 바이트 스트림:(InputStream, OutputStream) 이진 자료 혹은 지역 문자 세트의 문자자료 입출력 방법 제공

- 문자스트림 ( Reader, Writer) : 유니코드 문자자료 입출력 방법 제공

 

입출력 장치 종류에 따른 스트림의 분류

- 입출력장치 종류 ( 파일, 네트워크 )에 따라 다른 스트림 클래스들에 의해 지원

- 동일한 입출력 방식을 제공하나 기본적인 입출력 기능만 제공

 

입출력 기능에 따른 스트림의 분류 ( 필터링 filtering )

- 기존의 스트림에 부가적인 입출력 기능을 추가하여 제공하는 스트림

- 문자세트 변환: InputStreamReader, OutputStreamWriter

- 자료값을 스트링 표현으로 출력 : PrintWriter, PrintStream

- 버퍼링

- 자료의 내부 표현 값을 그대로 입출력 : DataInputStream, DataOutputStream

- 객체 입출력 ObjectInputStream, ObjectOutputStream

 

입출력 장치 종류에 따른 바이트 스트림 클래스

 

입출력 장치 종류에 독립적인 방식으로 이진 자료의 입출력

 

read                     InputStream ( abstract )             InputSource

binary      <----    -  FileInputStream                         - File

data                      -  ByteArrayInputStream               - byte[]

                             - PipedInputStream                      - PipedOutputStream

 

wirte                     OutputStream ( abstract )           Output Destination

binary      <----     - FileOutputStream                       - File

data                       - ByteArrayOutputStream             - byte[]

                              - PipedOutputStream                   - PipedInputStream

 

입출력 하고자 하는 장치의 종류에 따라 적당한 클래스를 선택하여 객체를 만든다.

FileInputStream, FileOutputStream : 파일로 부터 바이트를 입출력 하게 해주는 클래스

ByteArrayInputStream, ByteArrayOutputStream : 메모리(바이트배열)을 파일처럼 입출력 하게 해주는 스트림 클래스

PipedInputStream, PipedOutputStream : 다른 스레드와 파일처럼 입출력 함으로써 자료 교환을 할수있게 해주는 스트림 클래스

System.out, System.in, System.err: 표준 입출력 , 오류 장치로 입출력하게 해주는 클래스

 

InputStream : 추상 바이트 입력 스트림 클래스

 

입력 원천지( 연관된 입력 장치 혹은 입력 스트림 객체)를 기억하고 이곳으로 부터의 이진자료를 읽어 들이고 제어할 수 있는 메소드를 제공하는 바이트 입력스트림 클래스의 추상 최상위 클래스

 

abstract int read()

: 다음 입력 바이트를 양수(0~255)로 반환 ( 입력의 끝을 나타내는 -1과 입력자료를 구분키위해)

 

int read(byte[] buf, int start=0, int len=buf.length)

1~len개의 다음 입력 바이트를 버퍼 buf로 읽어 들이고 , 실제로 읽어 들인 바이트 수를 반환

입력자료가 더 이상 없으면 -1을 반환

InputStream 클래스에 정의된 이 메소드는 read()를 호출한다.

InputStream의 대부분의 하위 클래스에서 read() 대신 이 메소드를 사용하면 효율성이 높아짐

 

int skip( long n)

0~n개의 다음 입력바이트를 버리고 실제로 버려진 바이트 개수를 반환

 

int available()

: read 메소드 호출이 멈추지 (blocking) 않으면서 곧바로 읽어들일수 있는 바이트 갯수

( read메소드가 블락킹 되는 경우를 피하고자 할때 사용 )

 

close()

: 이 입력스트림과 관련된 운영체제 자원(파일 디스크립터 등등)을 운영체제에 반환

한번의 close() 호출로 최초 입력원천지까지 close() 된다.

 

OutputStream : 추상 바이트 출력 스트림 클래스

 

출력 목적지를 기억하고 이곳으로 이진자료(바이트)를 출력하고 제어할 수 있는 메소드를 제공하는 바이트 입력 스트림 클래스의 추상 최상위 클래스

 

abstract write(int b)

:b 내에 최하위 바이트를 출력, 나머지 상위 바이트는 무시

 

write ( byte[] buf, int start=0, int len=buf.length )

: buf 내의 len개의 바이트를 출력

OutputStream클래스에 정의된 이 메소드는 write(int b)를 호출한다.

대부분의 하위 클래스에서 write 메소드 대신 이 메소드를 사용하여 효율이 높아짐

 

flush()

버퍼가 채워지기 전에 출력스트림의 내부 버퍼에 남아있는 자료를 연관된 출력 목적지로 모두 출력되게 한다.

내부적으로 버퍼를 갖는 하위 클래스가 있으며 이 경우 연관된 출력 장치로의 실제 출력이 버퍼가 채워질때 까지 지연될수 있다.

출력 목적지가 스트림 객체인 대부분의 하위클래스에서는 그객체의 flush()를 또한 호출한다.

한번의 flush()호출로 최종출력 목적지까지 출력자료가 출력

(이것이 안되있으면 전송됬다가 안됬다가 한다)

 

close()

이 출력 스트림과 관련된 운영체제 자원이 있으면 이를 운영체제에 반환한다.

한번의 close()호출로 최종 출력목적지 까지 close()

 

이 클래스에 정의된 메소드는 아무것도 하지 않는다

하위클래스에서 적절히 재정의 하여 사용하여야 한다.

 

public class System_In {
        public static void main(String[] args) throws Exception {
                for (int input; (input=System.in.read())!=-1; ) {
                        if (input=='x')  {
                                System.exit(0);
                        }
                        System.out.print("입력 : ");
                        if (input!=10 && input!=13)  {
                                System.out.write(input);
                                System.out.print(", ");
                        }
                        System.out.println(input);
                }
        }

}

a

입력 : a , 97

입력 : 13

입력 : 10

자바

입력 : ? , 192

입력 : ? , 218

입력 : ? , 185

입력 : ? , 217

입력 : 13

입력 : 10

 

13은 CR carrage_return 커서를 맨앞으로 옮김

10은 LF Line_Feed 로 커서를 다음줄로 옮김

print() : 97이라는 숫자를 "97"이라는 문자를 만들어서 출력

write() : a라는 97에 해당하는 코드값을 출력

한글입력시 이에대한 코드는 '?'로 나오며 한글 한자당 두개가 발생되는 것을 알수 있다.

 

read() 메소드는 실행 스레드를 blocking 한다. 즉 데이터가 들어올때 까지 무조건 기다린다는 뜻이다.

그러므로 입력받는 부분은 따로 스레드를 구성해야 다른 수행에도 영향을 미치지 않게된다.

blocking에 대한것은 네트워크 프로그래밍을 할때 고려되는 사항이므로 네트워크 프로그래밍에 대해서 배울때는 반드시 염두에 두고 있어야 할 사항이다.

 

파일 바이트 스트림 : FileInputStream, FileOutputStream

 

각각 입력원천지와 출력 목적지가 파일인 바이트 스트림 클래스

 

FileInputStream클래스

new FileInputStream(String name) throws FileNotFoundException

new FileInputStream(File file) throws FileNotFoundException

 

FileOutputStream클래스

new FileOutputStream(String name, boolean append=false) throws FileNotFoundException

: append가 false이면 기존파일의 내용의 사라지고 true이면 출력자료가 추가된다.

new FileOutputStream(File file) throws FileNotFoundException

 

import java.io.*;

class FileByteStreamTest
{   public static void main( String[] args )
        throws IOException
    {   InputStream in = new FileInputStream(args[0]);
        OutputStream out = new FileOutputStream(args[1]);
        int count = 0;
        for( int b; (b = in.read()) != -1; )
        {    ++count;
             out.write( b );
        }
        System.err.println(count + " 바이트 복사됨.");
        in.close();
        out.close();
    }
}

java FileByteStreamTest test.dat test.out

 

import java.io.*;

class FileByteStreamTest2
{   public static void main( String[] args )
        throws IOException
    {   InputStream in = new FileInputStream(args[0]);
        OutputStream out = new FileOutputStream(args[1]);
        int count = 0;
        byte buf[] = new byte[1024];
        for( int cnt; (cnt = in.read(buf)) != -1; )
        {    count += cnt;
             out.write( buf, 0, cnt );
        }
        System.err.println(count + " 바이트 복사됨.");
        in.close();
        out.close();
    }
}

 

표준 입출력

 

프로그램의 수정없이 운영체제가 제공하는 기능에 의해 다양한 입출력 장치로 입출력할수있다

 

표준 입출력 객체

InputStream System.in

PrintStream System.out

PrintStream System.err

 

프로그램을 수행 시작 할때 < > 기호를 사용하여 System.in System.out의 실제입출력 장치를 파일로 장치 재지정을 할수 있으며 | 을 사용하여 하나의 프로그램의 표준 출력이 다른 프로그램의 표준 입력이 되게 할수 있다.

import java.io.*;

class StdIOTest
{   public static void main( String[] args )
    {   int count = 0;
        try
        {   for(int b; (b = System.in.read()) != -1; count++)
                System.out.write( b );
        } catch( IOException ex )
        {   System.err.println( "입출력 오류: " + ex.getMessage() );
        }
        System.out.close();
        System.err.println(count + " 바이트 복사됨.");
    }
}

java StdIOTest

abc (엔터)

abc

가나 (엔터)

가나  ( ctrl-Z or ctrl-D)

11바이트 복사됨

 

java StdIOTest > test.out

abc (엔터)

가나 (엔터)

( ctrl-Z or ctrl-D)

11바이트 복사됨

 

java StdIOTest < test.out > test2.out

11바이트 복사됨

 

입출력 장치 종류에 따른 문자 스트림 클래스

 

구조적으로 바이트 기반스트림과 별로 다르지 않지만 최소 단위가 바이트가 아니라 char이라는 점이 눈에 뜨인다.

캐릭터 기반스트림이기 때문에 write(String str), write(String str, int off, int len)처럼 스트링을 처리할수 있는 메소드가 있다.

 

모든 캐릭터 기반 스트림 클래스들은 java.io.FileReader, java.io.FileReader를 제외하고는 모두 생성자의인자로 java.io.Reader, java.io.Writer를 제공받는다.

 

 

 

java.io.InputStreamReader(InputStream in)

java.io.InputStreamReader(InputStream in, String enc)

java.io.OutputStreamWriter(outputStream out)

java.io.OutputStreamWriter(outputStream out, String enc) 

 

모든 캐릭터 기반 스트림들은 java.io.Reader와 java.io.Writer로 시작하며 바이트 기반 스트림을 캐릭터 기반 스트림으로 이어주기 위해서는 java.io.InputStreamReader,java.io.OutputStreamReader가 필요

 

import java.io.*;
  
public class CharacterStreamTest {
        public static void main(String[] args) throws IOException {
                File imsiFile=File.createTempFile("imsi", ".tmp");
                imsiFile.deleteOnExit();
 
                FileWriter fw=new FileWriter(imsiFile);
                BufferedWriter bw=new BufferedWriter(fw);
 
                for (int i=0; i<args.length; i++) {
                        bw.write(args[i]);
                        bw.newLine();
                }
 
                bw.close();
                System.out.println(imsiFile+" 에 썼습니다.");
 
                FileReader fr=new FileReader(imsiFile);
                BufferedReader br=new BufferedReader(fr);
 
                System.out.println(imsiFile+" 에서 읽어들입니다.");
                for (String readLine; (readLine=br.readLine())!=null; ) {
                        System.out.println(readLine);
                }
                br.close();
        }
}

 

입출력 장치 종류에 독립적인 방식으로 유니코드 문자 자료의 입출력(이들중 일부클래스는 인코딩)

 

                 Reader ( abstract )                          input source

read          - InputStreamReader                       - InputStream

text               - FileReader                                 - file

data          - CharArrayReader                          - char[]

                 - StringReader                                - String

                 - PipedReader                                - PipedWriter

 

                 Writer ( abstract )                             output destination

write          - outputStreamWriter                        - outputStream

text               - FileWriter                                    - file

data          - CharArrayWriter                             - char[]

                 - StringWriter                                   - String

                 - PipedWriter                                   - PipedReader

 

Reader: 추상 문자 입력 스트림 클래스

 

입력 원천지를 기억하고 이곳으로 부터 유니코드 문자자료(char,char[],String자료형등)를 읽어들이고 제어할 수 있는 메소드를 제공하는 문자 입력 스트림

 

int read()

다음 입력 유니코드 문자를 0~65535(0x00~0xffff)범위의 해당코드값으로 반환

입력자료가 더이상 없으면 -1을 반환

 

abstract int read( char [] buf, int start =0, int len = buf.length )

1~len개의 다음 입력 유니코드 문자를 버퍼 buf 로 읽어 들이고 실제로 읽어들인 유니코드 문자개수를 반환 . 입력자료가 더이상 없으면 -1을 반환

 

int skip (long n) : 1-n개의 다음 입력문자를 버리고 실제로 버려진 문자개수를 반환

 

boolean Ready()

: 다음 read()메소드의 호출이 멈추지 않고 곧바로 반환될 수 있으면 true

read가 블락킹 되는 경우를 피하고자 할대 사용

 

abstract close()

 

Writer : 추상 문자 출력 스트림 클래스

  

출력 목적지를 기억하고 이곳으로 유니코드 문자자료 ( char, char[], String 자료형의 문자)를 제어할 수 있는 메소드를 제공하는 문자 입력 스트림 클래스의 추상 최상위 클래스( 출력 목적지가 바이트 스트림인 경우, 유니코드 문자자료로 부터 바이트 자료로 변환을 함으로서 유니코드 문자를 출력할수 있게 해준다.

 

write(int b)

:b 내의 최하위 2바이트(유니코드 코드값)에 해당하는 유니코드 문자를 출력, 나머지 상위 바이트는 무시

 

abstract write(char[] buf, int start=0, int len=buf.length)

: 버퍼 buf내의 len개의 유니코드 문자를 출력.

Writer 클래스에 정의 된 이 메소드(재정의 메소드가 아닌) write(int b)를 호출하는 것으로 구현된다.

 

abstract flush()

: 내부적으로 버퍼를 갖는 하위클래스가 있으며 이 경우 연관된 출력장치로의 실제 출력이 버퍼가 채워질때 까지 지연될 수 있다.

출력 목적지가 스트림 객체인 모든 하위 클래스에서, 그 객체의 flush()를 또한 호출한다.

한번의 flush()를 또한 호출한다. 한번의 flush()로 최종 출력 목적지 까지 출력자료가 출력되게 한다.

 

abstract close()

 

파일 문자 스트림 : FileReader, FileWriter

 

유니코드 문자를 디폴트 문자 인코딩의 바이트와 변환하여 파일과 입출력

 

★ FileReader클래스

: 화일에 저장된 바이트가 디폴트 문자 인코딩으로 인코딩 되어 있다고 가정하고 유니코드 문자로 변환하여 입력

new FileReader(String name) throws FileNotFoundException

new FileReader(File file) throws FileNotFoundException

 

★ FileWriter클래스

: 출력할 유니코드 문자를 디폴트 문자 인코딩의 바이트로 변환하여 화일에 저장

new FileWriter(String name, boolean append=false) throws IOException true이면 추가저장

new FileWriter(File file) throws IOException

 

import java.io.*;
class FileCharStreamTest
{   public static void main( String[] args ) throws IOException
    {   Reader in = new FileReader(args[0]);
        Writer out = new FileWriter(args[1]);
        int count = 0;
        for(int ch; (ch = in.read()) != -1; count++)
            out.write(ch);
        System.err.println(count + " 문자 복사됨.");
        out.close();
    }
}

java FileCharStreamTest test.dat test.out

 

문자 스트림과 바이트 스트림과의 연결

 

바이트 스트림이 주어진 경우 이를 문자 스트림과 연결시켜 유니코드 문자가 입출력 할 수 있다.

바이트 스트림의 문자 인코딩을 지정함 으로써 지정된 문자 인코딩과 유니코드와의 인코딩 변환을 하게 할수 있다.

디폴트 인코딩과 관계없이 특정 문자 인코딩으로 변환되어 입출력 되어야 하는 경우에는 이와 같이 인코딩을 지정할 수 있는 방법을 사용해야 한다.

 

FileReader와 FileWriter는 디폴트 문자 인코딩만이 사용된다.

 

read

text    < ------------ InputStreamReader <---------- InputStream

data

          text data           character set            text data        

       ( in Unicode)       conversion             ( in any encoding)

write

text     ------------> OutputStreamReader --------  > OutputStream  

data

 

new InputStreamReader(InputStream in, String encoding=default encoding)

new OutputStreamWriter ( OutputStream out, String encoding=default encoding )

 

import java.io.*;

class ByteCharStreamTest
{   public static void main( String[] args )
        throws IOException
    {   InputStreamReader in = new InputStreamReader( System.in );
        OutputStreamWriter out = new OutputStreamWriter( System.out );
        int count = 0;
        for(int ch; (ch = in.read()) != -1; count++)
            out.write(ch);
        out.close();
        System.err.println(count + " 문자 복사됨.");
     }
}

 

메모리 스트림

 

: 바이트 배열, 문자배열, 문자열을 파일처럼 입력

스트림 모델의 입출력 방식이 지원되지 않믄 클래스에서 다양한 스트림 입출력 기능을 이용 할수 있다.

 

객체 직렬화등을 이용하여 바이트 배열과 입출력하고, 그 바이트 배열을 RandomAcessFile, java.net.DatagramSocket등에서 입출력 한다.

( 크기를 미리 알 수 없는 자료를 모두 읽어들인 후에 자료를 가공하고자 할 때에 유용하다. )

 

ByteArrayInputStream 클래스

- new ByteArrayInputStream( byte[], int offset=0, int length=buf.length)

 

CharArrayReader 클래스

- new CharArrayReader(char buf[], int offset =0 , int length= buf.length)

 

StringRader 클래스

- new StringReader(String str)

 

ByteArrayOutputStream 클래스

- new ByteArrayOutputStream( int initialCapacity= 디폴트)

int size() : 버퍼에 출력된 총 바이트 개수

byte[] toByteArray() : 버퍼의 내용을 바이트 배열에 복사하여 반환

String toString( String encoding=디폴트 인코딩) : 바이트 배열내의 문자가 encoding 인코딩으로 인코딩 되어 있다고 가정하고 유니코드 문자열인 스트링으로 변환하여 반환

 

CharArrayWriter 클래스

- new CharArrayWriter( int initialCapacity=디폴트)

int size() : 버퍼에 출력된 총 바이트 개수

byte[] toByteArray() : 버퍼의 내용을 바이트 배열에 복사하여 반환

String toString() : 버퍼의 내용을 스트링으로 변환하여 반환

writeTo(Writer out ) : 다른 문자 출력 스트림 out으로 버퍼의 내용을 모두 출력

 

StringWriter 클래스

- new StringWriter(int initialCapacity=디폴트)

StringBuffer getBuffer() : 내부 버퍼 객체를 그대로 반환(복사하지 않고)

String toString() : 버퍼의 내용을 스트링으로 변환하여 반환

 

import java.io.*;

class ByteArrayOutputStreamTest
{   public static void main( String[] args )
        throws IOException
    {   FileInputStream in = new FileInputStream(args[0]);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int count = 0;
        for(int b; (b = in.read()) != -1; count++)
             baos.write( b );
        System.out.print( baos.toString() );
        baos.close();
        System.out.close();
        System.err.println(count + " 바이트 읽음.");
    }
}

abc

가나

11 바이트 읽음

import java.io.*;

class MemoryCharStreamTest
{   public static void main( String[] args )
        throws IOException
    {   char[] arr = {'a', 'b', '한', '글'};
                     
        CharArrayReader in = new CharArrayReader(arr);
        StringWriter out = new StringWriter();
        int count = 0;
        for(int ch; (ch = in.read()) != -1; count++)
            out.write(ch);
        System.out.println(out.toString());
        System.err.println(count + " 문자 읽힘.");
    }
}

ab한글

4 문자 읽힘

 

입출력 기능에 따른 스트림의 분류( 필터링 )

 

read  <--   Input Filter         <-- Input Fliter          <-- InputStream

data           (readFloat())          ( buffering )                Reader

 

write  -->  Output Filter    -->  Outut Filter  --> OutputStream

data          ( Print() )               ( buffering )       Writer

 

기존의 스트림에 원하는 입출력 기능을 제공하는 스트림을 연결하여 새로운 스트림을 만든다.

- 자료를 문자열 표현으로 출력

- 버퍼링 : 효율적인 입출력

- 다중연결(Concatenating) : 여러개의 입력스트림을 하나의 스트림으로 만든다.

- 되돌림 (pushbacking) : 현재의 입력의 줄 번호를 기억해 준다.

- 자료를 내부 표현 그대로 입출력

- 객체의 내용을 입출력

 

read         <-- InputStream (abstract)    <--- input Source

binary        -BufferedInputStream                  -inputStream

data           -SequenceInputStream               -InputStream's

(byte)         -PushBackInputStream               -InputStream

                  -ObjectInputStream                     -InputStream

 

write          --> OutputStream ( abstract )  ---> output destination

binary        -BufferedOutputStream                   - OutputStream

data           -PrintStream                                   - OutputStream

                  -DataOuputStream                         - OutputStream

                  -ObjectOutputStream                     - OutputStream

 

read          <-- Reader ( abstract )         <-- input Source

text                - BufferedReader                   - Reader

data              - LineNumberReader              - Reader

                    - PushBackReader                 - Reader

 

write        --> Writer ( abstract )             --> output Destination

text             - BufferedWriter                      - Writer

data            - PrintWriter                           - Writer

 

스트림을 제어하는 필터 스트림

 

Filter류의 클래스들은 다른 스트림을 자신안에 놓고 이 스트림을 이용해서 다른 역할을 해준다

 

자료를 문자열 표현으로 출력 : PrintWriter, PrintStream

 

자료형에 따라 그 값을 사람이 이해할 수 있는 String 표현으로 자료의 값을 출력

 

PrintWriter 클래스

PrintWriter( writer out, boolean autoflush=false)

new PrintWriter(OutputStream out, boolean autoflush = false)

: 출력할 문자열을 디폴트 문자 인코딩의 바이트 열로 반환하여 출력한다.

print( type data )

println ( type data )

: 각 타입에따라 적절한 형태의 문자열로 변환 출력되도록 중복 정의 되어있다.

해당 객체의 toString() 메소드를 호출하여 그 반환문자열을 출력

println()

: 플랫폼의 디폴트 행 분리자 ( line.separator 시스템 프로퍼티 값 )을 출력스트림에 첨가

boolean checkError()

:출력중에 오류가 발생하였으면 true, PrintWriter는 자주 사용되므로 메소드가 입출력 예외를 발생시키는 대신 이 메소드를 이용하여 오류가 발생했는 지를 검출할 수 있도록 하였다.

이 스트림객체가 autoflush를 true로 하여 생성 되었으면 flush()를 자동적으로 호출함

 

PrintStream클래스

가능하면 PrintWriter 클래스를 사용한다.

디버깅에 편리하다. (System.out System.err가 PrintStream 클래스이다 )

import java.io.*;
class PrintWriterTest
{   public static void main( String[] args )
        throws IOException
    {   PrintWriter out = new PrintWriter( new FileWriter(args[0]) );
        out.println("PI = " + Math.PI);
        out.println("E = " + Math.E);
        out.close();
    }
}

 

버퍼링 ( Buffering Stream ) 스트림

 

내부 버퍼를 제공함으로써 효율성을 높인다.

BufferedReader, BufferedWriter의 경우에는 해당 운영체제에 적합한 행단위의 입출력 기능도 제공

 

버퍼링 입력 스트림

 

자료 입력 메소드 <-- 버퍼링 입력스트림 (내부버퍼) <-- 출력 스트림

 

- 입력 메소드가 필요로 하는 양 만큼 내부 버퍼에서 자료를 제공한다.

- 내부 버퍼가 비었을 경우, 연결된 스트림으로 부터 한번에 내부 버퍼를 가득 채운 후 자료를 제공

- 연결된 입력 스트림으로 부터의 입력 횟수를 줄인다.

   연결된 입력 스트림의 입력 메소드 실행시간이 상대적으로 느릴때 효과적

 

버퍼링 출력 스트림

 

자료 출력메소드 --> 버퍼링 출력스트림 (내부버퍼) --> 출력 스트림

 

- 출력 메소드의 출력 자료를 버퍼에 저장한다.

- 내부 버퍼가 가득 찼을경우  연결된 스트림으로 부터 한번에 내부 버퍼의 자료를 한번에 모두출력

- 연결된 입력 스트림으로 부터의 출력 횟수를 줄인다.

   연결된 입력 스트림의 입력 메소드 실행시간이 상대적으로 느릴때 효과적

 

BufferedInputStream 클래스

- new BufferedInputStream(InputStream in, int bufSize=디폴트)

 

BufferedOutputStream 클래스

- new BufferedOutputStream(OutputStream out, int bufSize=디폴트)

 

BufferedReader 클래스

- new BufferedReader ( Reader in, int bufSize-디폴트)

- String readLine()

   한 행의 문자열을 읽어서 '행 분리자' 문자열을 버리고 나머지 문자열을 반환한다.

   '행 분리자 문자열은 "\n", "\r", "\r\n" 중 어떠한 형태라도 인식한다.

 

BufferedWriter 클래스

- new BufferedWriter(Writer out, int bufSize=디폴트)

- newLine()

   해당 운영체제의 '디폴트 행 분리자' 문자열("line.separator"시스템 프로퍼티 값) 을 출력

import java.io.*;

class BufferedStreamTest
{   public static void main( String[] args )
        throws IOException
    {   BufferedReader in
            = new BufferedReader(new FileReader(args[0]));
        BufferedWriter out
            = new BufferedWriter(new FileWriter(args[1]));
        int count = 0;
        for(String line; (line = in.readLine()) != null; count++)
        {   out.write(line);
            out.newLine();
        }
        out.close();
        System.err.println(count + " 행 복사됨.");
    }
}

사이즈 윈 11, 솔라리스 9

 

되돌림 스트림 ( PushBacking )

 

이미 입력된 바이트나 문자를 스트림으로 되돌릴 수 있는 스트림.

문법 분석기(parser), 컴파일러등을 만드는데 사용될 수 있다.

 

-------------------------

  PushbackInputStream          new PushbackInputStream(InputStream in, int bufSize = 1)

  buffer [n]                  <---    unread(int b)

                                              unread( byte[] buf, int start=0,intlen=buf.length )

  input  source(inputStream)  ---> read

--------------------------

 

-------------------------

  PushbackReader                 new PushbackReader(InputStream in, int bufSize = 1)

  buffer [n]                  <---    unread(int b)

                                              unread( byte[] buf, int start=0,intlen=buf.length)

  input  source(inputStream)  ---> read

--------------------------

import java.io.*;
class PushbackReaderTest
{   public static void main( String[] args ) throws IOException
    {   PushbackReader in
            = new PushbackReader(new FileReader(args[0]), 2);
        System.out.print((char) in.read());
        in.unread('가');

        in.unread('x');
        for(int i = 0; i < 3; ++i)
            System.out.print((char) in.read());
        System.out.close();
    }
}

java PushbackReaderTest test.dat

ax가b

 

일반 스트림은 단방향이기 때문에 절대로 되돌어가서 데이타를 읽지 못한다. (이를해결)

입출력을 작업시의 부하를 줄이기 위해 일정양의 데이터를 한번에 처리한다.

입출력작업은 최소로 하면서 원하는 데이터들은 최대한 많이 처리할 수 있게 한다.

import java.io.*;  
public class BufferedStreamTest {
        public static void main(String[] args) throws Exception {
                if (args.length<1) {
                        System.out.println("사용법 : java BufferedStreamTest 파일이름");
                        System.exit(1);
                }
                FileInputStream fis=new FileInputStream(args[0]);
                BufferedInputStream bis=new BufferedInputStream(fis);
 
                System.out.println("스트림 되돌리기 가능 : "+bis.markSupported());
                bis.mark(1024);
 
                for (int i=0; i<10; i++) {
                        System.out.write(bis.read());
                }
 
                bis.reset();
                System.out.println("\nreset() 호출");
                for (int i=0; i<20; i++) {
                        System.out.write(bis.read());
                }
        }
}

markSupported() : 스트림이 되돌리기가 가능한지 판별

mart(int limit) : 쉽게 말해서 찜을 해주는 메소드로 reset() 메소드가 호출되었을때에는 읽어들일 포인터는 이찜을 해둔곳으로 바뀌게 된다.

limit는 찜을 해둔곳으로 부터 몇 바이트가까지 읽어 들이기 전까지는 찜이 유효하다는 뜻이된다.

 

입력스트림을 일련의 토큰(Token Sequence) 으로 변환

 

입력 스트림을 문법 분석(parsing)을 통하여 토큰으로 변환

토큰은 공백문자로 분리되는 다음과 같은 것들중의 하나이다.

단어 (word) : obj

숫자 (number) : 123, -123, 123.34

스트링 ( String ) : "abc", 'abc'

보통문자 (ordinary charatcter) : + , -

줄 주석 (line comment) : // 자바 소스에서 처럼 줄 끝까지 무시한다.

 

------------------------

  StreamTokenizer                  new StreamTokenizer(Reader in)

  input source( inputStream)  

  int ttype

      int TT_WORD                     nextToken() --> ttype value(int)

      int TT_NUMBER               <------ pushBack()

      int TT_EOL

      int TT_EOF

  String sval ( String )

  double nval ( number)

  current line number : int       ---> lineno()

-------------------------

 

import java.io.*;

class StreamTokenizerTest
{
    public static void main( String args[] )
    {   FileInputStream infile = null;
        try
        {   Reader in = new FileReader( args[0] );
            StreamTokenizer token = new StreamTokenizer(in);
            token.eolIsSignificant(true);
            int ttype;
            while ( (ttype = token.nextToken()) != StreamTokenizer.TT_EOF )
            {   switch( ttype )
                {   case StreamTokenizer.TT_WORD:
                        System.out.println( "TT_WORD: " + token.sval );
                        break;
                    case StreamTokenizer.TT_NUMBER:
                        System.out.println( "TT_NUMBER: " + token.nval +
                                            ", " + token.sval );
                        break;
                    case StreamTokenizer.TT_EOL:
                        System.out.println( "TT_EOL:");
                        break;
                }
            }
        } catch( IOException ex )
        {   System.err.println( "오류: 화일 읽기 실패" );
        }

        try
        {   if (infile != null)
                infile.close();
        } catch( IOException ex )
        { }
    }
}

 

★ 문자 분류 문법 바꾸기

wordChars( int low, int hi )

quoteChar ( int ch )

whitespaceChars(int low, int hi)

ordinaryChar( int ch)

commentchar(int ch)

slashSlashComments( boolean flag)

 

★ 문법 분석제어

parseNumbers()

lowerCaseMode(boolean flag)

eolIsSignificant(boolean flag)

 

★ 문법초기화

resetSyntax()

 

입출력 관련 기본 예외 클래스

 

java.io 및 java.net 패키지의 모든 예외 클래스는 java.io.IOException의 하위 클래스이다.

--> 이들 패키지에 정의된 예외는 IOException만 처리함으로서 모드 처리 할수 있다.

 

InterruptedIOException은 입출력(네크워킹 포함) 중에 Thread 클래스의 interrupt() 메소드가 호출되는 경우에도 발생 할 수 있다.

 

java.lang.Exception

 - IOException

    - FileNotFoundException

    - InterruptedIOException -- int bytesTransferred

    - UnsupportedEncodingException

    - CharConversionException

 

기본 자료형 자료의 내부 표현 입출력

 

기본 자료형으 자료를 내부 표현 그대로 입출력

1바이트 이상 차지하는 자료형의 자료는 상위 바이트 부터 입출력한다.(big Endian,network byte order)

 

PrintWriter 의 잇점

- 효율성 ( 더 적은 기억 공간과 더 빠른 입출력 )

- 정확한 입출력 ( 정보의 사소한 분실도 생기지 않음 )

 

-------------        -------------

OutputStream |       | DataOutput   |

(abstract)       |       | (Interface)    |

-------------        --------------

        |                                |

-----------------    <----+

DataOutputStream | new DataOutputStream(OutputStream out )    

output destination  |

(outputStream)      |

total number of      | ---> size()

written bytes: int    |

-----------------

 

-------------        -------------

InputStream |       | DataInput   |

(abstract)       |       | (Interface)    |

-------------        --------------

        |                                |

-----------------    <----+

DataInputStream | new DataInputStream(InputStream in )    

input destination  |

(inputStream)      |

-----------------

 

DataOutput 인터페이스

 

기본 자료형 자료의 내부 표현 출력을 위한 메소드 정의

메소드

write( int b)

writebyte( int b )

write( byte b[] )

write( byte b[], int off, int len )

writeShort(int v)

writeInt(int v)

writeLong(long v)

writeFloat(float v)

writeDouble(double v)

writeBoolean (boolean v)

writeChar( int v )

writeChars(String s)

writeUTF ( String str)

: 수정된 UTF-8 인코딩으로 출력한다. 자료를 출력하기 전에 인코딩후의 바이트 갯수를 2바이트로 맨 처음에 덧붙여 출력한다.

 

DataInput 인터페이스

 

기본 자료형 자료의 내부 표현 입력을 위한 메소드 정의

 

기본 자료형 내부표현 입력

byte readByte()

int readUnsignedByte()

readFully(byte buf[])

readFully(byte buf[], int off, int  len)

int skipBytes(int n)

short readShort()

int readUnsignedShort()

int readInt()

long readLong()

float readFloat()

double readDouble()

boolean readBoolean()

char readChar()

String readUTF() throws UTFDataFormatException

:수정된 UTF-8 인코딩의 바이트 자료을 읽어들여 문자열로 변환하여 반환 바이트 자료를 읽기전에 2바이트를 읽어 총 바이트 개수를 알아낸다.

 

★ 다른 InputStream, Reader 클래스의 입출력 메소드와의 차이점

자료가 완전히 읽혀지거나 skip 될 때 까지 스레드가 블락된다.

화일의 끝을 만나면 -1을 반환하지 않고 EOFException을 일으킨다.

 

import java.io.*;

class DataStreamTest
{   public static void main( String[] args ) throws IOException
    {   FileOutputStream fos = new FileOutputStream(args[0]);
        DataOutputStream dos = new DataOutputStream(fos);
        dos.writeDouble(Math.PI);  // 8 바이트 출력
        dos.writeChars("a가");     // 4 바이트 출력
        dos.writeUTF("a가");       // 6 바이트 출력
        dos.write("a가".getBytes());  // 3 바이트 출력
        dos.close();
        fos.close();

        FileInputStream fis = new FileInputStream(args[0]);
        DataInputStream dis = new DataInputStream(fis);
        System.out.println(dis.readDouble());
        System.out.print(dis.readChar());
        System.out.println(dis.readChar());
        System.out.println(dis.readUTF());
        byte[] buf = new byte[3];
        dis.readFully( buf );
        System.out.println(new String(buf));
        dis.close();
        fis.close();
    }
}

 

DataInputStream, DataOutputStream 클래스들은 byte, short, int, long같은 기본 데이터들에 대한 readByte(), readShort(), readLong()와 writeByte(int b), writeShort(int s), writeInt(int i),writeLong(long l)등의 메소드를 가지고 있습니다. 이 메소드들은 DataInput 과 DataOutput 인터페이스를 각각 구현 하기 때문에 존재한다.

주고 받을때 데이터 형이 일치하지 않으면 잘못된 결과가 나온다.

import java.io.*;  
  public class DataStreamTest {
        File imsiFile;
        public DataStreamTest() throws IOException {
                imsiFile=File.createTempFile("imsi", ".tmp");
                imsiFile.deleteOnExit();
        }
 
        public void writeData(int x, int y) throws IOException {
                FileOutputStream fos=new FileOutputStream(imsiFile);
                DataOutputStream dos=new DataOutputStream(fos);
 
                dos.writeInt(x);
                dos.writeInt(y);
                dos.writeInt(x*y);
                dos.close();
        }
        public void readData() throws IOException {
                FileInputStream fis=new FileInputStream(imsiFile);
                DataInputStream dis=new DataInputStream(fis);
 
                System.out.print(dis.readInt());
                System.out.print(" * ");
                System.out.print(dis.readInt());
                System.out.print(" = ");
                System.out.print(dis.readInt());
 
                dis.close();
        }
 
        public static void main(String[] args) throws IOException {
                if (args.length<2) {
                        System.out.println("사용법 : java DataStreamTest x y");
                        System.exit(1);
                }
 
                int x=Integer.parseInt(args[0]);
                int y=Integer.parseInt(args[1]);
                DataStreamTest dst=new DataStreamTest();
                dst.writeData(x, y);
                dst.readData();
        }
}

public static void createTempFile(String suffix, String prefix[,File dir])

: suffix는 임시로 만들 파일의 이름에 앞자리를 차지 하게 되는데 최소 3자리는 되어야 한다.

prefix는 확장자를 지정할 때 사용할수 있는데 null주면 자동으로 .tmp를 사용한다.

dir는 임시파일이 만들어진 디렉토리를 말하는데 지정해주지 않거나 null을 주면 기본 임시파일 디렉토리에 파일을 만들어 진다.

 

int 형 데이터가 4바이트이므로 12바이트가 저장되는데 char형 데이터를 저장할 때에는 데이터의 양의 유동적으로 UTF-8이라는 유니코드의 일종을 사용하기 때문에 ASCII에 해당하는 문자들은 전부 1바이트만을 차지하고 한글등은 3바이트를 차지하게 된다.

 

readLine()이라는 메소드를 쓸수는 있지만 한글등을 처리할때에는 문제가 생길수 있다.

여기서 DataOutputStream만 close() 시키면 FileOutputStream()까지 close() 시킬수 잇다.

 

import java.io.*;
class SequenceInputStreamTest
{   public static void main( String[] args ) throws IOException
    {   InputStream in = new SequenceInputStream(
            new FileInputStream(args[0]), System.in);
        OutputStream out = new FileOutputStream(args[1]);
        for(int b; (b = in.read()) != -1;)
            out.write(b);
        out.close();
    }
}

 

import java.io.*;

class PipeTest
{   public static void main( String[] args )
        throws IOException, InterruptedException
    {   PipedOutputStream pout = new PipedOutputStream();
        PipedInputStream pin = new PipedInputStream(pout);
        Thread writer1 = new WriterThread(pout, '0', '9');
        Thread writer2 = new WriterThread(pout, 'a', 'j');
        Thread reader1 = new ReaderThread(pin);
        writer1.start();
        writer2.start();
        reader1.start();
//        writer1.join();
//        writer2.join();
//        pout.close();
    }
}

class WriterThread extends Thread
{   private char first, last;
    private OutputStream out;
    public WriterThread(OutputStream out, char first, char last)
    {   this.first = first;
        this.last = last;
        this.out = out;
    }
    public void run()
    {   try
        {   for(int ch = first; ch <= last; ++ch)
            {   out.write(ch);
//                yield();
            }
        } catch( IOException e )
        {   e.printStackTrace(System.err);
        }
    }
}
            
class ReaderThread extends Thread
{   private InputStream in;
    public ReaderThread(InputStream in)
    {   this.in = in;
    }
    public void run()
    {   try {
            for(int ch; (ch = in.read()) != -1;)
            {   System.out.write(Character.toUpperCase((char) ch));
//                yield();
            }
        } catch( IOException e )
        {   e.printStackTrace(System.err);
        }
        finally
        {   System.out.flush();
        }
    }
}

 

자료 내부 표현 입출력 관련 예외클래스

 

IOException

  - UTFDataFormatException

  - EOFException

 

스트림 입출력 모델과 맞지 않는 입출력

 

무작위 접근 파일 : RandomAccessFile

- 하나의 파일을 동시에 읽고 쓸수 있다.

- 파일의 임의의 위체에 자료를 읽고 쓸수 있다.

- 파일만을 다룰수 있다.

 

윈도우 입출력 모델( 그래픽스, 마우스, 키보드) -> 윈도우 프로그래밍

네트워크 -> 소켓, 원격메소드 호출 , CORBA

 

직렬,병렬 포트 --> 자바 통신 패키지 사용 ( java communication API )

기타 주변기기 --> 네이티브 메소드 ( JNI ) 사용


관련글 더보기