Tcl 带(CR)(LF)的文本的字节长度

Tcl 带(CR)(LF)的文本的字节长度,tcl,Tcl,我从sqlite3得到的值可以用十六进制写成,比如“0x0D 0x0A”。是的,是(CR)和(LF)。我想知道我得到的数据的长度。但是命令“字符串长度”返回1,而不是2。“stringbytellength”也返回1。如何获得正确的数据长度(以字节为单位) 这是一个简单的例子。在实际的程序中,我从sqlite获得了不同的文本数据,编码未知。我所需要的就是以字节为单位获取数据的长度。但文本中的每个(CR)(LF)都以1字节计。 从sqlite和文件获取数据的示例: sqlite dbcmd mes

我从sqlite3得到的值可以用十六进制写成,比如“0x0D 0x0A”。是的,是(CR)和(LF)。我想知道我得到的数据的长度。但是命令“字符串长度”返回1,而不是2。“stringbytellength”也返回1。如何获得正确的数据长度(以字节为单位)

这是一个简单的例子。在实际的程序中,我从sqlite获得了不同的文本数据,编码未知。我所需要的就是以字节为单位获取数据的长度。但文本中的每个(CR)(LF)都以1字节计。 从sqlite和文件获取数据的示例:

sqlite dbcmd messages.db
set t [dbcmd message from messages limit 1,1]
string length $t


set f [open test.txt r]
set t [read $f]
string length $t
(Windows 7、ActiveTcl 8.6.4、tclkit 8.6.6)

默认情况下,Tcl将正在读取的文件中的CR-LF序列转换为简单的LF字符。这通常很有用,因为它大大简化了脚本中的普通文本处理。但是,如果需要精确的值,则可以使用
fconfigure
将通道置于备用处理模式。例如,将频道的
-translation
设置更改为
lf
(从
auto
)将保留所有回车(以及换行)

一般来说,还有其他设置可能会影响您获得的内容,特别是
-eofchar
-encoding
选项。
-eofchar
通常是EOF(即与Ctrl+Z关联的字符),而
-encoding
是一个系统特定的值,它取决于平台和区域设置等因素。如果您想真正使用二进制数据,即仅获取字节,可以将
-translation
选项设置为
binary
,这将为处理二进制数据做好一切准备。在
open
命令中有一个常用选项的缩写:

set f [open test.txt rb];  # ««« “b” flag in open mode
set t [read $f]
string length $t

如果您确实获取了字节并希望在某个时刻从中获取字符,那么
encoding convertfrom
命令就是您需要的工具。回想起字符和字节不是一回事。为了允许人们使用比字节中可表达的值更多的字符,必须放弃这一点。

不要使用
string bytellength
,除非您真的想知道特定形式的C级值所需的存储大小。在Tcl脚本级别,它很少对任何人有用(我有一些代码在发布运行时生成的汇编代码时实际使用它,但这确实是一个非常不寻常的用例…),在我的例子中,我从sqlite获取字符串。它既不是要配置的文件,也不是要配置的通道。保存文件是获取此字符串字节大小的唯一方法吗?我理解正确了吗,@DonalFellows?无论是CR-LF还是sqlite中的LF都没有区别,我总是在tcl中只得到LF。当我向套接字写入时,LF可能变成CR-LF或保持LF取决于套接字
LF
配置,不是吗?经过详细检查,我在数据库中只找到了LF。因此,TCL从sqlite获取数据时不需要转换。若数据库存储了CR-LR,TCL得到了CR-LR,我已经检查过了。在我的文章中,TCL在写入套接字时会从LR转换为CR-LR。有各种各样的地方可以进行转换,网络套接字就是其中之一(连接的套接字可以像打开的文件一样进行配置)。不幸的是,没有真正的解决办法,只有对您在特定位置真正传递的数据非常小心。你知道…实际上定义了你正在使用的协议。
set f [open test.txt rb];  # ««« “b” flag in open mode
set t [read $f]
string length $t