将 System.Entropy 生成的字节串转换为文本

Converting ByteString Generated by System.Entropy to Text

当我 运行 此代码时,我从 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 (Yosemite)GHC 版本 7.10.1

randBSreturns随机字节不是utf-8编码的数据! 你所拥有的不是 Text 的表示,所以你使用哪个函数并不重要 will 遇到一些解码错误,所以你必须使用类似decodeUtf8With 并使用错误处理程序将无效字节替换为对应的文字。

类似于:

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 + 错误处理程序。您可以使用 base16-bytestring library. So you'd first use the encode :: ByteString -> 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