我希望将String
转换为64位的块。我不确定ByteString
是否是正确使用的数据类型,但经过一些测试后,我意识到我无法将String
转换为ByteString
并返回:
import qualified Data.ByteString.Lazy.Char8 as B
main = putStrLn $ B.unpack $ B.pack "☂♞☯"
结果:
^/
不应该打印☂♞☯
?
我的第二次尝试是将String
拆分为Int
个列表,每个Int
代表一个字符:
main = putStrLn $ show $ map fromEnum "☂♞☯"
结果:
[9730,9822,9775]
现在我该如何将此列表转换为64位块列表?重要的是,我之后能够将64位块转换回String
,而不会丢失任何信息。
答案 0 :(得分:3)
The ByteString.Char8
documentation says(强调我的):
使用
ByteStrings
操作操纵Char
。所有字符将截断为8位。可以预期这些函数将以与Data.ByteString中的Word8等价物相同的速度运行。
IOW,这仅适用于您对纯ASCII字符串的期望。好吧,模块名称中的Char8
已经建议了,不是吗?所以,不,它不应该打印☂♞☯
。
你的第二种方法更有意义。为了使其可靠,您不应使用Int
而是使用Word64
;您可以使用fromIntegral . fromEnum
而不是后者转换为此类型。
尝试直接从这些单词构建ByteString
并不可取,因为类似数组的东西的纯函数级联效果不佳。但是Binary.Builder
模块有一个有效的monoid用于此目的。 monoid可以直接映射到列表上:
> toLazyByteString $ foldMap (putWord64le . fromIntegral . fromEnum) "☂♞☯"
"\STX&\NUL\NUL\NUL\NUL\NUL\NUL^&\NUL\NUL\NUL\NUL\NUL\NUL/&\NUL\NUL\NUL\NUL\NUL\NUL"
因此,这些是您要求的实际64位块。 Basicall UTF-64,当然空间效率很高。
根据你想要做的事情,一个更好的选择可能只是encode字符串:
Prelude Data.Binary> encode "☂♞☯"
"\NUL\NUL\NUL\NUL\NUL\NUL\NUL\ETX\226\152\130\226\153\158\226\152\175"
这实际上将字符串存储为UTF-8(加上存储在前八个字节中的 length 信息)。这可以很容易地撤消:
Prelude Data.Binary> putStrLn . decode $ encode "☂♞☯"
☂♞☯
答案 1 :(得分:2)
假设UTF-8,utf8-string
包实现了所需的编码算法。下面的encode
函数需要String
并返回一个无符号字节数组。
module Main where
import Codec.Binary.UTF8.String as UTF8
main :: IO ()
main =
print (UTF8.encode "☂♞☯")
输出:
λ> main
[226,152,130,226,153,158,226,152,175]
如您所见,UTF-8将您的Unicode字符串表示为九个不同的字节。您必须编写自己的代码将它们转换为64位的块。有很多不同的方法来分块!