Tcl 从二进制文件中读取错误的字节数
我有以下代码:Tcl 从二进制文件中读取错误的字节数,tcl,Tcl,我有以下代码: set myfile "the path to my file" set fsize [file size $myfile] set fp [open $myfile r] fconfigure $fp -translation binary set data [read $fp $fsize] close $fp puts $fsize puts [string bytelength $data] 它表明读取的字节与请求的字节不同。请求的字节与文件系统显示的字节匹配;实际读取
set myfile "the path to my file"
set fsize [file size $myfile]
set fp [open $myfile r]
fconfigure $fp -translation binary
set data [read $fp $fsize]
close $fp
puts $fsize
puts [string bytelength $data]
它表明读取的字节与请求的字节不同。请求的字节与文件系统显示的字节匹配;实际读取的字节数增加了22%(请求的字节数为29300,得到的字节数为35832)。我在Windows上用Tcl 8.6测试了这个功能。使用
字符串长度
。不要使用字符串bytellength
。它给出了“错误”的答案,或者更确切地说,它回答了一个你可能不想问的问题
更深入
stringbytelength
命令返回Tcl内部几乎是UTF-8编码的数据的字节长度。如果您不直接使用Tcl的C API,那么该值实际上没有什么合理的用途,C代码实际上可以在没有该命令的情况下获得该值。对于ASCII文本,长度和字节长度相同,但对于二进制数据或NUL或大于U+00007F的字符(相当于ASCII DEL的Unicode字符)的文本,值将不同。相比之下,string length
命令知道如何正确处理二进制数据,并将报告您读入的字节字符串中的字节数。我们计划不推荐使用字符串bytellength
命令,因为它几乎每次都是某人代码中的一个bug
(我猜您的输入数据实际上有6532个字节,超出了1–127的范围;其他字节在内部使用几乎为UTF-8的双字节表示。幸运的是,Tcl在需要时才真正转换为该格式,而在本例中使用了紧凑的字节数组;您通过请求字符串来强制转换ByTeleLength
)
背景资料
“Tcl实际使用了多少内存来读取这些数据”这一问题很难回答,因为Tcl会在内部对数据进行变异,以使其以最有效的形式保存在应用于它的操作中。因为Tcl的内部类型都是完全透明的(也就是说,它们之间的转换不会丢失信息)我们故意不多谈论它们,除非从优化的角度;作为程序员,你应该假装Tcl除了unicode字符串之外没有其他类型
您可以使用
tcl::unsupported::representation
命令(在8.6中引入)稍微揭开面纱.不要使用类型来决定在代码中要做什么,因为这确实不是语言所能保证的,但它确实让您看到了更多关于幕后真实情况的信息。请记住,您看到的值与Tcl实现所考虑的值不同。思考你看到的值(没有这个神奇的命令)会让你一直思考它应该写的东西。使用字符串长度
。不要使用string bytellength
。它给出了“错误”的答案,或者更确切地说,它回答了一个你可能不想问的问题
更深入
string bytelength
命令返回Tcl内部几乎UTF-8编码中数据的字节长度。如果您不直接使用Tcl的C API,那么该值实际上没有什么实际用途,而C代码实际上可以在没有该命令的情况下获得该值。对于ASCII文本,长度和字节长度是相同,但适用于NUL或大于U+00007F(等同于ASCII DEL的Unicode字符)的二进制数据或文本,值会有所不同。相比之下,字符串长度
命令知道如何正确处理二进制数据,并会报告您读入的字节字符串中的字节数。我们计划通过tellength命令弃用字符串,因为它几乎每次被使用都会成为某人代码中的错误
(我猜您的输入数据实际上有6532个字节,超出了1–127的范围;其他字节在内部使用几乎为UTF-8的双字节表示。幸运的是,Tcl在需要时才真正转换为该格式,而在本例中使用了紧凑的字节数组;您通过请求字符串来强制转换ByTeleLength
)
背景资料
“Tcl实际使用了多少内存来读取这些数据”这一问题很难回答,因为Tcl会在内部对数据进行变异,以使其以最有效的形式保存在应用于它的操作中。因为Tcl的内部类型都是完全透明的(也就是说,它们之间的转换不会丢失信息)我们故意不多谈论它们,除非从优化的角度;作为程序员,你应该假装Tcl除了unicode字符串之外没有其他类型
您可以使用tcl::unsupported::representation
命令(在8.6中引入)稍微揭开面纱.不要使用类型来决定在代码中要做什么,因为这确实不是语言所能保证的,但它确实让您看到了更多关于幕后真实情况的信息。请记住,您看到的值与Tcl实现所考虑的值不同。思考您看到的值(没有该神奇命令)将使您不断思考编写正确的内容。谢谢。这就解决了问题。我的下一个挑战是通过Tcl_CreateCommand将该字符串传递给C中定制的命令,而不需要解释器更改原始二进制字符串。@Eduardo由于Tcl几乎是UTF8编码,二进制数据将通过C str传递这意味着您可以使用Tcl\u NewStringObj(theStr,-1)
将参数存储在Tcl\u Obj*
ref中,并使用Tcl\u GetByteArrayFromObj
访问二进制字节。它返回的无符号字符*
指针在