Visual Works smalltalk,如何将Ascii值转换为字符
Visual Works smalltalk, how to convert Ascii values to characters
使用 visualworks,在闲聊中,我从网络连接接收到类似“31323334”的字符串。
我需要一个读取“1234”的字符串,所以我需要一种方法来一次提取两个字符,将它们转换为它们在 ascii 中表示的内容,然后构建它们的字符串...
有办法吗?
编辑(7/24):出于某种原因,你们中的许多人都假设我只会处理数字并且可以截断 3 或读取所有其他字符。事实并非如此,读取的字符串示例可能包括美国标准键盘上的任何键(a-z、A-Z、0-9、punctuation/annotation,例如 {}*&^%$...)
通常有一个 #fold:
或 #reduce:
方法可以让您做到这一点。在 Pharo 中还有一条消息 #allPairsDo:
和 #groupsOf:atATimeCollect:
。您可以使用以下方法之一:
| collectionOfBytes |
collectionOfBytes := '9798'
groupsOf: 2
atATimeCollect: [ :group |
(group first digitValue * 10) + (group second digitValue) ].
collectionOfBytes asByteArray asString "--> 'ab'"
Pharo 中的 #digitValue
消息只是 returns 数字字符的数字值。
如果您在流中接收数据,您可以用循环替换 #groupsOf:atATime:
(result
可以是任何集合,然后您可以像上面那样将其转换为字符串):
...
[ stream atEnd ] whileFalse: [
result add: (stream next digitValue * 10) + (stream next digitValue) ]
...
按照 Max 开始建议的思路:
x := '31323334'.
in := ReadStream on: x.
out := WriteStream on: String new.
[ in atEnd ] whileFalse: [ out nextPut: (in next digitValue * 16 + (in next digitValue)) asCharacter ].
newX := out contents.
newX
将得到结果 '1234'
。或者,如果您开始于:
x := '454647'
您将得到 'EFG'
的结果。
请注意,digitValue
可能只能识别大写的十六进制数字,因此在处理之前可能需要对字符串添加 asUppercase
。
在 Smalltalk/X 中,有一个名为“fromHexBytes:
”的方法,ByteArray class 可以理解。我不确定,但认为其他 ST 方言中也存在类似的东西。
如果存在,您可以通过以下方式解决此问题:
(ByteArray fromHexString:'68656C6C6F31323334') asString
反之则为:
'hello1234' asByteArray hexPrintString
另一种可能的解决方案是将字符串读取为十六进制数,
获取 digitBytes(它应该给你一个字节数组),然后将其转换为一个字符串。
即
(Integer readFrom:'68656C6C6F31323334' radix:16)
digitBytes asString
一个问题是我不确定您将获得 digitBytes 的字节顺序(LSB 或 MSB),以及它是否定义为跨体系结构相同或在图像加载时转换为使用本机顺序。所以可能需要在最后反转字符串(为了便携,甚至可能需要有条件地反转它,这取决于系统的字节顺序。
我无法在 VisualWorks 上对此进行测试,但我认为它在那里也应该可以正常工作。
使用 visualworks,在闲聊中,我从网络连接接收到类似“31323334”的字符串。
我需要一个读取“1234”的字符串,所以我需要一种方法来一次提取两个字符,将它们转换为它们在 ascii 中表示的内容,然后构建它们的字符串...
有办法吗?
编辑(7/24):出于某种原因,你们中的许多人都假设我只会处理数字并且可以截断 3 或读取所有其他字符。事实并非如此,读取的字符串示例可能包括美国标准键盘上的任何键(a-z、A-Z、0-9、punctuation/annotation,例如 {}*&^%$...)
通常有一个 #fold:
或 #reduce:
方法可以让您做到这一点。在 Pharo 中还有一条消息 #allPairsDo:
和 #groupsOf:atATimeCollect:
。您可以使用以下方法之一:
| collectionOfBytes |
collectionOfBytes := '9798'
groupsOf: 2
atATimeCollect: [ :group |
(group first digitValue * 10) + (group second digitValue) ].
collectionOfBytes asByteArray asString "--> 'ab'"
Pharo 中的 #digitValue
消息只是 returns 数字字符的数字值。
如果您在流中接收数据,您可以用循环替换 #groupsOf:atATime:
(result
可以是任何集合,然后您可以像上面那样将其转换为字符串):
...
[ stream atEnd ] whileFalse: [
result add: (stream next digitValue * 10) + (stream next digitValue) ]
...
按照 Max 开始建议的思路:
x := '31323334'.
in := ReadStream on: x.
out := WriteStream on: String new.
[ in atEnd ] whileFalse: [ out nextPut: (in next digitValue * 16 + (in next digitValue)) asCharacter ].
newX := out contents.
newX
将得到结果 '1234'
。或者,如果您开始于:
x := '454647'
您将得到 'EFG'
的结果。
请注意,digitValue
可能只能识别大写的十六进制数字,因此在处理之前可能需要对字符串添加 asUppercase
。
在 Smalltalk/X 中,有一个名为“fromHexBytes:
”的方法,ByteArray class 可以理解。我不确定,但认为其他 ST 方言中也存在类似的东西。
如果存在,您可以通过以下方式解决此问题:
(ByteArray fromHexString:'68656C6C6F31323334') asString
反之则为:
'hello1234' asByteArray hexPrintString
另一种可能的解决方案是将字符串读取为十六进制数, 获取 digitBytes(它应该给你一个字节数组),然后将其转换为一个字符串。 即
(Integer readFrom:'68656C6C6F31323334' radix:16)
digitBytes asString
一个问题是我不确定您将获得 digitBytes 的字节顺序(LSB 或 MSB),以及它是否定义为跨体系结构相同或在图像加载时转换为使用本机顺序。所以可能需要在最后反转字符串(为了便携,甚至可能需要有条件地反转它,这取决于系统的字节顺序。
我无法在 VisualWorks 上对此进行测试,但我认为它在那里也应该可以正常工作。