記錄

JAVA) Stream 본문

Computer language/JAVA

JAVA) Stream

surhommejk 2018. 2. 14. 15:23

Stream


개요

Stream은 연결통로, 입출력통로, 중간매개체와 '빨대'에 비유하면 이해하기가 쉽다. 빨대의 지름보다 작은 것은 쉽게 빨대를 통해서 섭취할 수 있다. 즉, 빨대 내를 이동할 수 있는 것은 빨대의 지름보다 작은 것에 한정된다. 그런 의미에서 Stream은 기본적으로 1Byte의 크기까지만 다룰 수 있는 제한된 크기를 갖고 있다. 쉽게 말해서 1Byte단위로 Byte 배열을 보내고 받을 수 있다는 것이다.


I/O (InputStream / OutputStream)

InputStream과 OutputStream은 모두 API내에서 추상 클래스로 저장되어 있다. 따라서 혼자 힙에 올라갈 수 없고 반드시 상속 후 Override를 한 뒤에 힙에 올라갈 수 있다. 그래서 사용을 할 때에는 입출력 용도에 맞는 Stream으로 재정의 하여 사용하게 된다.


Target에 따른 클래스

Target이 Memory인 경우 : ByteArrayInputStream, ByteArrayOutputStream

Target이 File인 경우 : FileInputStream , FileOutputStream


Buffer

(추가적인 보조 클래스로 성능향상도모, 추후 업로드)




public class Ex01_Stream {
    public static void main(String[] args) {
        // Memory (배열)
        // byte (-128 ~0 127) : 정수값
        byte[] inSrc = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
        byte[] outSrc = null; // outsrc 메모리를 가지고 있지 않다

        
        ByteArrayInputStream input = new ByteArrayInputStream(inSrc);
        // read()를 지니고 있는 input을 생성
        // 읽어들일 byte[]의 주소값을 생성시 파라미터로 설정해야한다
        // 파라미터로 설정하는 과정은 먹을 Target에 빨대를 꽂는 과정과도 같다
        
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        // write()를 지니고 있는 output을 생성

        int data = 0;
        while ((data = input.read()) != -1) {
            output.write(data);}
        // read()기능이 반복되면서 하나하나 data에 대입이 되고
        // 이를 output의 write기능을 통해 buffer에 넣는 과정이다
        
        // read()는 내부적으로 next()처럼
        // 커서가 계속 이동하는 기능을 가지고 있다

        outSrc = output.toByteArray();
        /*
        toByteArray
        Creates a newly allocated byte array.
        Its size is the current size of this output stream and
        the valid contents of the buffer have been copied into it.
        
        Returns:the current contents of this output stream, as a byte array!
        */
        
        System.out.println(Arrays.toString(outSrc));
        // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 가 출력된다

    } // end-main
} // end-class



//대상 : File (read , write) : 물리적인 파일
//FileInputStream , FileOutputStream
//txt 기반 작업 : C:\\Temp\\a.txt >>HELLO

public class Ex02_POINT_File_Read_Write {
    public static void main(String[] args) {

        FileInputStream fs = null;
        FileOutputStream fos = null;
        // 이렇게 밖에서 선언을 해주고 생성을 try 내에서 해주는 이유는
        // try에서 생성을 해버리면 finally에서 close를 못하기 때문이다
        // 왜냐면 try가 끝나면서 fs가 없어져버리기 때문!

        String path = "C:\\Temp\\a.txt";
        try {
            fs = new FileInputStream(path);
            // read()의 경로를 생성시 파라미터로 부여
            // Target에 빨대 꽂는 기능

            fos = new FileOutputStream("C:\\Temp\\new.txt");
            // 보낼 Target에 빨대 꽂는 기능
            // FileOutputStream 클래스는 Temp 폴더안에 new.txt 가 존재하지 않으면
            // 파일 생성까지 할 수 있다 그 후 생성된 파일에 write 쓰기 작업

            /*
            
            FileOutputStream
            public FileOutputStream(String name, boolean append) throws FileNotFoundException
            
            Creates a file output stream to write to the file with the specified name.
            If the second argument is true, then bytes will be written to
            the end of the file rather than the beginning.
            
            */
            
            int data = 0;
            while ((data = fs.read()) != -1) {
                fos.write(data);
                // write()을 통해서 미리 설정한 Target에 write 처리
            
            }
        } catch (Exception e) {
                // read에서 예외처리해줘야 할 이유는 파일이 미존재시 프로그램 종료될 수 도 있어서
                // 그래서 Stream생성 예외와 파일 미존재 예외 모두를 담기 위해서
                // 최상위 예외 클래스인 Exception으로 e 를 만들어 주는 것이다
            
            System.out.println(e.getMessage());
        } finally {
            try {
                fos.close();
                fs.close();
                // POINT : I/O 작업은 대부분 가비지 컬렉터의 대상이 아니다
                // 명시적으로 자원을 해제 작업을 한다 (함수 : close() -> 소멸자 함수 호출)
            
            } catch (Exception e) {
                // close 에서 예외처리 이유는 쓰지도 않았는데 close일까봐
                e.printStackTrace();
            }
        }

    }

}




public class Ex03_Stream_File {
    public static void main(String[] args) {

        String orifile = "C:\\Temp\\shinsaegyung.jpeg";
        String targetfile = "copy.jpeg";

        FileInputStream fis = null;
        FileOutputStream fos = null;

        try {
            fis = new FileInputStream(orifile);
            // 읽어들일 Target에 빨대 꽂는 기능
            
            fos = new FileOutputStream(targetfile);
            //보낼 Target에 빨대 꽂는 기능

            int data = 0;
            while ((data = fis.read()) != -1) {
                fos.write(data);
                // byte단위로 읽어서 미리 설정한 경로에
                // write 처리
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                fis.close();
                fos.close();
                // 자원해제
                
            } catch (Exception e) {
            }
        }
    } // end-main
} // end-class



