谁能解释一下scan
和binary scan
之间的区别。
format
和binary format
.
我对二进制命令感到困惑.
要了解操作二进制和字符串数据的命令集之间的区别,您必须了解这两种数据之间的区别。
在Tcl中,就像在许多(大多数?)高级语言中一样,字符串是相当抽象的 - 也就是说,它们以相当高级的术语描述。 特别是在 Tcl 中,字符串被定义为具有以下属性:
- 它们包含来自 Unicode 曲目的字符。
- Tcl 运行时提供了一组标准命令来操作字符串,例如索引、搜索、追加、提取子字符串等。
请注意,此定义中遗漏了许多内容:
- 存储这些 Unicode 字符的编码。
- 它们究竟是如何存储的(
NUL
终止数组?unsigned long
s的链表?别的什么?)。
(从更有趣的角度来看,Tcl 能够透明地更改它管理的字符串的底层表示形式——在UTF-8
和UTF-16
编码序列之间。 但这里我们谈论的是引用 Tcl 实现,其他实现(例如 Jacl)可以完全自由地做其他事情。
相同的方法用于在 Tcl 解释器中操作所有其他类型的数据。 例如,整数是使用本机平台"整数"(大致为"如 C 格式")存储的,但如果算术运算即将溢出平台大小的结果,它们会被透明地升级为任意大小的整数。
只要你不离开Tcl解释器的舒适世界,这就是你应该知道的关于它管理的数据类型的全部信息。 但现在有外面的世界。 在其中,作为Tcl字符串的抽象概念不存在。 比如说,如果您需要通过网络套接字或使用文件或任何其他类型的媒体与其他程序进行通信,则必须深入了解原始字节的确切布局级别,这些布局由"有线协议"和文件格式或任何适用于您的情况描述。 这就是"二进制文件"发挥作用的地方:它们允许您精确地指定数据的布局方式,以便准备好将其传输到外部世界或从中消费 -binary format
制作这些"二进制文件"并binary scan
读取它们。
请注意,某些用于处理外部世界的 Tcl 命令是"默认智能的"——例如,默认情况下打开文件的open
命令假定它们是文本的,并且以默认的系统编码进行编码(从广义上讲,从环境中推断出来)。 然后,您可以使用chan configure
(在旧版本的 Tcl 中为fconfigure
)命令更改此编码或通过指定通道处于"二进制模式"来完全禁止转换。 这同样适用于 EOL 转换。
另请注意,Tcl 有专门的软件包,可以有效地隐藏使用特定线路/文件格式的复杂性。 举一个例子,tdom 包与XML
一起工作;当你使用这个包操作XML
时,你并不关心XML
在保存到文件时必须如何准确表示——你只处理 tdom 的对象、原生 Tcl 字符串等。
文档非常好,包含示例:
- 扫描:http://www.tcl.tk/man/tcl8.6/TclCmd/scan.htm
- 格式: http://www.tcl.tk/man/tcl8.6/TclCmd/format.htm
- 二进制扫描:http://www.tcl.tk/man/tcl8.6/TclCmd/binary.htm#M42
- 二进制格式:http://www.tcl.tk/man/tcl8.6/TclCmd/binary.htm#M16
也许你可以问一个更具体的问题?
format
命令组合字符串,binary format
命令组合字节字符串。scan
和binary scan
命令执行相反的操作,分别从字符串和字节字符串中提取形成。
请注意,Tcl碰巧将字节字符串整齐地映射到字符串上,其中字符在u0000
–u00FF
范围内,并且还有其他操作用于将信息传入和传出有时相关的二进制字符串。最值得注意的是,encoding convertto
和encoding convertfrom
:encoding convertto
将字符串格式化为以给定编码表示该字符串的字节序列(可能会丢失信息的操作),并且encoding converfrom
朝着相反的方向发展。
那么Tcl的字符串到底是什么编码呢?嗯,真的没有。或很多。逻辑级别只使用字符序列,并且实现实际上将根据需要来回移动内容(主要是在 UTF-8 和 UCS-2 的变体之间,尽管通过unsigned char
数组处理字节字符串进行了优化)。虽然这并不总是完全有效的,但由于使用了类型缓存,大多数代码永远不会注意到发生了什么。
如果你有 Tcl 8.6,你可以偷看幕后,使用不受支持的命令观察类型:
# Output is human-readable; experiment to see what it says for you
puts [tcl::unsupported::representation $MyString]
不要用它来作为功能决策的基础;Tcl非常乐意从你脚下变异类型。但是,在找出代码出乎意料地慢的原因时,它会有所帮助。(另请注意,类型附加到值,而不是变量。