Data.ByteString 和 Data.ByteString.Char8 的区别

6
我读到,Char8仅支持ASCII字符,如果您使用其他Unicode字符,则使用它可能会很危险。
{-# LANGUAGE OverloadedStrings #-}

--import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as BC
import qualified Data.Text.IO as TIO
import qualified Data.Text.Encoding as E
import qualified Data.Text as T

name :: T.Text
name = "{ \"name\": \"哈时刻\" }"

nameB :: BC.ByteString
nameB = E.encodeUtf8 name

main :: IO ()
main = do
  BC.writeFile "test.json" nameB
  putStrLn "done"

产生相同的结果,就像

{-# LANGUAGE OverloadedStrings #-}

import qualified Data.ByteString as B
--import qualified Data.ByteString.Char8 as BC
import qualified Data.Text.IO as TIO
import qualified Data.Text.Encoding as E
import qualified Data.Text as T

name :: T.Text
name = "{ \"name\": \"哈时刻\" }"

nameB :: B.ByteString
nameB = E.encodeUtf8 name

main :: IO ()
main = do
  B.writeFile "test.json" nameB
  putStrLn "done"

那么,使用 Data.ByteString.Char8Data.ByteString 有什么区别呢?

请注意,您的两个程序实际上是相同的。类型BC.ByteStringData.ByteString.ByteString的重新导出,您将其用作B.ByteString - 因此这些字面上是指相同的类型,所有代码都是相同的,所以... - Thomas M. DuBuisson
1个回答

8
如果你比较 Data.ByteStringData.ByteString.Char8,你会发现许多在前者中引用 Word8 的函数,在后者中引用了 Char
-- Data.ByteString
map :: (Word8 -> Word8) -> ByteString -> ByteString
cons :: Word8 -> ByteString -> ByteString
snoc :: ByteString -> Word8 -> ByteString
head :: ByteString -> Word8
uncons :: ByteString -> Maybe (Word8, ByteString) 
{- and so on... -}


-- Data.ByteString.Char8
map :: (Char -> Char) -> ByteString -> ByteString
cons :: Char -> ByteString -> ByteString
snoc :: ByteString -> Char -> ByteString
head :: ByteString -> Char
uncons :: ByteString -> Maybe (Char, ByteString) 
{- and so on... -}

对于这些功能,Data.ByteString.Char8 提供了便利,不必不断地将 Word8 值转换为 Char 值。在这些函数中,只有这种情况下才会提供此类便利。writeFile 在两个模块中的行为完全相同。 以下是一种很好的方式,可以看到 TextByteStringByteString.Char8 中类似函数的不同行为:
{-# LANGUAGE OverloadedStrings #-}

import Data.Text.Encoding

import qualified Data.Text as T
import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as BC

nameText :: T.Text
nameText = "哈时刻"

nameByteString :: B.ByteString
nameByteString = encodeUtf8 nameText

main :: IO ()
main = do
  print $ T.head nameText               -- '\21704'     actual first character
  print $ B.head nameByteString         -- 229          first byte
  print $ BC.head nameByteString        -- '\299'       first byte as character

  putStrLn [ T.head nameText ]          -- 哈           actual first character
  putStrLn [ BC.head nameByteString ]   -- å            first byte as character

非常感谢您花时间向我展示不同之处。看起来如果我们不想失去Unicode字符的上下文,应该坚持使用T.Text。那么ByteString的用例是什么? - laiboonh
5
ByteString 是用于表示字节串的数据类型。包括文件读写、网络通信、大多数加密操作等等,这些操作通常最自然地使用 ByteString 进行表示。而对于文本(如准备网页中的 HTML、修改文本文档、构建用户界面等)的操作,则应该使用 Text。偶尔需要在两者之间进行转换,例如将 HTML 发送到网络上或在 stdout 上显示 UI;在这种情况下,必须选择正确的编码方式进行转换。 - Daniel Wagner
@laiboonh ByteString 用于处理原始二进制数据。而 Text 则用于处理文本数据。具体使用取决于你是要处理文本数据还是原始二进制文件/网络协议等。 - MathematicalOrchid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接