.Net에서는 정보를 저장 또는 출력하는,
즉 1차원적인 데이터의 흐름을 의미한다.
스트림 자체는 논리적이기 떄문에 어떠한 물리장치에도 간섭받지 않고
키보드나 마우스, 모니터, 파일등 모든 장치에 대해 제어가 가능하다.
Stream은 입력스트림과 출력스트림으로 구분이 가능하고
또한 바이트스트림과 문자스트림으로도 구분이 가능하다.
- 입력스트립과 출력스트림
스트림은 기본적으로 입력스트림과 출력스트림으로 나눌 수 있으며
입력스트림은 Stream, TextReader, BinaryReader 클래스 등으로 나눌 수 있다.
출력 스트림은 Stream, TextWriter, BinaryWriter 클래스 등이 있다.
*Stream클래스는 입, 출력이 동시에 가능한 클래스이다.
*Stream, TextReader, TextWriter 은 추상클래스이므로
스스로 하는 작업보다는 파생클래스에서 구현하여 사용한다.
- 문자스트림과 바이트스트림
문자스트림과 바이트스트림은 스트림 처리단위를 기준으로 한 분류다.
문자스트림은 말 그대로 문자단위로 처리하고 바이트 스트림은 바이트 단위로 처리한다.
문자스트림은 TextReader와 TextWriter는 상속해서 구현한다,
TextReader은 StringReader로 확장되며, TextWriter은 StringWriter로 확장되어 사용된다.
- 종류)
TextReader, TextWriter : 문자스트림 계층 구조의 최상위 추상클래스
StreamReader : 입력 바이트스트림을 문자스트림으로 변환
StreamWriter : 출력 바이트스트림을 문자스트림으로 변환
StringReader : 문자열을 핸들하기 위한 입력 문자스트림
StringWriter : 문자열을 핸들하기 위한 출력 문자스트림
바이트스트림은 바이트단위의 데이터를 주고받는 스트림으로써
Stream클래스가 대표적인 예이다.
Stream은 입력과 출력을 하나의 클래스에서 처리하며, Stream클래스를 상속하여
구현한 모든 스트림들은 바이트스트림이 된다.
그리고 대부분의 바이트스트림 클래스의 이름에는 Stream이라는 이름이 붙는다.
- 종류)
Stream : 스트림 계층 구조의 최상위 추상 기본클래스
BufferedStream : 바이트스트림에 버퍼 기능의 추가
FileStream : 파일 I/O에 사용
MemoryStream : 메모리에 사용
문자 스트림이든 바이트스트림이든 모두 처음엔 바이트로 받아들인다.
그리고 받아들인 스트림이 용도에 맞게 변환을 시켜주게 된다.
결국 각각의 스트림은 방법과 장치만 다를 뿐 데이터를 읽고 기록하는 것은 같다.
* BufferedStream 클래스
버퍼는 메모리의 바이트 블록으로써 데이터를 저장하여 불필요한 자원의
사용을 최소화한다. 그리고 이런 버퍼를 사용하면 읽기 및 쓰기 성능이 좋아진다.
이런 버퍼를 읽기 및 쓰기 모두 사용 할 수는 있지만 동시에 사용하는 것은 안된다.
이럴때 BufferedStream의 Read와 Write메서드는 버퍼를 자동으로 유지관리한다.
BufferedStream는 특정형식의 스트림으로 구성할 수 있다.
다르 형식으로 읽고 쓰려면 BinaryReader 및 BinaryWriter를 사용한다.
BufferedStream 은 버퍼가 필요하지 않을 때 버퍼로 인해 입/출력 속도가 저하되지
않도록 한다. 버퍼에 데이터를 쌓아두다가 데이터의 입력이 끝나면
한꺼번에 데이터를 파일에 입출력한다.
그래서 비교적 빠른 속도를 낸다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Threading.Tasks;
using System.IO;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
byte[] data = new byte[127];
FileStream file = new FileStream("Example.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite);
BufferedStream bs = new BufferedStream(file);
for (int i = 0; i < 127; i++)
{
data[i] = (byte)(i + 1);
}
bs.Write(data, 0, data.Length);
bs.Close(); // 이 부분이 빠지면 IOException 이 뜬다.
file = new FileStream("Example.txt", FileMode.Open, FileAccess.Read);
bs = new BufferedStream(file);
data = new byte[127];
bs.Read(data, 0, 127);
Console.WriteLine(System.Text.Encoding.Default.GetString(data));
bs.Close();
}
}
}
* MemoryStream
MemoryStream은 이름처럼 메모리에 기록하고 불러오는 것이다.
메모리에 데이터를 기록하고 원하는 데로 수정하고 출력하는 것이다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Threading.Tasks;
using System.IO;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
MemoryStream ms = new MemoryStream();
ms.Capacity = 20; // 메모리 스트림 크기 지정
ms.Position = 0; // 스트림의 위치를 시작부분으로 이동
byte[] data = Encoding.Default.GetBytes("blog.houkibosi.com");
ms.Write(data, 0, data.Length); // byte배열을 메모리 스트림에 출력
ms.Position = 3; // 메모리 스트림에서 4번째 위치로 이동
ms.WriteByte((byte)71); // 4번째 데이터를 71-A 로 변경출력
data = ms.GetBuffer(); // 메모리 스트림 전체 내용을 byte배열로 반환
Console.WriteLine(Encoding.Default.GetString(data)); // 화면에 문자열로 변경해서 출력함.
}
}
}
* GZipStream
GZipStream은 간단히 말해 데이터를 압축하고 압축을 푸는 클래스다.
GZipStream은 파일을 손실없이 압축하거나 암축을 풀기위해 gzip데이터 형식을 사용한다.
이 형식에는 데이터 손상을 감지하기 위한 순환중복검사 값이 포함된다.
(gzip은 4g이상의 데이터는 지원하지 않는다.)
*GZipStream을 상속하는 경우 CanSeek, CanWrite, CanRead 멤버를 재정의해야한다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Threading.Tasks;
using System.IO;
using System.IO.Compression;
namespace ConsoleApplication3
{
public class GZipTest
{
public static int ReadAllBytesFromStream(Stream stream, byte[] buffer)
{
// Use this method is used to read all bytes from a stream.
int offset = 0;
int totalCount = 0;
while (true)
{
int bytesRead = stream.Read(buffer, offset, 100);
if (bytesRead == 0)
{
break;
}
offset += bytesRead;
totalCount += bytesRead;
}
return totalCount;
}
public static bool CompareData(byte[] buf1, int len1, byte[] buf2, int len2)
{
// Use this method to compare data from two different buffers.
if (len1 != len2)
{
Console.WriteLine("Number of bytes in two buffer are different {0}:{1}", len1, len2);
return false;
}
for (int i = 0; i < len1; i++)
{
if (buf1[i] != buf2[i])
{
Console.WriteLine("byte {0} is different {1}|{2}", i, buf1[i], buf2[i]);
return false;
}
}
Console.WriteLine("All bytes compare.");
return true;
}
public static void GZipCompressDecompress(string filename)
{
Console.WriteLine("Test compression and decompression on file {0}", filename);
FileStream infile;
try
{
infile = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
byte[] buffer = new byte[infile.Length];
int count = infile.Read(buffer, 0, buffer.Length);
if (count != buffer.Length)
{
infile.Close();
Console.WriteLine("Test Failed: Unable to read data from file");
return;
}
infile.Close();
MemoryStream ms = new MemoryStream();
GZipStream compressedzipStream = new GZipStream(ms, CompressionMode.Compress, true);
Console.WriteLine("Compression");
compressedzipStream.Write(buffer, 0, buffer.Length);
// Close the stream.
compressedzipStream.Close();
Console.WriteLine("Original size: {0}, Compressed size: {1}", buffer.Length, ms.Length);
// Reset the memory stream position to begin decompression.
ms.Position = 0;
GZipStream zipStream = new GZipStream(ms, CompressionMode.Decompress);
Console.WriteLine("Decompression");
byte[] decompressedBuffer = new byte[buffer.Length + 100];
// Use the ReadAllBytesFromStream to read the stream.
int totalCount = GZipTest.ReadAllBytesFromStream(zipStream, decompressedBuffer);
Console.WriteLine("Decompressed {0} bytes", totalCount);
if (!GZipTest.CompareData(buffer, buffer.Length, decompressedBuffer, totalCount))
{
Console.WriteLine("Error. The two buffers did not compare.");
}
zipStream.Close();
} // end try
catch (InvalidDataException)
{
Console.WriteLine("Error: The file being read contains invalid data.");
}
catch (FileNotFoundException)
{
Console.WriteLine("Error:The file specified was not found.");
}
catch (ArgumentException)
{
Console.WriteLine("Error: path is a zero-length string, contains only white space, or contains one or more invalid characters");
}
catch (PathTooLongException)
{
Console.WriteLine("Error: The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters.");
}
catch (DirectoryNotFoundException)
{
Console.WriteLine("Error: The specified path is invalid, such as being on an unmapped drive.");
}
catch (IOException)
{
Console.WriteLine("Error: An I/O error occurred while opening the file.");
}
catch (UnauthorizedAccessException)
{
Console.WriteLine("Error: path specified a file that is read-only, the path is a directory, or caller does not have the required permissions.");
}
catch (IndexOutOfRangeException)
{
Console.WriteLine("Error: You must provide parameters for MyGZIP.");
}
}
public static void Main(string[] args)
{
string usageText = "Usage: MYGZIP <inputfilename>";
//If no file name is specified, write usage text.
if (args.Length == 0)
{
Console.WriteLine(usageText);
}
else
{
if (File.Exists(args[0]))
GZipCompressDecompress(args[0]);
}
}
}
}
* NetworkStream
'Hoons.Net > C#' 카테고리의 다른 글
| 캠퍼스 시삽 과제 6-1) 쓰레드의 개념과 닷넷에서 지원하는 쓰레드 (0) | 2012.08.27 |
|---|---|
| 캠퍼스 시삽 과제 5-1) Delegate (0) | 2012.08.23 |
| 캠퍼스 시삽 과제 3-2) 컬렉션 점찍어 출력하기(Parallel Ver.) (0) | 2012.08.13 |
| 캠퍼스 시삽 과제 3-2) 컬렉션 점찍어 출력하기(While Ver.) (0) | 2012.08.13 |
| 캠퍼스 시삽 과제 3-2) 컬렉션 점찍어 출력하기(StringBuilder Ver.) (0) | 2012.08.10 |