Programming/.NET

Stream은 추상클래스로서 프로그램에서 필요로하는 데이터의 입출력이 발생하면 그에 맞는 파생 클래스를 사용하여 데이터의 입출력을 처리할 수 있습니다. 아래는 Stream에서 파생되어 자주사용되는 클래스의 목록입니다.

 

 System.IO.FileStream

 파일관련 입출력에 사용됩니다.

 System.IO.MemoryStream

 스트림의 저장소를 메모리로하는 입출력에 사용됩니다.

 System.IO.UnmanagedMemoryStream

 MemoryStream와 같으나 비관리 메모리 접근을 지원합니다.

 System.IO.BufferedStream

 다른 데이터 입출력에서 버퍼처리를 추가하는데 사용됩니다.

 System.Net.Sockets.NetworkStream

 소켓통신을 통한 데이터 처리에 사용됩니다.

 System.Security.Cryptography.CryptoStream

 데이터를 암호화하여 입출력 처리하는데 사용됩니다.

 System.IO.Compression.GZipStream

 GZip형식의 데이터 압축을 지원합니다.

 System.IO.Compression.DeflateStream

 Deflate 알고리즘을 통한 데이터 압축을 지원합니다.

 System.Net.Security.NegotiateStream

 협정 보안프로토콜을 통한 클라이언트 인증과 서버의 선택적 인증을 지원합니다.

 System.Net.Security.SslStream

 SSL (Secure Socket Layer) 통신을 통한 서버의 인증과 선택적 클라이언트 인증을 지원합니다.

 

위 표에서 보듯 파일을 다루기 위한 기본 클래스는 System.IO.FileStream 클래스입니다. 이 클래스를 토대로 간단한 텍스트파일을 읽으려면 다음과 같이 예제를 작성할 수 있습니다.

 

System.IO.FileStream fs = new System.IO.FileStream(@"C:\test.txt", System.IO.FileMode.Open);

byte[] b = new byte[fs.Length];

fs.Read(b, 0, (int)fs.Length);
fs.Close();

string s = ASCIIEncoding.Default.GetString(b);

 

우선 스트림 데이터를 담기위한 바이트 배열이 필요한데 이때 바이트배열은 스트림의 length속성을 통해 스크림의 길이만큼 확보하도록 하고 이 배열을 Read메소드에 전달하여 읽어들인 데이터를 해당 배열에 저장하도록 합니다.

 

FileStream에서는 첫번째 매개변수로 파일명과 파일의 위치를 전달하고 두번째 매개변수로 FileMode의 Open 열거형 값을 전달해 파일열기를 지시합니다.

 

또한 스크림을 통해 데이터를 읽어오는데 성공하면 Close 메소드를 통해 해당 스트림을 명시적으로 닫아줘야 합니다. 아니면 다음과 같이 using문을 사용해도 동일한 결과를 얻을 수 있습니다.

 

using (System.IO.FileStream fs = new System.IO.FileStream(@"C:\test.txt", System.IO.FileMode.Open)) {
        byte[] b = new byte[fs.Length];
 
        fs.Read(b, 0, (int)fs.Length);
 
        string s = ASCIIEncoding.Default.GetString(b);
}

 

참고로 MSDN등의 문서상으로는 되도록 using문 사용을 권고하고 있습니다. using은 using문이 닫히는 시점에서 자동적으로 Dispose 메소드를 호출하는데 FileStream에서 Dispose 메소드가 호출되면 Close메소드로 같이 자동으로 호출됩니다.

 

using (System.IO.FileStream fs = new System.IO.FileStream(@"C:\test.txt", System.IO.FileMode.Append, System.IO.FileAccess.Write, System.IO.FileShare.Read, 

8, System.IO.FileOptions.None)) {
    byte[] b = System.Text.Encoding.ASCII.GetBytes("Hi");

    fs.Write(b, 0, b.Length);
    fs.Flush();
} 

 

위 예제는 기존 파일에 특정 내용을 추가하는 동작을 수행합니다. 우선 FileStream 클래스를 사용할때 매개변수부터 달라졌는데 FileMode와 더불어 FileAccess, FileShare, FileOptions 열거형이 추가되었습니다.

 

