스트림의 개념

Download Report

Transcript 스트림의 개념

9장 스트림(Stream)
스트림의 개념
- 컴퓨터 내부나 네트워크에서 단방향성을 갖고 흘러 다니는 바이트 형태의
데이터
- 데이터를 입출력 할 때 중간 매개체 역할
- 입출력의 대상이 되는 장치(파일, 키보드, 모니터, 마우스, 메모리, 네트워크,
프린터)에 상관없이 동일한 방법으로 자료를 처리
- 사용자의 요구에 따라서 자료의 변환도 가능
- 종류 : 바이트 스트림(Byte Stream) 과 문자 스트림(character Stream)
바이트 스트림(Byte Stream)
-
데이터를 바이트 단위로 주고받는 스트림
입력과 출력을 하나의 클래스에서 해결
Stream 클래스는 대표적인 바이트 스트림
Stream 클래스의 하위 클래스
클래스
설명
BufferedStream
버퍼를 이용해 스트림을 다루고, 주로 대용량의 데이터를 고속으로 처리할 때 사용
FileStream
파일 입출력에 관련된 스트림을 처리할 때 사용
MemoryStream
주기억장치에 스트림 데이터를 입출력할 때 사용
NetworkStream
소켓기반의 통신 프로그램에서 스트림 형태로 데이터를 주고받을 때 사용
문자 스트림(Character Stream)
-
데이터를 문자 단위로 주고받는 스트림
입력과 출력을 다른 클래스에서 해결
TextReader 클래스와 TextWriter 클래스를 상속해서 구현
TextReader 하위 클래스
- stringReader, streamReader
- TextWriter 하위 클래스
- StringWriter, streamWriter
Stream 클래스의 추상 멤버
- Stream 클래스는 추상 클래스
- 파일이나 입력/출력 장치에서 바이트 흐름을 추상적으로 나타냄
- 파생 클래스는 다른 형식의 입력 및 출력에 대한 일반 뷰를 제공
속성
설명
CanRead / CanSeek / CanWrite
현재 스트림에 대해 읽기, 탐색, 쓰기가 가능한지 확인
Length
현재 스트림의 길이를 바이트 단위로 환산
Position
현재 스트림의 위치를 결정
메소드
설명
Close
스트림을 닫고, 관련된 리소스(예 파일, 소켓 등)를 해제
Flush
버퍼에 저장된 데이터를 목적지에 전송하고, 버퍼를 비움
Read
현재 스트림에서 연속된 바이트를 읽어 들이고, 스트림의 위치를 읽어 들인 만큼 앞으
로 이동
ReadByte
Seek
현재 스트림에서 위치를 지정, SeekOrigin 열거형을 사용해 상대적인 위치를 지정
SeekOrigin.Begin => 스트림의 시작위치
SeekOrigin.Current => 스트림의 현재위치
SeekOrigin.End
=> 스트림의 마지막 위치
SetLength
스트림의 길이를 지정
Write
현재 스트림에 연속된 바이트를 쓰고, 스트림의 위치를 쓴 바이트 수만큼 앞으로 이동
WriteByte
FileStream 클래스
- File 기반의 스트림을 제공
- 새로운 파일을 생성하거나 변경, 삭제시 사용
- FileStream 클래스의 생성자
public FileStream(string filename, FileMode fm);
public FileStream(string filename, FileMode fm, FileAccess fa);
public FileStream(string filename, FileMode fm, FileAccess fa, FileShare fs);
- FileMode 열거형 값
메소드
설명
Append
파일이 존재하면 열고, 파일의 끝을 찾는다. 만약, 파일이 존재하지 않을 경우에는
새로운 파일을 생성
FileMode.Append 속성은 FileAccess.Write와 함께 사용
Create
파일이 없을 경우 새 파일 생성, 존재하면 기존 파일을 덮어쓴다.
CreateNew
새로운 파일을 생성하며, 파일이 존재하면 IOException 예외가 발생
Open
지정한 파일을 열도록 설정
OpenOrCreate
파일이 존재할 경우 파일을 열고, 아니면 새로운 파일 생성
- FileAccess 열거형 값
메소드
설명
Read
파일을 읽기 전용으로 열도록 설정
ReadWrite
파일을 읽기/쓰기 형태로 열도록 설정
Write
파일을 쓰기 전용으로 열도록 설정
- FileShare 열거형 값
메소드
설명
None
현재 파일에 대한 공유를 거부
Read
해당 파일에 대해 연속적인 파일 열기 요청을 허락
ReadWrite
해당 파일에 대해 연속적인 읽기/쓰기 형태의 열기 요청을 허락
Write
해당 파일에 대해 연속적인 파일 쓰기 요청을 허락
- 예) FileStream 클래스를 이용해 파일 생성 및 데이터 저장하기
class Program
{
static void Main(string[] args) {
//Example.txt 파일을 읽기/쓰기 형태로 생성
FileStream file = new FileStream("Example.txt",FileMode.OpenOrCreate, FileAccess.Write);
//1~127 사이의 아스키 코드를 Example.txt에 출력
for(int i=0; i<=127; i++) {
//Convert 클래스는 기본 데이터 형식을 다른 데이터 형식으로 변환
file.WriteByte(Convert.ToByte(i)); //
}
file.Close(); //파일스트림을 닫습니다.
}
}
//Example.txt 파일을 읽기 전용으로 읽어옴
file =new FileStream("Example.txt",FileMode.Open,FileAccess.Read);
for(int i=0; i<=127; i++) {
//파일내용을 바이트 단위로 읽어 화면에 출력
Console.Write(Convert.ToChar(file.ReadByte()));
}
file.Close(); //파일스트림을 닫습니다.
BufferedStream 클래스
- 내부적으로 입출력에 대한 버퍼 기능을 제공해주는 스트림
- 디폴트 버퍼 크기는 4096 바이트
- 생성자의 예
public BufferedStream(Stream stream);
public BufferedStream(Stream stream, int bufferSize);
- 예) BufferedStream 을 이용한 파일 읽고 쓰기
class program {
static void Main(string[] args){
byte [] data = new Byte[127];
//Example.txt 파일을 읽기/쓰기 형태로 생성
FileStream file = new FileStream("Example.txt", FileMode.OpenOrCreate,
FileAccess.Write);
//BufferedStream 개체 생성
BufferedStream bs = new BufferedStream(file);
for(int i=0; i<127; i++) {
data[i] = (byte)(i+1);
} //1~127사이의 아스키 코드를 Example.txt에 출력
bs.Write(data,0,data.Length);
bs.Close();
//Example.txt 파일을 읽기 전용으로 읽어옴
file = new FileStream("Example.txt",FileMode.Open,FileAccess.Read);
bs = new BufferedStream(file);
data = new byte[127];
}
}
bs.Read(data,0,127);
// 바이트 배열의 모든 바이트를 문자열로 디코딩
Console.WriteLine(Encoding.Default.GetString(data));
bs.Close();
MemoryStream 클래스
- 스트림 데이터를 파일이나 소켓 대신 메모리에 직접 출력
- MemoryStream 속성 및 메소드
메소드
Capacity
설명
스트림이 할당된 바이트 수
메소드
설명
GetBuffer
스트림 내용을 바이트 배열로 반환
ToArray
전체 문자열의 내용을 바이트 배열로 반환
WriteTo
MemoryStream의 모든 내용을 다른 스트림에 출력
- 예) MemoryStream 예제
class program {
static void Main(string[] args){
byte[ ] values = new byte [ ] {0,1,2,3,4,5,6,7,8,9};
Console.WriteLine("배열에서 읽어 화면에 출력");
foreach (byte b in values)
Console.Write(b+" ");
Console.WriteLine("");
Console.WriteLine("메모리 스트림에서 읽어 화면에 출력");
MemoryStream ms = new MemoryStream(values);
int temp = 0;
while( (temp = ms.ReadByte())!=-1 )
{ //메모리 스트림읽기
Console.Write(temp+" ");
}
Console.WriteLine("");
Console.WriteLine("메모리 스트림을 배열로 만들고 배열을 화면에 츨력");
byte[ ] result = ms.ToArray(); //메모리스트림을 배열로
foreach (byte b in result)
Console.Write(b +" ");
Console.WriteLine("");
}
}
StreamWriter 와 StreamReader 클래스
- 문자열 기반 데이터를 문장단위로 처리할 때 유용한 클래스
- WriteLine, ReadLine메서드를 제공하며 이를 이용하면 라인피드로 구분된
문장을 손쉽게 입출력
StreamWriter 속성 / 메소드
설명
BaseStream
백업 저장소의 인터페이스 역할을 하는 내부 스트림
Close
StreamWriter 개체를 종료
Flush
StreamWriter 버퍼의 모든 데이터를 해당 스트림에 전송
Write
해당 스트림에 1바이트 이상의 데이터를 전송
WriteLine
한 문장을 해당 스트림에 전송
StreamReader 메소드
설명
Close
StreamReader 개체를 종료
DiscasdBufferedData
StreamReader에 현재 기록된 데이터 삭제
Peek
다음 데이터를 스트림에서 제거하지 않고 반환
Read
StreamReader 스트림에서 하나 이상의 데이터 읽음
ReadBlock
블록 단위로 데이터 읽음
ReadLine
첫 번째 라인피드(줄바꿈) 문자까지 읽음
ReadToEnd
스트림의 끝까지 데이터 읽음
ToString
StreamReader 개체를 문자열 형태로 반환
- 예) 파일에 글을 저장한 후 다시 읽어들여 화면에 출력하는 예제
class program {
static void Main(string[] args){
string filename = "stream.txt";
// StreamWriter를 이용한 파일 쓰기
FileStream fs1 = new FileStream(filename, FileMode.Create);
StreamWriter w = new StreamWriter(fs1);
w.WriteLine("C# Programming");
w.WriteLine("StreamWrite and StreamReader");
w.WriteLine("Example");
w.Flush();
w.Close();
// StreamReader를 이용한 파일 읽기 및 화면에 출력
FileStream fs2 = new FileStream(filename,FileMode.OpenOrCreate,
FileAccess.Read);
StreamReader r = new StreamReader(fs2,System.Text.Encoding.Default);
r.BaseStream.Seek(0, SeekOrigin.Begin); //
while (r.Peek() > -1)
// while(sr.EndOfStream)
{
Console.WriteLine(r.ReadLine());
}
r.Close();
}
}
StringWriter 와 StringReader 클래스
-
string형의 문자열을 기록하거나 읽어낼 때 사용하는 클래스
StringReader의 Read 메서드를 사용해서 데이터를 읽음
StringWriter의 Write 메서드를 이용하여 스트림에 기록
StreamWriter, StreamReader클래스의 멤버 메서드와 유사
문자열을 StringReader 클래스로 읽고, 그것을 StringWriter 클래스를 사용해
스트림에 기록시킨 후 화면에 출력하는 예제 프로그램
class program {
static void Main(string[] args) {
string str = "C# Programming";
StringReader sr = new StringReader(str);
StringWriter sw = new StringWriter();
while((ch=sr.Read())!=-1)
sw.Write((char)ch);
Console.WriteLine("문자열 화면 출력: "+sw.ToString());
}
}
객체의 직렬화 및 역직렬화
-
직렬화 : 객체를 파일에 저장하기 위해 바이트 스트림으로 변환
역직렬화 : 파일로부터 읽은 바이트 스트림을 객체로 변환
직렬화는 애트리뷰트(SerializableAttribute 클래스)를 통해 구현
객체를 직렬화하려면 직렬화시키고자 하는 부분에 "[Serializable]"를 명시
직렬화시키지 않을 부분을 "[NonSerializable]"로 명시
예)
[Serializable] // ManInfo 클래스는 직렬화가 가능
class ManInfo
{
string name;
int age;
string phone;
[NonSerialzable]
string email; // email은 직렬화가 불가능
...
}
BinaryFormatter 클래스
-
객체를 이진 형식으로 serialize 및 deserialize
바이너리 형식 지원
파일 확장자 : bin
System.Runtime.Serialization.Formatters.Binary 네임스페이스에 포함
SoapFormatter 클래스
-
개체를 SOAP 형식으로 serialize 및 deserialize
SOAP(Simple Object Access Protocol) 형식 지원
파일 확장자 : xml
System.Runtime.Serialization.Formatters.Soap 네임스페이스에 포함
두 클래스의 멤버는 거의 동일
- Serialize 메서드 : 객체를 스트림으로 변환
- Deserialize 메서드 : 스트림을 객체로 변환
BinaryFormatter 를 사용하여 객체를 직렬화/역직렬화 시키는 절차
// 직렬화 과정
ManInfo f = new ManInfo(); // 직렬화시킬 객체를 생성
// 객체가 저장될 바이트 스트림을 생성
FileStream fs = new FielStream("test.bin", FileMode.Create);
BinaryFormatter bf = new BinaryFormatter(); // BinaryFormatter 객체를 생성
bf.Serialize(fs, f); // 객체 f를 바이너리 형식으로 직렬화
// 역직렬화 과정
// 파일에 대한 바이트 스트림을 생성
FileStream fs1 = new FileStream("test.bin", FileMode.Open);
BinaryFormatter bf1 = new BinaryFormatter(); // BinaryFormatter 객체를 생성
f = (ManInfo)bf1.Deserialize(fs1); // 파일로부터 읽은 객체를 역직렬화
ManInfo 클래스 객체를 바이너리 형식으로 직렬화 시키고, 직렬화된 파일을 역직
렬화 시키는 예제
[Serializable]
class ManInfo
{
string name;
int age;
string phone;
// email은 직렬화 불가능
[NonSerialized]
string email;
// 생성자
public ManInfo(string n, int a, string p, string e)
{
this.name = n;
this.age = a;
this.phone = p;
this.email = e;
}
// 객체에 들어 있는 데이터를 출력하는 메서드
public void ShowInfo()
{
Console.WriteLine("이름: {0}", name);
Console.WriteLine("나이: {0}", age);
Console.WriteLine("전화번호: {0}", phone);
Console.WriteLine("이메일: {0}", email);
}
}
class Program {
static void Main()
{
// 어레이 리스트 객체 생성
ArrayList al = new ArrayList();
// 객체를 저장할 수 있는 파일을 생성하고, 스트림 객체를 얻는다.
FileStream fs = new FileStream("test.bin", FileMode.Create);
// ManInfo 객체를 생성한다.
ManInfo f = new ManInfo("조해원", 25, "011-123-1234", "hwcho@suwon");
// 어레이 리스트에 첨가
al.Add(f);
// ManInfo 객체를 생성한다.
ManInfo f2 = new ManInfo("홍길동", 100, "000-123-1234", "kdhong@suwon");
al.Add(f2);
// 바이너리 형식으로 직렬화하기 위해서
BinaryFormatter bf = new BinaryFormatter();
// 어레이리스트 객체를 바이너리 형식으로 직렬화
bf.Serialize(fs, al);
al.Clear(); // 어레이리스트를 비운다.
// 객체가 저장되어 있는 파일을 열고, 그에 대한 스트림 객체를 얻는다.
FileStream fs1 = new FileStream("test.bin", FileMode.Open);
// 객체로 역직렬화하기 위해서
BinaryFormatter bf1 = new BinaryFormatter();
// 파일로부터 읽은 객체를 어레이리스트 객체로 역직렬화
al = (ArrayList)bf1.Deserialize(fs1);
//어레이리스트의 내용을 출력
foreach (ManInfo i in al)
i.ShowInfo(); fs1.Close();
}
}
ManInfo 클래스 객체를 SOAP 형식으로 직렬화시키고, 직렬화된 파일을 역직
렬화시키는 예제 프로그램
// 클래스 객체는 직렬화가 가능
[Serializable]
class ManInfo {
string name;
int age;
string phone;
// email은 직렬화 불가능
[NonSerialized]
string email;
// 생성자
public ManInfo(string n, int a, string p, string e)
{
this.name = n;
this.age = a;
this.phone = p;
this.email =e;
}
// 객체에 들어 있는 데이터를 알아보는 메서드
public void ShowInfo()
{
Console.WriteLine("이름: {0}", name);
Console.WriteLine("나이: {0}", age);
Console.WriteLine("전화번호: {0}", phone);
Console.WriteLine("이메일: {0}", email);
}
}
class Program {
static void Main()
{
// 어레이리스트 객체 생성
ArrayList al = new ArrayList();
// 객체를 저장할 수 있는 파일을 생성하고, 스트림 객체를 얻는다.
FileStream fs = new FileStream("test.xml", FileMode.Create);
// ManInfo 객체를 생성
ManInfo f = new ManInfo("조해원", 25, "011-123-1234", "hwcho@suwon");
// 어레이 리스트에 첨가
al.Add(f);
// ManInfo 객체를 생성
ManInfo f2 = new ManInfo("홍길동", 25, "011-123-1234", "kdhong@suwon");
al.Add(f2);
// Soap 형식으로 직렬화하기 위해서
SoapFormatter bf = new SoapFormatter();
// 어레이리스트 객체 바이너리 형식으로 직렬화
bf.Serialize(fs, al);
fs.Close();
al.Clear(); // 어레이리스트를 비운다.
// 객체가 저장되어 있는 파일을 열고, 그에 대한 스트림 객체를 얻는다.
FileStream fs1 = new FileStream("test.xml", FileMode.Open);
// 객체로 역직렬화하기 위해서
SoapFormatter bf1 = new SoapFormatter();
al = (ArrayList)bf1.Deserialize(fs1);
//어레이리스트의 내용을 출력
foreach (ManInfo i in al)
i.ShowInfo(); fs1.Close();
}
}