public class Ex04_Stream_File_Buffer {

    public static void main(String[] args) {

        /*
         *
         * BufferedInputStream public BufferedInputStream(InputStream in)
         *
         * Creates a BufferedInputStream and saves its argument, the input stream in,
         * for later use. An internal buffer array is created and stored in buf.
         * Parameters:in - the underlying input stream.
         *
         * >> API설계 자체상 이미 파라미터로 InputStream을 생성하여 넣어주지 않으면 생성 자체가 불가능
         * 즉, 보조적인 역할이라는 설계에서부터 알 수 있다.
         *
         */

        FileOutputStream fos = null;
        BufferedOutputStream bos = null;

        try {
            fos = new FileOutputStream("data.txt"); // 파일 생성 기능 가지고 있다
            bos = new BufferedOutputStream(fos);

            for (int i = 0; i < 10; i++) {
                bos.write('A');
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        } finally {
            try {
                
                bos.close();
                // buffer의 안에 내용이 8kbyte 차면 자동으로 전달 후 비운다
                // 그래서 용량이 다 차지 않고 프로그램이 종료되면 아무것도 전달되지 않고 종료가 된다
                // 따라서 buffer를 강제로 비우기 위해서 close를 하는 것이다
                // close가 buffer를 비우는 기능을 하는 것은 아니고
                // 내부에 bos.flush() 기능을 가지고 있어서 close() 실행시 자동으로 flush()를 call
                
                /*
                
                java buffer 크기 : 8kbyte => 8192Byte
                1.buffer 안에 내용이 8kbyte 채우면 자동 으로 비운다
                2.buffer 강제로 비우는 방법 : flush() 강제 호출
                3.bos.close(); 내부에서 flush() 호출
                
                */
                
                fos.close();
                                
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }
}



//한글 2Byte -> Stream 통한 통신 불가 (Byte 단위)
//2Byte 문자 -> Reader , Writer 추상 클래스
public class Ex05_Reader_Writer_kor {
    public static void main(String[] args) {
        FileReader fr = null;
        FileWriter fw = null;
        try {
            fr = new FileReader("Ex01_Stream.java");
            fw = new FileWriter("copy_Ex01.txt"); // 파일 생성 기능도 내재되어 있다

            /*
            
            public class FileReader extends InputStreamReader
            
            Convenience class for reading character files.
            The constructors of this class assume that the default character encoding and
            the default byte-buffer size are appropriate.
            To specify these values yourself, construct an InputStreamReader on a FileInputStream.
            FileReader is meant for reading streams of characters.
            For reading streams of raw bytes, consider using a FileInputStream.



            public class FileWriter extends OutputStreamWriter
            
            Convenience class for writing character files.
            The constructors of this class assume that the default character encoding and
            the default byte-buffer size are acceptable.
            To specify these values yourself, construct an OutputStreamWriter on a FileOutputStream.
            Whether or not a file is available or may be created depends upon the underlying platform.
            Some platforms, in particular, allow a file to be opened for writing by only one FileWriter
            (or other file-writing object) at a time.
            In such situations the constructors in this class will fail if the file involved is already open.
            
            FileWriter is meant for writing streams of characters.
            For writing streams of raw bytes, consider using a FileOutputStream.
            
            */
            
            int data = 0;
            while ((data = fr.read()) != -1) {
                // System.out.println(data + " : " + (char)data);
                fw.write(data);
            }

        } catch (Exception e) {

        } finally {
            try {
                fw.close();
                fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }

}



import java.io.*;

public class filetest {

    public static void main(String[] args) {

        FileInputStream fis = null;
        FileOutputStream fos = null;
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;

        try {

            fis = new FileInputStream("C:\\Temp\\shinsaegyung.jpeg");
            fos = new FileOutputStream("MyShin2.jpeg");
            // 반드시 여기서 fis, fos를 먼저 생성해주고 그 뒤에
            // bis, bos에 파라미터로 들어간다는 것을 숙지!!
            // 코드 실행 순서상 매우 상식적인 부분이다
                        
            bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(fos);
            
            int data = 0;
            
            while ((data = bis.read()) != -1) {
                bos.write(data);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {

            try {
                bis.close();
                bos.close();
                fos.close();
                fis.close();
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

    }

}



cf)

Stream들을 close() 해주는 이유?


예를 들어 네트워크 환경에서 내가 엑셀작업을 하고 있는데 다른 사람이 이 파일을 수정하고 싶다고 하자. 하지만 내가 작업중인 경우 수정 권한이 없다. 따라서 내가 손을 떼야(프로그램을 꺼야) 타인이 수정을 할 수 있다. close()는 이 예시에서 내가 손을 뗀다(프로그램을 끈다)는 행위와 같다.

'Computer language > JAVA' 카테고리의 다른 글

JAVA) CMD내 TREE 기능 구현  (0) 2018.02.19
JAVA) Map.Entry와 entrySet()  (1) 2018.02.14
JAVA) ' .equlas ' 와 ' == ' 의 차이  (0) 2018.02.13
JAVA) Down Casting  (0) 2018.02.09
JAVA) 컬렉션 프레임워크(Collection Framework)  (0) 2018.02.09
Comments