기존 FileMode는 파일의 생성및 추가, 열기등을 제어하고 FileAccess는 파일에 대한 읽기, 쓰기를 제어합니다. FileShare는 특정 파일을 다룰때 해당 파일에 접근하여 처리할 수 있는 작업을 제한하고 FileOpetions는 파일에 대한 임의, 순차접근, 암호화, 비동기쓰기등을 지원합니다.

 

결국 FileMode.Append는 파일에 대한 추가와 함께 FileAccess.Write로 쓰기작업을, 파일이 처리되는 동안 FileShare.Read로 읽기만을 허용하도록 하는 것입니다.

 

파일에 데이터를 쓰는 경우 특정 문자열에 대한 바이트 배열을 System.Text.Encoding.ASCII.GetBytes메소드로 가져와 바이트배열을 초기화 하고 Wirte 메소드로 해당 배열에 있는 데이터를 버퍼에 작성하도록 합니다. 그래서 Flush메소드로 버퍼링된 데이터를 원하는 파일에 실질적으로 기록될 수 있도록 해야 합니다.

 

다만 파일에 대한 FileStream클래스의 Close메소드를 명시적으로 호출하는 경우 Flush메소드는 자동적으로 호출됨으로 스트림에 대한 닫기와 Flush는 같이 수행할 필요가 없습니다.(예제에는 Flsuh호출이 있지만 이는 빠져도 무관합니다.)

 

참고로 MemoryStream은 FileStream과 목적하는 저장소만 다를 뿐 처리방식은 완전히 동일하므로 위 예제에서 FileStream을 MemoryStream으로 바꾸고 FileStream 클래스를 호출할때의 매개변수만 제거하면 메모리를 스트림으로 하는 동작이 완벽하게 구현됩니다.

 

Stream 클래스는 파일에 대한 작업과 함께 네트워크 통신을 위한 스트림 데이터 처리용으로도 많이 사용됩니다. 네트워크 통신을 위한 스트림 클래스는 System.Net.Sockets.NetworkStream 입니다.

 

우선 간단히 NetworkStream으로 TCP/IP를 통해 데이터를 받아오는 부분을 살펴보겠습니다.

 

int buffer = 1024;

byte[] read_byte = new byte[buffer];

System.Net.Sockets.TcpClient client = new System.Net.Sockets.TcpClient("cliel.com", 1212);
System.Net.Sockets.NetworkStream ns = client.GetStream();

int size = ns.Read(read_byte, 0, buffer);
string response = System.Text.Encoding.ASCII.GetString(read_byte, 0, size);

MessageBox.Show(response);

 

우선 받아올 만큼의 바이트배열을 생성하고 TcpClient 클래스로 서버쪽에의 데이터를 받아오도록 합니다. 예제에서는 cliel.com 으로 서버를 지정했지만 IP로도 가능하며 두번째 매개변수에 통신할 포트를 지정합니다.

 

원하는 서버로의 포트를 통해 데이터를 받아오면 TcpClient클래스의 GetStream메소드를 통해 데이터 스트림을 받아와 NetworkStream클래스의 Read메소드로 받아온 데이터를 바이트배열에 담고, 이 후 인코딩으로 바이트이 들어간 스트림값을 가져오면 됩니다.

 

받대로 데이터를 쓰는 경우는 Read메소드 대신 Write메소드를 호출합니다.

 

byte[] write_byte = ASCIIEncoding.Default.GetBytes("me" + Environment.NewLine);
ns.Write(write_byte, 0, write_byte.Length);

'Programming > .NET' 카테고리의 다른 글

[ASP.NET] WCF - 2  (0) 2016.09.07
[ASP.NET] WCF - 1  (0) 2016.08.31
[C#] Stream  (0) 2016.08.24
[ASP.NET] 개인화(Personalization)  (0) 2016.08.16
[ASP.NET] 서버 컨트롤 - 2 (렌더링)  (0) 2016.08.09
[ASP.NET] 서버 컨트롤 - 1 (기본생성)  (0) 2016.08.01
0 0