Tcl Character Encoding in IO

风行水上 @ 2014-06-19 17:28:45
标签:

比如字符串“非 是 非 - noyesno ”内部表示(Unicode BE)为:

975e 0020 662f 0020 975e 0020 002d 0020 006e 006f 0079 0065 0073 006e 006f

数据的输出

默认编码

encoding system utf-8

set data "非 是 非 - noyesno"

set file "out.txt"
set fout [open $file "w"]
puts -nonewline $fout $data
close $fout

puts "size = [file size $file]"
exec xxd $file >@ stdout

输出文件正常,字符采用了系统默认编码"utf-8"。

设置输出编码

另外尝试一下几种编码设置:

  1. fconfigure $fout -encoding binary
  2. fconfigure $fout -translation binary
  3. fconfigure $fout -encoding utf-8
  4. ``fconfigure $fout -encoding utf-8 -translation binary

只有第三种设置输出正常,其他几种均出现乱码或者内容错误。

先说结论:

  • -translation binary会自动设置-encoding binary
  • -encoding binary的效果是把每一个字符(两个字节)作为一个字节输出(低位字节)。
    • 对于非ASCII字符来说,高位字节丢失导致数据遗漏

输出二进制数据

需要以二进制形式输出数据时:

  • 不希望做自动的编码转换,因此需要使用-encoding binary选项。
  • 不希望对换行符进行自动转换,因此需要使用-translation binary选项

上述任一项设置都会导致-encoding binary,进而出现上面提到的高位字节丢失问题。

因此需要输出二进制数据时需要预先转换编码:

set data [encoding convertto $data]
puts -nonewline $sock $data   ;# 注意使用 -nonewline 选项

额外需要注意使用 -nonewline 选项,以避免添加额外的字符。

为什么需要以二进制形式输出数据

比如,通讯协议要求了,先传输数据长度(字节数),再传输数据内容。这时需要:

  • 预先计算数据字节长度
  • 数据内容不能变动

这在涉及数据结构的编程(网络通讯,二进制数据文件)中很重要。

数据的读入

TODO

标签:

分享到:
comments powered by Disqus

28/32ms