프로그래밍을 하다 보면, 이진 파일을 읽거나 써야할 때가 생깁니다.

이럴 때 System.IO 네임스페이스에 있는 스트림 클래스를 사용하면 아주 쉽게 해결이 가능합니다.


System.IO 네임스페이스에 있는 클래스 중 Writer 으로 끝나는 것들은 모두 쓰기를 지원하는 스트림입니다.

예외적으로, BufferedStream 이나 MemoryStream의 경우엔 스트림에 쓴 값을 배열로 바꾸고 쓰기 가능한 스트림에

배열을 복사함으로써 쓰기가 가능하게 됩니다.


일단.. 이 글에서는 FileStream 만을 다루려고 합니다.

FileStream 을 사용하는 것은 매우 간단합니다.


System.IO 네임스페이스를 임포트 한다음, FileStream 클래스에 대한 개체 생성. 그리고 쓰기 작업

이게 끝입니다. 어때요? 참 쉽죠??


FileStream 클래스에 대한 개체는 어떻게 생성하느냐?

 FileStream fs = new FileStream(@"C:\testfile.bin", FileMode.Create);


이런식으로 가능합니다.

C 드라이브 밑에 testfile.bin이란 파일을 만드는데, Create는 파일이 있으면 파일을 비운 후 쓰고, 없다면
새로운 파일을 만들어라~ 라는 의미를 가지고 있겠습니다~

이게 끝입니다.
이제는 FileStream 의 Write, WriteByte 메서드만 호출해주면 끝입니다. 그러면 알아서 바이트 값이 써질 터이니~ 허허허
그러면 스트림에 값을 우째 쓰느냐!

Write 메서드의 경우 바이트 배열을 스트림에 쓸 수가 있고,
WriteByte 메서드의 경우 단일 바이트를 스트림에 쓸 수가 있습니다.

더 많은 설명을 원하신다면, 아래의 MSDN 문서를 참고하시기 바랍니다.


그리고, Encoding 클래스를 이용하여 문자를 쓸 수도 있습니다.

Byte[] asciiBytes = System.Text.Encoding.ASCII.GetBytes("Hello world!");
Byte[] uniBytes = System.Text.Encoding.Unicode.GetBytes("안녕 세상!");


System.Text를 쓰는 것이 귀찮다면, System.Text 네임스페이스를 임포트 함으로써 더 간단하게
Encoding.Unicode, Encoding.Ascii 와 같은 형식으로 사용하실 수가 있습니다.


그럼 한번 실전으로 가보죠.

예제에 사용된 코드입니다.

using System;
using System.IO;
using System.Text;

namespace BinaryWriting {
    class Program {
        public static void Main(string[] args) {
            Console.WriteLine("파일이 저장될 위치를 입력하세요:");
            String path = Console.ReadLine();
            
            try {
                FileStream fs = new FileStream(path, FileMode.Create);
                
                // 단일 바이트 쓰기
                fs.WriteByte(0x01);
                fs.WriteByte(0x23);
                fs.WriteByte(0x45);
                fs.WriteByte(0x67);
                fs.WriteByte(0x89);
                fs.WriteByte(0xAB);
                fs.WriteByte(0xCD);
                fs.WriteByte(0xEF);
                
                Byte[] asciiByte = Encoding.ASCII.GetBytes("ASCII string to byte!");
                Byte[] uniByte = Encoding.Unicode.GetBytes("유니코드 문자열을 바이트로 변환!");
                
                // ASCII 바이트 쓰기
                fs.Write(asciiByte, 0, asciiByte.Length);
                
                // 줄바꿈 (\r\n)
                fs.WriteByte(13);
                fs.WriteByte(10);
                
                // UNICODE 바이트 쓰기
                fs.Write(uniByte, 0, uniByte.Length);
                
                // 위치를 처음으로!
                fs.Position = 0;
                
                // 단일 바이트를 총 8회 읽습니다.
                for ( Int32 i = 0; i < 8; i++ ) {
                    Byte readSingleByte = (Byte) fs.ReadByte();
                    Console.WriteLine("읽은 바이트 (0x{0:X4}): {1:X2}", fs.Position, readSingleByte);
                }
                
                Byte[] dummyAsciiByte = new Byte[asciiByte.Length];
                Byte[] dummyUniByte = new Byte[uniByte.Length];
                
                // 쓴 ASCII 바이트를 읽고 출력해보자!
                fs.Read(dummyAsciiByte, 0, dummyAsciiByte.Length);
                Console.WriteLine("읽은 ASCII 바이트: {0}", Encoding.ASCII.GetString(dummyAsciiByte));
                
                // 줄바꿈 문자(\r\n)는 건너뛴다. 
                fs.ReadByte();
                fs.ReadByte();
                
                // 쓴 UNICODE 바이트를 읽고 출력해보자!
                fs.Read(dummyUniByte, 0, dummyUniByte.Length);
                Console.WriteLine("읽은 UNICODE 바이트: {0}", Encoding.Unicode.GetString(dummyUniByte));
                
                // 작업이 끝났으니 파일을 저장하고 닫는다!
                fs.Close();
                
            } catch (Exception ex) {
                Console.WriteLine("작업 도중 예외가 발생했습니다!\n예외 메세지: {0}", ex.Message);
            }
            
            Console.WriteLine("아무 키나 누르면 종료합니다!");
            Console.ReadKey(true);
        }
    }
}


그리고! 예제의 실행 결과는 이렇습니다.


c:\testfile.bin 파일의 내용은 어떨까요?

각각 메모장에서 연 것과 16진수로 본 파일의 내용은 이렇습니다.


메모장 내용:

줄바꿈이 된 것을 확인하실 수 있습니다.


16진수 내용:




사진을 보시면 아시겠지만, 0x0 ~0x7 부분은 단일 바이트를 01, 23, 45, 67, 89, AB, CD, EF 를 8개 썼는데

정말로 8바이트가 정확하게 들어가 있는것을 알 수 있습니다.

ASCII 문자열의 경우 그대로 들어가 있는 것을 확인할 수 있고, UNICODE 문자열의 경우 깨져서 나오네요.

하지만! 저건 바이트대로 쓴 것이기 때문에 2바이트 문자는 깨질 수 밖에 없지요.

그래서 Encoding 클래스를 이용하여 바이트를 문자로 변환하면! 깔끔한 한국어가 나오게 되는 거랍니다.


그리고 예제에 사용된 소스 코드입니다.

BinaryWriting.zip



추가로, 궁금한 점이 있다면 댓글 남겨놔주시기 바랍니다~!


+ Recent posts