11

尝试读取 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 的最佳方法是什么?
4

2 回答 2

13

ByteString将 a 转换为 an的最佳方法X取决于X. 如果您有良好的 from 转换String,则 viaData.BytString.Char8.unpack可能会很好,如果它是 ASCII 的话ByteString。对于 UTF-8 编码ByteString的,utf8-string包中包含转换函数toString。对于某些特定类型,如Int标题中提到的,存在特殊的更快转换。例如Data.ByteString.Char8.readIntreadInteger

于 2012-01-16T23:40:42.287 回答
10

Show用于创建String事物的表示,这对于调试纯文本序列化很有用。typeclassShow不仅仅是将任何东西转换为String. 这就是为什么ByteString在字符串中添加引号:因为在调试或反序列化数据流时,可以说以这种方式更容易阅读。

您可以使用该Data.ByteString.Char8.unpack函数将 a 转换ByteString为 a String,但请注意,这会ByteString逐字节解包,这会混淆高值 Unicode 字符或其他存储为多个字节的字符;如果您想做的不是read在结果上使用,我建议您将其转换ByteStringText,这样可以在这种情况下提供更大的灵活性。假设在这种情况下您的编码是 UTF8(在 Snap 中应该是默认的),您可以为此使用该Data.Text.Encoding.decodeUtf8函数。然后要将Text值转换为String具有正确 Unicode 符号的 a,请使用Data.Text.unpack.

一旦你有了String,你就read可以随心所欲地使用它;或者,您可以选择Text直接使用Data.Text.Read模块中的函数读取值。

于 2012-01-16T23:36:05.627 回答