将System.Entropy生成的ByteString转换为Text

时间:2015-06-28 08:09:16

标签: haskell bytestring

当我运行此代码时,我从Data.Text收到解码错误。我究竟做错了什么?

import Data.Text                    (Text, pack, unpack)
import Data.Text.Encoding           (decodeUtf8)
import Data.ByteString              (ByteString)
import System.Entropy

randBS :: IO ByteString 
randBS = do
    randBytes <- getEntropy 2048  
    return randBytes

main :: IO ()
main = do
    r <- randBS
    putStrLn $ unpack $ decodeUtf8 r 

运行时错误:

Cannot decode byte '\xc4': Data.Text.Internal.Encoding.Fusion.streamUtf8:
Invalid UTF-8 stream

我想生成一些随机字节,用作身份验证令牌。

我在 Mac OS X(约塞米蒂) GHC版本7.10.1

1 个答案:

答案 0 :(得分:4)

randBS返回随机字节 utf-8编码数据! 你所拥有的不是Text的代表,所以你使用哪个函数遇到一些解码错误并不重要,所以你必须使用类似{{3}的东西并使用错误处理程序将无效字节替换为其文字副本。

类似的东西:

import Data.Text                    (Text, pack, unpack)
import Data.Text.Encoding           (decodeUtf8With)
import Data.ByteString              (ByteString)
import Data.Char                    (chr)
import Control.Applicative          ((<$>))
import System.Entropy

handler _ x = chr <$> fromIntegral <$> x

randBS :: IO ByteString 
randBS = do
    randBytes <- getEntropy 2048  
    return randBytes

main :: IO ()
main = do
    r <- randBS
    putStrLn $ unpack $ decodeUtf8With handler r 

未经测试,此刻我没有安装GHC:s

可能更好的是简单地使用十六进制编码而不是utf-8 +错误处理程序。您可以使用decodeUtf8With库执行此操作。因此,您首先使用base16-bytestring来获取仅具有ASCII值的表示:

import Data.Text                    (Text, pack, unpack)
import Data.ByteString              (ByteString)
import Data.ByteString.Encoding     (decodeUtf8)
import Data.ByteString.Base16       (encode)
import System.Entropy

--- ... randBS as before

main = do
    r <- randBS
    putStrLn $ unpack $ decodeUtf8 $ encode r