BOM 이 있는 File인 경우에는 자동으로 읽을 수 있는 옵션을 제공해줍니다.
public StreamReader( Stream stream, bool detectEncodingFromByteOrderMarks )
하지만 BOM이 없는 경우에는 딱히 자동으로 확인 할 수 있는 방법이 없습니다.
그래서 어떻게 확인 가능한 방법이 없을까 검색하던중
Notepad에서 characterset을 확인하는 방법을 소개한 blog를 발견하였습니다.
http://blogs.msdn.com/b/oldnewthing/archive/2004/03/24/95235.aspx
예를 들어서 "Hello" 가 저장되어 있는 Text File인 경우 각각의 characterset 및 BOM 여부에 따라서 아래와 같이 저장됩니다.
* Traditional ANSI encoding
48 65 6C 6C 6F
* Unicode (little-endian) encoding without BOM
48 00 65 00 6C 00 6C 00 6F 00
* Unicode (little-endian) encoding with BOM
FF FE 48 00 65 00 6C 00 6C 00 6F 00
* Unicode (big-endian) encoding without BOM
00 48 00 65 00 6C 00 6C 00 6F
* Unicode (big-endian) encoding with BOM
FE FF 00 48 00 65 00 6C 00 6C 00 6F
* UTF-8 encoding with BOM
EF BB BF 48 65 6C 6C 6F
* UTF-7 encoding with BOM
2B 2F 76 38 2D 48 65 6C 6C 6F
위 7가지에 대해서 Check를 자동으로 하여 File 내용을 읽어주는 함수를 만들어 봤습니다.
Encoding에 맞게 읽으면 왠만해서는 그대로 사용이 가능하지만,
사용하는 Platform에 따라 안되는 파일이 있어서 다시한번 Convert 하는 Code를 넣었습니다.
* Code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.IO; | |
using System.Text; | |
public string ReadFile(string fileName, Encoding encode = null) | |
{ | |
if (encode == null) | |
encode = Encoding.Default; | |
string strRet = null; | |
Encoding fileEnc = DetectEncoding(fileName); | |
using (Stream S = File.OpenRead(fileName)) | |
{ | |
using (StreamReader sr = new StreamReader(S, fileEnc)) | |
{ | |
if (encode == fileEnc) | |
strRet = sr.ReadToEnd(); | |
else | |
{ | |
string strFile = sr.ReadToEnd(); | |
byte[] bytesFile = fileEnc.GetBytes(strFile); | |
byte[] bytesRet = Encoding.Convert(fileEnc, encode, bytesFile); | |
strRet = encode.GetString(bytesRet); | |
} | |
} | |
} | |
return strRet; | |
} | |
public Encoding DetectEncoding(string filename) | |
{ | |
using (Stream S = File.OpenRead(filename)) | |
{ | |
using (StreamReader SR = new StreamReader(S)) | |
{ | |
char[] buffer = new char[10]; | |
SR.Read(buffer, 0, 10); | |
if (IsEqualBytes(buffer, new byte[] { 0xFF, 0xFE }, 2)) | |
{ | |
return Encoding.Unicode; // Little Endian with BOM | |
} | |
else if (IsEqualBytes(buffer, new byte[] { 0xFE, 0xFF }, 2)) | |
{ | |
return Encoding.BigEndianUnicode; // with BOM | |
} | |
else if (IsEqualBytes(buffer, new byte[] { 0xEF, 0xBB, 0xBF }, 3)) | |
{ | |
return Encoding.UTF8; // with BOM | |
} | |
else if (IsEqualBytes(buffer, new byte[] { 0x2B, 0x2F, 0x76, 0x38, 0x2D }, 5)) | |
{ | |
return Encoding.UTF7; // with BOM | |
} | |
else if (IsZeroBytes(buffer, 10, true)) | |
{ | |
return Encoding.Unicode; // Little Endian without BOM | |
} | |
else if (IsZeroBytes(buffer, 10, false)) | |
{ | |
return Encoding.BigEndianUnicode; // without BOM | |
} | |
} | |
} | |
return Encoding.Default; // Ansi : MBCS (Multibyte Character Set) | |
} | |
public bool IsEqualBytes(char[] src, byte[] pattern, int num) | |
{ | |
if (src.Length < num || pattern.Length < num) | |
return false; //throw new ArgumentOutOfRangeException(); | |
bool bRet = true; | |
for (int i = 0; i < num; i++) | |
{ | |
if (src[i] != pattern[i]) | |
{ | |
bRet = false; | |
break; | |
} | |
} | |
return bRet; | |
} | |
public bool IsZeroBytes(char[] src, int num, bool checkOdd = true) | |
{ | |
if (src.Length < num) | |
return false; //throw new ArgumentOutOfRangeException(); | |
bool bRet = true; | |
int rest = checkOdd ? 1 : 0; | |
for (int i = 0; i < num; i++) | |
{ | |
if (i % 2 == rest) | |
{ | |
if (src[i] != 0x00) | |
{ | |
bRet = false; | |
break; | |
} | |
} | |
} | |
return bRet; | |
} |
댓글 없음:
댓글 쓰기