TCL 中的二进制格式化变量
Binary Formatting Variables in TCL
我正在尝试创建一个二进制消息以通过套接字发送,但我遇到了 TCL 将所有变量视为字符串的方式。我需要计算字符串的长度并知道它的二进制值。
set length [string length $message]
set binaryMessagePart [binary format s* { $length 0 }]
但是,当我 运行 这样做时,我得到了错误 'expected integer but got "$length"'。我如何让它工作以及 return 整数 5 而不是 char 5 的值?
要计算字符串的长度,请使用 string length
。要计算特定编码中字符串的长度,请将字符串转换为该编码并使用 string length
:
set enc "utf-8"; # Or whatever; you need to know this ahead of time for sanity's sake
set encoded [encoding convertto $enc $message]
set length [string length $encoded]
请注意,对于编码长度,这将以字节为单位,而编码之前的长度以字符为单位。对于某些消息和某些编码,差异可能很大。
要使用消息的长度和正文(一种相当常见的二进制格式)组成二进制消息,请像这样使用 binary format
:
# Assumes the length is big-endian; for little-endian, use i instead of I
set binPart [binary format "Ia*" $length $encoded]
你做错了什么是使用 s*
它消耗一个整数列表并在输出字符串中产生一个 little-endian 短整数二进制值序列,但正在提供列表字面上 $length 0
; string $length
不是整数,因为它们不是以 $
开头的。我们本可以改为 [list $length 0]
来生成 s*
的论点,这会奏效,但对于问题的上下文来说,这似乎不太正确。
在binary format
中,这些是常用的格式(还有很多):
a
用于字符串数据(助记“ASCII”);这是二进制字符串数据,您需要先对其进行编码。
i
和 I
用于 32 位数字(助记“int
”,就像在许多编程语言中一样,但尤其是 C)。大写为big-endian,小写为little-endian.
s
和 S
用于 16 位数字(助记“short
”)。
c
用于 8 位数字(来自 C 的助记符“char
”)。
w
和 W
用于 64 位数字(助记“宽整数”)。
f
和 d
用于 IEEE 二进制浮点数(助记符分别为“float
”和“double
”,所以 4 和 8 个字节)。
All 后面可以跟一个可选的长度,可以是数字或 *
。对于数字,不是插入单个数字,而是插入它们的列表(因此消耗列表);数字给出固定长度,*
给出“所有列表”。对于字符串格式指示符,数字在消息中使用固定数量的字节(根据需要用零字节截断或填充)并且 *
执行“所有字符串”(从不截断或填充)。
我正在尝试创建一个二进制消息以通过套接字发送,但我遇到了 TCL 将所有变量视为字符串的方式。我需要计算字符串的长度并知道它的二进制值。
set length [string length $message]
set binaryMessagePart [binary format s* { $length 0 }]
但是,当我 运行 这样做时,我得到了错误 'expected integer but got "$length"'。我如何让它工作以及 return 整数 5 而不是 char 5 的值?
要计算字符串的长度,请使用 string length
。要计算特定编码中字符串的长度,请将字符串转换为该编码并使用 string length
:
set enc "utf-8"; # Or whatever; you need to know this ahead of time for sanity's sake
set encoded [encoding convertto $enc $message]
set length [string length $encoded]
请注意,对于编码长度,这将以字节为单位,而编码之前的长度以字符为单位。对于某些消息和某些编码,差异可能很大。
要使用消息的长度和正文(一种相当常见的二进制格式)组成二进制消息,请像这样使用 binary format
:
# Assumes the length is big-endian; for little-endian, use i instead of I
set binPart [binary format "Ia*" $length $encoded]
你做错了什么是使用 s*
它消耗一个整数列表并在输出字符串中产生一个 little-endian 短整数二进制值序列,但正在提供列表字面上 $length 0
; string $length
不是整数,因为它们不是以 $
开头的。我们本可以改为 [list $length 0]
来生成 s*
的论点,这会奏效,但对于问题的上下文来说,这似乎不太正确。
在binary format
中,这些是常用的格式(还有很多):
a
用于字符串数据(助记“ASCII”);这是二进制字符串数据,您需要先对其进行编码。i
和I
用于 32 位数字(助记“int
”,就像在许多编程语言中一样,但尤其是 C)。大写为big-endian,小写为little-endian.s
和S
用于 16 位数字(助记“short
”)。c
用于 8 位数字(来自 C 的助记符“char
”)。w
和W
用于 64 位数字(助记“宽整数”)。f
和d
用于 IEEE 二进制浮点数(助记符分别为“float
”和“double
”,所以 4 和 8 个字节)。
All 后面可以跟一个可选的长度,可以是数字或 *
。对于数字,不是插入单个数字,而是插入它们的列表(因此消耗列表);数字给出固定长度,*
给出“所有列表”。对于字符串格式指示符,数字在消息中使用固定数量的字节(根据需要用零字节截断或填充)并且 *
执行“所有字符串”(从不截断或填充)。