(Tcl) 我应该使用什么字符编码集?
(Tcl) what character encoding set should I use?
所以我尝试用 Tcl 打开和解析一些旧的 Visual Studio 编译日志文件;我唯一的问题是文件的编码很奇怪。使用 Notepad++ 检查它们后,它们似乎处于 'UCS-2 Little Endian' 编码中。两个问题:
- Tcl 中是否有任何命令可以让我查看文件的字符编码?我知道有
encoding system
告诉我系统编码。
使用 encoding names
Tcl 告诉我可用的编码名称如下列表:
cp860 cp861 cp862 cp863 tis-620 cp864 cp865 cp866 gb12345 gb2312-raw cp949 cp950 cp869 dingbats ksc5601 macCentEuro cp874 macUkraine jis0201 gb2312 euc-cn euc-jp macThai iso8859-10 jis0208 iso2022-jp macIceland iso2022 iso8859-13 jis0212 iso8859 -14 iso8859-15 cp737 iso8859-16 big5 euc-kr macRomania macTurkish gb1988 iso2022-kr macGreek ascii cp437 macRoman iso8859-1 iso8859-2 iso8859-3 macCroatian koi8-r iso8859-4 ebcdic iso8859-5 cp1250 macCyrillic iso8859-6 cp1251 macDingbats koi8-u iso8859-7 cp1252 iso8859-8 cp1253 iso8859-9 cp1254 cp1255 cp850 cp1256 cp932 identity cp1257 cp852 macJapan cp1258 shiftjis utf-8 cp855 cp936 symbol cp775 unicode cp857[=17]
鉴于此,在 fconfigure -encoding
命令中使用什么名称来读取这些 UCS-2 Little Endian
编码文件并将其转换为 UTF-8
以供使用?如果我正确理解 fconfigure
命令,我需要指定源文件的编码类型,而不是我想要的;只是不知道上面列表中的哪个选项对应UCS-2 Little Endian
。稍作阅读后,我看到 UCS-2 是 UTF-16 字符编码的前身,但该选项也不在这里。
谢谢!
恐怕,目前没有办法仅通过使用 fconfigure -encoding ?something?
来做到这一点:unicode
编码具有相当实际的意义,并且有一个 feature request 来创建明确的支持对于 UTF-16 变体。
你能做些什么?
因为 unicode
在 Tcl 运行 上 Windows 应该 意味着 UTF-16 与本机字节序 1(Wintel 上的小端),如果您的解决方案应该是一个快速而肮脏的解决方案,请尝试使用 -encoding unicode
看看是否有帮助。
如果您的目标是更可靠或面向未来的跨平台解决方案,我会将通道切换到二进制更多,一次读取两个字节的块中的内容,然后使用
binary scan $twoBytes s n
到 scan the sequence of two bytes in $twoBytes
作为一个 16 位整数到一个名为 "n" 的变量中,后跟类似
set c [format %c $n]
到$n中的produce a unicode character out of the number,赋值给一个变量
这种方式据说需要更多技巧才能正确获得:
- 您可能会检查从流中获取的第一个字符,看它是否是字节顺序标记,如果是则将其丢弃。
- 如果您需要以逐行方式处理流,则必须实现一个能够正确处理 CR+LF 序列的小型状态机。
- 在执行
read $channelId 2
时,为了获取下一个字符,您应该检查它是否不仅返回 0 或 2,还返回 1——以防文件碰巧损坏——并处理这个问题。
UCS-2 编码与 UTF-16 的不同之处在于后者可能包含所谓的代理对,因此它不是固定长度的编码。因此正确处理 UTF-16 流意味着还检测这些代理对。另一方面,我几乎不相信 MSVS 生成的编译日志可能包含它们,所以我只是假设它是用 UCS-2LE 编码的。
1 真实的故事是 Tcl 唯一保证它处理的 textual 字符串(即那些通过操作文本获得的字符串,而不是通过 binary format
或 encoding convertto
或以二进制模式读取流)是因为它们是 Unicode(或者更确切地说,是它的 "BMP" 部分)。
但从技术上讲,解释器可能会在它默认使用的 UTF-8 编码和 some 固定长度编码之间切换任何字符串的内部表示,这就是该名称所指的 "unicode"。 "problem" 是 Tcl 文档的任何部分都没有指定内部固定长度编码,因为你 需要 显式转换你输出的任何文本或阅读 to/from 一些特定编码——通过配置流或使用 encoding convertfrom
和 encoding convertto
或使用 binary format
和 binary scan
,无论当前使用哪种精确编码,解释器都会做正确的事情用于您的源字符串值——这一切都是透明的。此外,"standard" Tcl 解释器的下一个版本可能会决定完全放弃此内部功能,或者说,使用 32 位或 64 位整数进行内部固定长度编码。 "non-standard" 解释器做什么(如 Jacl
等)也取决于他们。换句话说,此功能是内部的,不是有关口译员行为的书面合同的一部分。顺便说一下,Tcl 字符串 (UTF-8) 的 "standard" 编码也没有指定——这只是一个实现细节。
在 Tcl v8.6.8 中,我可以使用 fconfigure channelId -encoding unicode 解决同样的问题。
所以我尝试用 Tcl 打开和解析一些旧的 Visual Studio 编译日志文件;我唯一的问题是文件的编码很奇怪。使用 Notepad++ 检查它们后,它们似乎处于 'UCS-2 Little Endian' 编码中。两个问题:
- Tcl 中是否有任何命令可以让我查看文件的字符编码?我知道有
encoding system
告诉我系统编码。 使用
encoding names
Tcl 告诉我可用的编码名称如下列表:cp860 cp861 cp862 cp863 tis-620 cp864 cp865 cp866 gb12345 gb2312-raw cp949 cp950 cp869 dingbats ksc5601 macCentEuro cp874 macUkraine jis0201 gb2312 euc-cn euc-jp macThai iso8859-10 jis0208 iso2022-jp macIceland iso2022 iso8859-13 jis0212 iso8859 -14 iso8859-15 cp737 iso8859-16 big5 euc-kr macRomania macTurkish gb1988 iso2022-kr macGreek ascii cp437 macRoman iso8859-1 iso8859-2 iso8859-3 macCroatian koi8-r iso8859-4 ebcdic iso8859-5 cp1250 macCyrillic iso8859-6 cp1251 macDingbats koi8-u iso8859-7 cp1252 iso8859-8 cp1253 iso8859-9 cp1254 cp1255 cp850 cp1256 cp932 identity cp1257 cp852 macJapan cp1258 shiftjis utf-8 cp855 cp936 symbol cp775 unicode cp857[=17]
鉴于此,在
fconfigure -encoding
命令中使用什么名称来读取这些UCS-2 Little Endian
编码文件并将其转换为UTF-8
以供使用?如果我正确理解fconfigure
命令,我需要指定源文件的编码类型,而不是我想要的;只是不知道上面列表中的哪个选项对应UCS-2 Little Endian
。稍作阅读后,我看到 UCS-2 是 UTF-16 字符编码的前身,但该选项也不在这里。
谢谢!
恐怕,目前没有办法仅通过使用 fconfigure -encoding ?something?
来做到这一点:unicode
编码具有相当实际的意义,并且有一个 feature request 来创建明确的支持对于 UTF-16 变体。
你能做些什么?
因为 unicode
在 Tcl 运行 上 Windows 应该 意味着 UTF-16 与本机字节序 1(Wintel 上的小端),如果您的解决方案应该是一个快速而肮脏的解决方案,请尝试使用 -encoding unicode
看看是否有帮助。
如果您的目标是更可靠或面向未来的跨平台解决方案,我会将通道切换到二进制更多,一次读取两个字节的块中的内容,然后使用
binary scan $twoBytes s n
到 scan the sequence of two bytes in $twoBytes
作为一个 16 位整数到一个名为 "n" 的变量中,后跟类似
set c [format %c $n]
到$n中的produce a unicode character out of the number,赋值给一个变量
这种方式据说需要更多技巧才能正确获得:
- 您可能会检查从流中获取的第一个字符,看它是否是字节顺序标记,如果是则将其丢弃。
- 如果您需要以逐行方式处理流,则必须实现一个能够正确处理 CR+LF 序列的小型状态机。
- 在执行
read $channelId 2
时,为了获取下一个字符,您应该检查它是否不仅返回 0 或 2,还返回 1——以防文件碰巧损坏——并处理这个问题。
UCS-2 编码与 UTF-16 的不同之处在于后者可能包含所谓的代理对,因此它不是固定长度的编码。因此正确处理 UTF-16 流意味着还检测这些代理对。另一方面,我几乎不相信 MSVS 生成的编译日志可能包含它们,所以我只是假设它是用 UCS-2LE 编码的。
1 真实的故事是 Tcl 唯一保证它处理的 textual 字符串(即那些通过操作文本获得的字符串,而不是通过 binary format
或 encoding convertto
或以二进制模式读取流)是因为它们是 Unicode(或者更确切地说,是它的 "BMP" 部分)。
但从技术上讲,解释器可能会在它默认使用的 UTF-8 编码和 some 固定长度编码之间切换任何字符串的内部表示,这就是该名称所指的 "unicode"。 "problem" 是 Tcl 文档的任何部分都没有指定内部固定长度编码,因为你 需要 显式转换你输出的任何文本或阅读 to/from 一些特定编码——通过配置流或使用 encoding convertfrom
和 encoding convertto
或使用 binary format
和 binary scan
,无论当前使用哪种精确编码,解释器都会做正确的事情用于您的源字符串值——这一切都是透明的。此外,"standard" Tcl 解释器的下一个版本可能会决定完全放弃此内部功能,或者说,使用 32 位或 64 位整数进行内部固定长度编码。 "non-standard" 解释器做什么(如 Jacl
等)也取决于他们。换句话说,此功能是内部的,不是有关口译员行为的书面合同的一部分。顺便说一下,Tcl 字符串 (UTF-8) 的 "standard" 编码也没有指定——这只是一个实现细节。
在 Tcl v8.6.8 中,我可以使用 fconfigure channelId -encoding unicode 解决同样的问题。