www.Jabook.org에서 제공되는 있는
소설같은 자바I 에서의 스트림 부분입니다. 위의 사이트에서.. 더 많은
스트림 내용을 보실 수 있을 실 겁니다! ^^
스트림이란?
스트림이란 장치, 생각하기 쉽게 하드웨어장치라고 하죠. 장치로부터 데이터를 얻거나 보낼 때 사용되는 중간 매개체 역할을 하는 놈입니다. 곰곰히 생각하면, 별로 어려운 것도 아닌데 스트림이 어렵다고 하는 것은 아마도 스트림의 종류가 많고 다양하기 때문일 것입니다. 하지만, 그 정확한 뜻을 알고 있다면 스트림은 대단히 쉬워집니다.
스트림! 이 스트림은 여러분들을 도와주는 아주 훌륭한 도구입니다. 여러분이 하드웨어를 어케 알겠습니까? Computer Engineering쪽도 아닌데. 저 또한 마찬가지 아니겠습니까? 그런데, 우리는 하드웨어 장치를 몰라도 그 쪽에 할건 다 하고 있습니다. 이것을 해결해 주는 것이 바로 스트림이죠. 누군가가 미리 장치에 연결할 수 있는 방법을 만들어 둔 것입니다. 어떻게 장치에 스트림을 연결하느냐가 문제지 사용하는 방법은 별로 어렵지 않습니다. 장치에 스트림만 연결되면 하는 일은 뻔하거든요. 장치로부터 데이터를 읽어들이거나 기록하거나 둘중에 하나죠뭐. 스트림에서 읽고 쓰는 것을 빼면 아마 스트림은 시체가 되고도 남을 것입니다. 물론 모든 장치가 하드웨어계열은 아닙니다. 하드웨어 계열에 이러한 방법을 사용해 보고 괜찮다 싶으니까 이곳 저곳에 스트림을 막 만들어 두는 것이지요. 스트림은 입력과 출력을 도와주는 매개역할을 하는 것이니, 입력과 출력이 관련된 곳이면 어디서든 등작을 하는 것 아니겠습니까?
스트림의 종류는 아주 다양하게 분류되어지고 있습니다. 이유는 아주 단순하죠. 데이터의 입출력장치가 여러 종류이니 스트림의 종류도 여러 종류라고 말할 수 있습니다. 단순히 분류하자면 입력과 출력 스트림으로 나누어 생각해 볼 수 있습니다. 그리고 입력이든 출력이든 각각의 입출력 장치에 해당하는 스트림이 거의 대부분 한쌍으로 되어 있습니다.
만약 파일에 데이터를 읽고 기록하고자 한다면, 여러분은 당연히 파일에 관련된 스트림을 찾을 것입니다. 자바에서 파일스트림은 FileInputStream과 FileOutputStream이 있습니다. 입력이든 출력이든 목표지점을 정확하게 주어야 파일을 읽고 기록할 것입니다. 파일 입.출력스트림에 목표지점(파일이름)을 주고 난 후 스트림을 생성하고, 기록을 하든지 읽어 들이든지 둘 중에 하나겠죠. 거짓말같지만 자바 스트림이 하는 일은 이것밖에는 없습니다. 특별한 것은 없습니다.
스트림을 설명하고자 할 때 다음과 같은 비유가 가장 좋은 것 같군요
n 스트림은 데이터를 읽고 기록하는 중간역할을 한다.
n 스트림은 빨대다.
n 빨대는 음료수를 마시는 중간역할을 한다.
n 빨대는 입에 있는 음료수를 다시 내뱉는 중간역할을 한다.
n 스트림은 단 방향 빨대다. 음료수를 내뱉고 다시 마시려면 빨대가 2개 필요하다.
약간 지저분하긴 하지만 아주 탁월한 비유인 것 같습니다. 더 자세하게 입력과 출력을 나누어서 비교해 보도록 하겠습니다.
입력스트림 비교
n 입력 스트림은 데이터를 먼저 스트림으로 읽어 들입니다. 그리고 스트림에 존재하는 데이터를 하나씩 읽어 들일 수 있습니다.
n 음료수를 마실 때 빨대를 이용하여 음료수를 빨대에 모으고 빨대에 들어있는 음료수를 흡입합니다. 그러면 입안으로 음료수가 들어 올 것입니다.
출력스트림의 비교
n 출력스트림으로 데이터를 보냅니다. 그리고 출력스트림에 보낸 데이터를 비워 버립니다. 그렇게 되면 출력 스트림에 존재하던 데이터가 모두 목표지점에 저장됩니다.
n 입안에 있던 음료수를 빨대로 일단 보냅니다. 빨대에 들어 있는 음료수를 불어 버립니다. 그렇게 되면 음료수는 다시 컵안으로 들어가게 됩니다.
이러한 절차를 스트림으로 표현하면 다음과 같이 되어 질 것입니다.
n 목표로 하는 데이터를 정한다.
n 데이터에 맞는 스트림을 생성한다.
n 스트림클래스의 멤버메서드를 이용하여 쉽게 데이터를 핸들한다. 기록하거나 읽어들이거나, 보내거나 받거나!
위와 같이 스트림은 데이터의 중간자 역할을 합니다. 우리는 데이터의 목표지점이 네트웍의 어떠한 장소이든, 메모리이든 상관하지 않습니다. 다만 해당 데이터를 스트림으로 보내고 그리고 스트림에 존재하는 데이터를 읽어 들이거나 기록해 버리면 끝인 것입니다. 이것은 목표지점이 어디라도 상관없다는 이야기죠. 그리고, 복잡한 작업은 스트림이 알아서 해결해 준다는 의미입니다. 스트림이 없다면 직접 다 해야죠뭐. 자 그렇다면 스트림에는 어떤 종류의 스트림이 있는지를 알아 보도록 하죠.
9.1.2 스트림의 종류
스트림은 가장 최초의 분류를 당연히 입력과 출력 스트림으로 나눌 수 있습니다. 각각의 장치에 당연히 입력과 출력은 있으니 당연한 것 아니겠습니다.
기본적인 분류
n 입력 스트림(ex. FileInputStream, ObjectInputStream)
n 출력 스트림(ex. FileOutputStrea, ObjectOutputStream)
이 기본적인 분류는 각각의 장치에 쌍으로 입출력이 존재한다고 볼 수 있습니다. 그리고 이러한 분류는 사실 분류도 아니지요. 그렇다면 실제적인 분류는 어떠한 방식으로 나눌 수 있을까요? 가장 많이 나누는 분류는 보통 문자단위로 스트림을 처리하느냐, 바이트단위로 처리하느냐에 따라서 나누어집니다. 이러한 분류는 프로그램상에서도 구분이 확연히 드러 나고 있습니다.
현재 아래에 나타난 구조는 문자 스트림의 구성도 입니다. 일단 문자스트림은 최상위의 Reader와 Writer로 이루어져 있습니다. 그리고 거의 대부분의 스트림의 이름에 규칙이 있습니다. 자세히 한번 보시기 바랍니다.
그 규칙은 Reader 즉, 입력문자스트림은 대부분 Reader라는 단어가 붙어있습니다. 반대로 Writer 출력 문자 스트림에서 Writer라는 단어가 붙어 있습니다. 그렇다면, 이러한 결론을 내릴 수 있을 것입니다. Reader나 Writer가 붙는다면, 문자스트림의 한 종류다라고 생각하시면 편할 것입니다. 문자 스트림을 구분하라고 Reader와 Writer를 고의로 붙여 둔 모양입니다. 사실, 문자관련 스트림은 대부분 Reader와 Writer를 상속받죠. 그래서 그런것입니다.
다음으로 바이트 스트림의 구성도를 한번 보도록 하겠습니다.
위의 스트림은 바이트 스트림으로 이 스트림 또한 입력과 출력의 차이를 InputStream과 OutputStream으로 나누어 볼 수 있습니다. 그리고 문자 스트림에서와 같이 InputStream에는 대부분 InputStream이라는 꼬리말이 OutputStream에는 OutputStream이라는 꼬리말이 붙어 있습니다. 물론 아닌 놈도 몇 있는데 일단은 대부분 이 형식을 따르고 있으니 InputStream과 OutputStream이 붙어 있으면 바이트 스트림으로 보아도 좋을 것입니다.
스트림의 종류1
n 문자스트림: Reader나 Writer가 붙는다.
n 바이트스트림:InputStream과 OutputStream이 붙는다.
스트림의 종류는 아주 많습니다. 이러한 스트림을 전부 사용할 줄 안다면 다행이겠지만 이것을 모두 습득하기에는 역부족일 것입니다. 솔직히 종류가 너무 많습니다. 그렇다고 그냥 앉아 있을 수만은 없습니다. 일단은 나중에 사용하더라도 어떤 규칙이라도 찾아야 할 것입니다. 자 그렇다면 규칙을 찾아 보도록 하죠.
스트림에서 나타나는 규칙은 아주 단순합니다. InputStream과 Reader계열일 경우에는 읽어 들이는 메서드를 포함하고 있습니다. 그리고 OutputStream 과 Writer계열일 경우에는 기록하는 메서드를 포함 하고 있을 것입니다. InputStream과 OutputStream일 경우에는 바이트를 Reader와 Writer의 경우 문자를 다루는 메서드를 포함하고 있을 것입니다. 이것을 정리한다면 다음과 같이 나타낼 수 있을 것입니다.
스트림의 종류2
n 입력스트림: Reader나 InputStream
n 출력스트림:Writer나 OutputStream
입력계열의 스트림은 대부분 read라는 메서드를 포함하고 있습니다. 읽어 들인다는 의미겠죠. 다음은 입력스트림에 사용되는 메서드를 보여주고 있습니다.
입력스트림계열의 멤버메서드
바이트단위(InputStream)
n int read()
n int read(byte cbuf[])
n int read(byte cbuf[], int offset, int length)
문자단위(Reader)
n int read()
n int read(char cbuf[])
n int read(char cbuf[], int offset, int length)
출력계열의 스트림은 대부분 write라는 메서드를 포함하고 있습니다. 기록한다는 의미겠죠. 다음은 출력스트림에 사용되는 메서드를 보여주고 있습니다.
출력스트림계열의 멤버메서드
바이트단위(OutputStream)
n int write(int c)
n int write(byte cbuf[])
n int write(byte cbuf[], int offset, int length)
문자단위(Writer)
n int write(int c)
n int write(char cbuf[])
n int write(char cbuf[], int offset, int length)
이것은 단순히 입출력에 관한 규칙입니다. 다음은 문자스트림과 바이트스트림의 간단한 설명을 붙인 것입니다.
문자 스트림 클래스 |
바이트 스트림 클래스 |
설명 |
Reader |
InputStream |
문자/바이트 입력 스트림을 위한 추상클래스 |
BufferedReader |
BufferedInputStream |
문자/바이트 버퍼 입력, 라인 해석 |
LineNumberReader |
LineNumberInputStream |
문자/바이트 입력시, 라인 번호를 유지 |
CharArrayReader |
ByteArrayInputStream |
문자/바이트 배열에서 읽어들임 |
InputStreamReader |
|
바이트 스트림을 문자 스트림으로 변환 |
FileReader |
FileInputStream |
파일에서 바이트를 읽어들어 문자/바이트 스트림으로 변환 |
FilterReader |
FilterInputStream |
필터적용(filtered) 문자/바이트 입력을 위한 추상클래스 |
PushbackReader |
PushbackInputStream |
읽어들인 문자/바이트를 되돌림(pushback) |
PipedReader |
PipedInputStream |
PipedWriter/PipedOutputStream에서 읽어들임 |
StringReader |
StringBufferInputStream |
문자열에서 읽어들임 |
Writer |
OutputStream |
문자 출력 스트림을 위한 추상클래스 |
BufferedWriter |
BufferedOutputStream |
문자/바이트 스트림에 버퍼 출력, BufferedWriter는 플랫폼에서 사용하는 라인 구분자(line separator) 사용 |
CharArrayWriter |
ByteArrayOutputStream |
문자/바이트 스트림에 문자/바이트 배열 출력 |
FilterWriter |
FilterOutputStream |
필터적용(filtered) 문자/바이트 출력을 위한 추상클래스 |
OutputStreamWriter |
(none) |
문자 스트림을 바이트 스트림으로 변환 |
FileWriter |
FileOutputStream |
문자/바이트 스트림을 바이트 파일로 변환 |
PrintWriter |
PrintStream |
Writer/Streamdp 값과 객체를 프린트 |
PipedWriter |
PipedOutputStream |
PipedReader/PipedOutputStream에 출력 |
StringWriter |
(none) |
문자열 출력 |
이것을 외울 필요는 없겠죠. 어떻게 하다보면 알지도 모르니까요.
9.1.3 바이트스트림과 문자스트림
스트림의 가장 기본적인 분류는 다음과 같은 두 가지 종류가 있습니다.
n 바이트 스트림: 바이트, 바이트 배열
n 문자 스트림: 문자, 문자 배열, 문자열
바이트스트림부터 알아 보도록 하죠. 바이트 스트림은 데이터를 바이트단위로 주고 받는 것을 말합니다. 대표적인 바이트 스트림은 InputStream과 OutputStream이라고 배웠습니다. 그렇다면, InputStream과 OutputStream을 통과하는 단위는 당연히 바이트겠죠. 바이트가 뭔지 아십니까? 8bit의 이진 비트를 묶으면 바이트가 되죠. 바로 그 바이트입니다. 원래 데이터는 모두 바이트죠. 알고 보면 그림도 바이트들로 이루어져 있고, 텍스트도 바이트로 이루어져 있습니다. 그리고, 물론 zip이나 jar같은 압축파일도 일단은 바이트로 되어 있습니다. 이 바이트들이 적절하게 변환 되면 의미 있는 데이터가 되는 것이지요. 원시 바이트로 주고 받겠다는 것입니다. 그런데, 문자스트림은 뭘 보고 문자 스트림이라고 할까요?
자바에서 사용하는 문자방식은 두 바이트로 한 문자를 표현하는 유니코드방식입니다. 그래서, 바이트로 전송되어지는 것을 스트림에서 인코딩을 가하게 됩니다. 즉, 바이트를 문자로 가공을 한다는 말이죠. 이 인코딩은 문자스트림이 담당합니다. 아래의 그림은 스트림이 문자를 인코딩하는 것을 보여주고 있습니다.
첫댓글 양이 꽤 돼네여... ㅡㅡ;; 소설같은 자바 얘기는 많이 들었는데... 함 빌려봐야겠네여... ^^ 님 감사합니당~~~