Thursday, September 11, 2008

對三種編碼文件的測試

用記事本分別用三種編碼保存同一個內容
文件內容:中國ABC

保存編碼:ANSI
文件長度:9=2+2+ 1+1+1+ 1+1
具體內容:
D6 D0 B9 FA 41 42 43 0D - 0A

保存編碼:UniCode
文件長度:16=2+ 2+2+ 2+2+2+ 2+2
具體內容:FF FE 2D 4E FD 56 41 00 - 42 00 43 00 0D 00 0A 00

保存編碼:UTF-8
文件長度:14=3+ 3+3+ 1+1+1+ 1+1
具體內容:EF BB BF E4 B8 AD E5 9B - BD 41 42 43 0D 0A

結論:
ANSI保存中文就是GB2312的編碼,英文一個字節
UniCode前面有兩個引導符,然後中文、英文都是兩個字節,英文就是ANSI前面加00而成(保存時,低位在前,高位在後)

接著,我再測試JavaScript中的幾個編碼轉換工具是干什麼用的。
<html>
<body>
<script>
alert(escape("中"));
//顯示 %u4E2D

alert(unescape("%u4E2D"));
//顯示 中

alert(encodeURI("中"));
//顯示 %E4%B8%AD

alert(decodeURI("%E4%B8%AD"));
//顯示 中

alert("中".charCodeAt(0));
//顯示 20013

alert("中".charCodeAt(0).toString(16));
//顯示 4e2d

</script>
</body>
</html>
結論:IE中,總是以UniCode來保存。escape可以實現字符串到UniCode碼的轉換。encodeURI可以實現字符串到UTF-8碼的轉換。

現在的目標是,要在JavaScript中正確讀取UTF-8的文件。

先列出讀取文件的代碼測試結果:
<html>
<body>
<script>

var fso, ts;
var ForReading = 1;
var TristateTrue = true; //打開Unicode文件時用
var TristateFalse = false; //打開ANSI文件時用
fso = new ActiveXObject("Scripting.FileSystemObject");
ts = fso.OpenTextFile("c:\\testfile.txt", ForReading, false, TristateTrue); //文件內容:中國ABC
var c1 = ts.ReadLine();
document.writeln("第一個字:" + c1.charCodeAt(0).toString(16));
ts.Close();

</script>
</body>
</html>

當文件用ANSI編碼保存時:
用TristateFalse打開時第一個字為:4e2d(正確)
用TristateTrue打開則為:d0d6(原始內容)
當文件用Unicode編碼保存時:
用TristateFalse打開時第一個字為:f8f5
用TristateTrue打開第一個字為:4e2d(正確)
當文件用UTF-8編碼保存時:
用TristateFalse打開時第一個字為:9518
用TristateTrue打開則為:bbef(原始內容)

可以得知TristateFalse針對ANSI的,TristateTrue針對UniCode的。而UTF-8沒有對應的,但如果用TristateTrue,可以讀出原始的值。如果再把原始值編碼為%E4%B8%AD,就可以用decodeURI轉換結果了。

最後的代碼如下:
讓JavaScript讀取UTF-8編碼的文件
<html>
<body>
<script>

var fso, ts;
var ForReading = 1;
var TristateTrue = true; //打開Unicode文件時用
var TristateFalse = false; //打開ANSI文件時用
fso = new ActiveXObject("Scripting.FileSystemObject");
ts = fso.OpenTextFile("c:\\testfile2.txt", ForReading, false, TristateTrue); //中國ABC
var c1 = ts.ReadAll();
var s0=escape(c1);
var s1="";
var new_s="";
//六位一組,形式:%u4E2D
for (var i=0; i<s0.length; i+=6)
{
s1=s0.substr(i, 6);
//前面兩個%u取消,後兩位移前,前兩位移後,得到%2D%4E
new_s+="%" + s1.substr(4, 2) + "%" + s1.substr(2, 2);
}
//前三個字節是標誌,放棄它
new_s=new_s.substr(9, new_s.length);
document.write("內容:" + decodeURI(new_s));
ts.Close();

</script>
</body>
</html>

No comments: