【问题标题】:Length in bytes of text with (CR) (LF)带有 (CR) (LF) 的文本字节长度
【发布时间】:2017-04-29 15:14:14
【问题描述】:

我从 sqlite3 得到的值可以用十六进制写成“0x0D 0x0A”。是的,它是(CR)和(LF)。我想知道我拥有的数据长度。但是命令“字符串长度”返回 1,而不是 2。“字符串字节长度”也返回 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)

【问题讨论】:

  • 不要使用string bytelength,除非你真的想知道 C 级别的特定形式的值所需的存储大小。对于 Tcl 脚本级别的任何人来说,它很少有用(我有代码在发布运行时生成的汇编代码时实际使用它,但这确实是一个非常不寻常的用例……)

标签: tcl


【解决方案1】:

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

set f [open test.txt r]
fconfigure $f -translation lf
set t [read $f]
string length $t

一般来说,还有其他设置可能会影响您获得的内容,尤其是 -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 命令是您需要的工具。请记住,字符和字节是一回事。为了让人们可以使用比字节中可表达的值更多的字符,必须放弃这一点。

【讨论】:

  • 在我的情况下,我从 sqlite 获取字符串。它既不是文件也不是通道来配置。保存到文件是获取此字符串字节大小的唯一方法吗?
  • 我理解正确吗,@DonalFellows?在 sqlite 中是 CR-LF 还是 LF 没有区别,我在 tcl 中总是只得到 LF。而当我写入套接字时,LF 可能变为 CR-LF 或保持 LF 取决于套接字 lf 配置,不是吗?
  • 经过详细检查,我发现数据库中只有LF。因此,TCL 从 sqlite 获取数据,无需转换。如果数据库存储 CR-LR,TCL 获取 CR-LR,我已经检查过了。在我的问题中,TCL 在写入套接字时会从 LR 转换为 CR-LR。
  • 有各种各样的地方可以发生转换,网络套接字就是其中之一(连接的套接字可以是fconfigured,就像打开的文件一样)。不幸的是,除了非常小心您在特定位置传递的数据是什么之外,没有真正的解决方法。你知道……实际上定义你正在使用的协议。
猜你喜欢
  • 2016-07-07
  • 1970-01-01
  • 1970-01-01
  • 2011-08-06
  • 2013-02-23
  • 2011-01-27
  • 2011-03-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多