![](/img/trans.png)
[英]Is there no way to handle encoding with Data.Text.IO.hGetContents?
[英]Inverse of `Data.Text.Encoding.decodeLatin1`?
是否有 function f:: Text -> Maybe ByteString
這樣的 forall x
:
f (decodeLatin1 x) == Just x
請注意, decodeLatin1
具有簽名:
decodeLatin1 :: ByteString -> Text
我擔心encodeUtf8
不是我想要的,因為我猜它所做的只是將 UTF-8 字符串轉儲為 ByteString,而不是反轉decodeLatin1
在進入上半部分字符的過程中所做的更改字符集。
我知道f
必須返回一個Maybe
,因為通常有 Unicode 個字符不在拉丁字符集中,但我只希望它至少能夠往返,因為如果我們從ByteString
開始,我們應該回到它。
免責聲明:認為這是一個很長的評論而不是一個解決方案,因為我還沒有測試過。
我想你可以用witch
library來做。 它是一個具有相當多類型安全性的通用類型轉換器庫。 有一個名為TryFrom的類型 class 用於執行可能無法轉換的類型之間的轉換。
幸運的是, witch
也提供從/到 encondings 的轉換,具有一個實例TryFrom Text (ISO_8859_1 ByteString)
,這意味着您可以在Text
和 latin1 編碼ByteString
之間進行轉換。 所以我認為(未測試!!)這應該有效
{-# LANGUAGE TypeApplications #-}
import Witch (tryInto, ISO_8859_1)
import Data.Tagged (Tagged(unTagged))
f :: Text -> Maybe ByteString
f s = case tryInto @(ISO_8859_1 ByteString) s of
Left err -> Nothing
Right bs -> Just (unTagged bs)
注意tryInto
返回一個Either TryFromException s
,所以如果你想處理錯誤,你可以用Either
來完成。 由你決定。
此外, witch
docs 指出這種轉換是通過String
類型完成的,因此可能有一個開箱即用的解決方案,無需依賴witch
package。我不知道這樣的解決方案,並期待源代碼沒有幫助
顯然已經閱讀了witch
源代碼,這應該可以工作
import qualified Data.Text as T
import Data.Char (isLatin1)
import qualified Data.ByteString.Char8 as C
f :: Text -> Maybe ByteString
f t = if allCharsAreLatin then Just (C.pack str) else Nothing
where str = T.unpack t
allCharsAreLatin = all isLatin1 str
latin1 編碼非常簡單——代碼點 X 映射到字節 X,只要它在一個字節的范圍內。 因此,只需立即打開包裝並重新包裝。
import Control.Monad
import qualified Data.Text as T
import qualified Data.ByteString.Char8 as BS
latin1EncodeText :: T.Text -> Maybe BS.ByteString
latin1EncodeText t = BS.pack (T.unpack t) <$ guard (T.all (<'\256') t)
可以避免中間String
,但在嘗試之前,您可能應該確保這是您的瓶頸。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.