将ByteString转换为Int的最佳方法是什么?

时间:2012-01-16 23:25:53

标签: haskell bytestring

尝试读取ByteString时,我总是遇到以下错误:
Prelude.read: no parse

以下是在浏览器中呈现时会导致此错误的代码示例:

factSplice :: SnapletSplice App App
factSplice = do
    mbstr <- getParam "input" -- returns user input as bytestring
    let str = maybe (error "splice") show mbstr
    let n = read str :: Int
    return [X.TextNode $ T.pack $ show $ product [1..n]]

或者更简单:

simple bs = read (show bs) :: Int

出于某种原因,在show bs之后,结果字符串包含引号。 因此,为了解决错误,我必须删除引号然后read它。 我使用从互联网复制的以下功能来执行此操作:

sq :: String -> String
sq s@[c]                     = s
sq ('"':s)  | last s == '"'  = init s
            | otherwise      = s
sq ('\'':s) | last s == '\'' = init s
            | otherwise      = s
sq s                         = s

然后simple bs = read (sq.show bs) :: Int按预期工作。

  1. 为什么会这样?
  2. 将ByteString转换为Int的最佳方法是什么?

2 个答案:

答案 0 :(得分:10)

ByteString转换为X的最佳方式取决于X。如果您从String转换得很好,那么通过Data.BytString.Char8.unpack进行转换可能会很好,如果它是ASCII ByteString。对于UTF-8编码的ByteStringutf8-string包中包含转换函数toString。对于某些特定类型,例如标题中提到的Int,存在特殊的更快转换。例如Data.ByteString.Char8.readIntreadInteger

答案 1 :(得分:9)

Show用于创建某事物的String表示,这对调试纯文本序列化非常有用。 Show类型类不仅仅是将任何东西转换为String的奇特方式。这就是ByteString为字符串添加引号的原因:因为在调试或反序列化数据流时,以这种方式读取它会更容易。

您可以使用Data.ByteString.Char8.unpack函数将ByteString转换为String,但请注意,这会解压缩ByteString每字节字节数,这会高度混乱-value Unicode字符或存储为多个字节的其他字符;如果您想对结果使用read以外的其他操作,我建议您将ByteString转换为Text,这样可以在这种情况下提供更大的灵活性。假设在这种情况下你的编码是UTF8(因为它应该是Snap中的默认值),你可以使用Data.Text.Encoding.decodeUtf8函数。要使用正确的Unicode符号将Text值转换为String,请使用Data.Text.unpack

获得String后,您可以随心所欲read获取;或者,您可以选择使用Data.Text.Read模块中的函数直接读取Text值。