Каков наилучший способ конвертировать String в ByteString - PullRequest
29 голосов
/ 13 июля 2010

Каков наилучший способ преобразования строки в ByteString в Haskell?

Моя внутренняя реакция на проблему

import qualified Data.ByteString as B
import Data.Char (ord)

packStr = B.pack . map (fromIntegral . ord)

Но это не кажется удовлетворительным.

Ответы [ 3 ]

24 голосов
/ 13 июля 2010

Data.ByteString.UTF8.fromString также полезен. Версия Char8 потеряет Unicode-ness, а UTF8 создаст кодировку UTF8 ByteString. Вы должны выбрать один или другой.

11 голосов
/ 08 ноября 2016

Вот моя шпаргалка для строгого / ленивого преобразования Haskell String / Text / ByteString при условии, что желаемая кодировка - UTF-8. В библиотеке Data.Text.Encoding доступны другие кодировки.

Пожалуйста, убедитесь, что не пишите (используя OverloadedStrings):

lazyByteString :: BL.ByteString
lazyByteString = "lazyByteString ä ß" -- BAD!

Это будет закодировано неожиданным способом. Попробуйте

lazyByteString = BLU.fromString "lazyByteString ä ß" -- good

вместо.

Строковые литералы типа 'Text' работают нормально с кодировкой.

Шпаргалка:

import Data.ByteString.Lazy as BL
import Data.ByteString as BS
import Data.Text as TS
import Data.Text.Lazy as TL
import Data.ByteString.Lazy.UTF8 as BLU
import Data.ByteString.UTF8 as BSU
import Data.Text.Encoding as TSE
import Data.Text.Lazy.Encoding as TLE

-- String <-> ByteString

BLU.toString   :: BL.ByteString -> String
BLU.fromString :: String -> BL.ByteString
BSU.toString   :: BS.ByteString -> String
BSU.fromString :: String -> BS.ByteString

-- String <-> Text

TL.unpack :: TL.Text -> String
TL.pack   :: String -> TL.Text
TS.unpack :: TS.Text -> String
TS.pack   :: String -> TS.Text

-- ByteString <-> Text

TLE.encodeUtf8 :: TL.Text -> BL.ByteString
TLE.decodeUtf8 :: BL.ByteString -> TL.Text
TSE.encodeUtf8 :: TS.Text -> BS.ByteString
TSE.decodeUtf8 :: BS.ByteString -> TS.Text

-- Lazy <-> Strict

BL.fromStrict :: BS.ByteString -> BL.ByteString
BL.toStrict   :: BL.ByteString -> BS.ByteString
TL.fromStrict :: TS.Text -> TL.Text
TL.toStrict   :: TL.Text -> TS.Text

Пожалуйста, ответ Пикера +1, потому что он правильно справляется с кодировкой.

10 голосов
/ 01 апреля 2014

Безопасный подход предполагает кодирование строки Unicode:

import qualified Data.ByteString as B
import qualified Data.Text as T
import Data.Text.Encoding (encodeUtf8)

packStr'' :: String -> B.ByteString
packStr'' = encodeUtf8 . T.pack

Относительно других ответов: Data.ByteString.Char8.pack фактически совпадает с версией в вопросе и вряд ли будет тем, что вы хотите:

import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as C
import qualified Data.Text as T
import Data.Text.Encoding (encodeUtf8)
import Data.Char (ord)

packStr, packStr', packStr'' :: String -> B.ByteString
packStr   = B.pack . map (fromIntegral . ord)
packStr'  = C.pack
packStr'' = encodeUtf8 . T.pack

*Main> packStr "hellö♥"
"hell\246e"
*Main> packStr' "hellö♥"
"hell\246e"
*Main> packStr'' "hellö♥"
"hell\195\182\226\153\165"

Data.ByteString.UTF8.fromString - это хорошо, но требует пакета с utf8-строкой, тогда как Data.Text.Encoding поставляется с платформой Haskell.

...