2012-01-16 106 views
8

試圖讀取字節字符串時,我總是碰到以下錯誤:
Prelude.read: no parse將ByteString轉換爲Int的最佳方式是什麼?

這裏的代碼樣本,這將導致在瀏覽器中渲染出現此錯誤:

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 [email protected][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的最佳方式是什麼?

回答

9

Show用於創建的東西String表示,這是調試純文本的序列有用。 Show typeclass不只是一種將任何東西轉換爲String的奇特方式。這就是爲什麼ByteString爲字符串添加引號的原因:因爲在調試或反序列化數據流時,可以更容易地讀取它。

可以使用Data.ByteString.Char8.unpack功能轉換ByteStringString,但要注意,這個解包ByteString字節每字節,這打亂了存儲爲多於一個字節的高價值的Unicode字符或其它字符;如果您想對結果使用read以外的其他內容,建議您將ByteString改爲Text,這樣可以提供更大的靈活性。假設在這種情況下你的編碼是UTF8(這應該是Snap中的默認值),你可以使用Data.Text.Encoding.decodeUtf8函數。要使用正確的Unicode符號將Text值轉換爲String,請使用Data.Text.unpack

一旦你有了String,你可以免費獲得read;或者,您可以選擇直接使用Data.Text.Read模塊中的功能讀取Text值。

+0

對我而言,問題#2仍然不是很清楚 - 或者它可能只是一個更具體的用例,我很好奇,我認爲它與這個最初的問題有關: 如果某種「長度字段「,它被解析爲長度爲4的ByteString,其實際上描述了一個Int32。您建議的解決方法仍然有效嗎?作爲一個更舒適的解決方案,我正在尋找一個可以接受這種類型的ByteString的庫,並返回正確的Int。有沒有可以處理這個用例的庫? – 2015-03-15 19:12:49

10

ByteString轉換爲X的最佳方法取決於X。如果從String轉換得很好,那麼通過Data.BytString.Char8.unpack可以很好,如果它是ASCII ByteString。對於編碼爲UTF-8的ByteString s,utf8-string包中包含轉換函數toString。對於某些特定類型,如標題中提到的Int,存在特殊的更快轉換。例如Data.ByteString.Char8.readIntreadInteger

+1

對於那些從互聯網進入的人:**如果「最好的方式」也意味着「高效的方式」,這就是答案!** – donatello 2015-08-28 07:53:53

相關問題