帶有簽名的UTF-8文件可以通過讀取BOM輕松識別, 而不帶簽名的UFT-8文件只有通過UTF-8編碼的規則 來嘗試辨別。
先來看看UTF-8編碼是如何實現UNICODE字符的:
UNICODE UTF-8 00000000 - 0000007F 0xxxxxxx 00000080 - 000007FF 110xxxxx 10xxxxxx 00000800 - 0000FFFF 1110xxxx 10xxxxxx 10xxxxxx 00010000 - 001FFFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 00200000 - 03FFFFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 04000000 - 7FFFFFFF 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx從上表可以看出如果以個UTF-8字符是以2個或2個以上的字節組成, 則首字節前有多個連續的值為1的 比特位, 隨後是一個值為0的比特位。
根據這一特點我們可以嘗試識別判斷一個文件是否為UFT-8格式。
代碼如下:
//data為從文件讀取的字節數組
public bool IsUTF8Bytes(byte[] data)
{
int charByteCounter = 1; //計算當前正分析的字符應還有的字節數
byte curByte; //當前分析的字節.
for (int i = 0; i < data.Length; i++)
{
curByte = data[i];
if (charByteCounter == 1)
{
if (curByte >= 0x80)
{
//判斷當前
while (((curByte <<= 1) & 0x80) != 0)
{
charByteCounter++;
}
//標記位首位若為非0 則至少以2個1開始 如:110XXXXX...........1111110X
if (charByteCounter == 1 || charByteCounter > 6)
{
return false;
}
}
}
else
{
//若是UTF-8 此時第一位必須為1
if ((curByte & 0xC0) != 0x80)
{
return false;
}
charByteCounter--;
}
}
if (charByteCounter > 1)
{
throw new Exception("非預期的byte格式");
}
return true;
}
需要注意的是,一些比較特殊的字符用此方法無法正確識別是否為UTF8格式, 傳說中的微軟屏蔽聯 通就是此問題
希望此文對大家有幫助
附:
1.UTF-8的相關基礎知識可以前往這裡http://www.codeguru.com/Cpp/misc/misc/multi- lingualsupport/article.php/c10451/