回答haskell-convert-unicode-sequence-to-utf-8我遇到了ByteString.putStrLn
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Data.Text (Text)
import Data.ByteString (ByteString)
import qualified Data.ByteString.Char8 as B
inputB, inputB' :: ByteString
inputB = "ДЕЖЗИЙКЛМНОПРСТУФ"
inputB' = "test"
main :: IO ()
main = do putStr "B.putStrLn inputB: "; B.putStrLn inputB
putStr "print inputB: "; print inputB
putStr "B.putStrLn inputB': "; B.putStrLn inputB'
putStr "print inputB': "; print inputB'
产生
B.putStrLn inputB:
rint inputB: "\DC4\NAK\SYN\ETB\CAN\EM\SUB\ESC\FS\GS\RS\US !\"#$"
B.putStrLn inputB': test
print inputB': "test"
我在这里不明白的是 - 为什么第一行输出行缺少和第二行打印的 p 缺失。
我的猜测是,这与导致输入错误的俄语字母有关。因为简单的“测试”案例才有效。
xxd输出
> stack exec -- unicode | xxd
00000000: 422e 7075 7453 7472 4c6e 2069 6e70 7574 B.putStrLn input
00000010: 423a 2014 1516 1718 191a 1b1c 1d1e 1f20 B: ............
00000020: 2122 2324 0a70 7269 6e74 2069 6e70 7574 !"#$.print input
00000030: 423a 2022 5c44 4334 5c4e 414b 5c53 594e B: "\DC4\NAK\SYN
00000040: 5c45 5442 5c43 414e 5c45 4d5c 5355 425c \ETB\CAN\EM\SUB\
00000050: 4553 435c 4653 5c47 535c 5253 5c55 5320 ESC\FS\GS\RS\US
00000060: 215c 2223 2422 0a42 2e70 7574 5374 724c !\"#$".B.putStrL
00000070: 6e20 696e 7075 7442 273a 2074 6573 740a n inputB': test.
00000080: 7072 696e 7420 696e 7075 7442 273a 2022 print inputB': "
00000090: 7465 7374 220a test".
文库
> stack exec -- ghc-pkg list
/opt/ghc/7.10.3/lib/ghc-7.10.3/package.conf.d
Cabal-1.22.5.0
array-0.5.1.0
base-4.8.2.0
bin-package-db-0.0.0.0
binary-0.7.5.0
bytestring-0.10.6.0
containers-0.5.6.2
deepseq-1.4.1.1
directory-1.2.2.0
filepath-1.4.0.0
ghc-7.10.3
ghc-prim-0.4.0.0
haskeline-0.7.2.1
hoopl-3.10.0.2
hpc-0.6.0.2
integer-gmp-1.0.0.0
pretty-1.1.2.0
process-1.2.3.0
rts-1.0
template-haskell-2.10.0.0
terminfo-0.4.0.1
time-1.5.0.1
transformers-0.4.2.0
unix-2.7.1.0
xhtml-3000.2.1
/home/epsilonhalbe/.stack/snapshots/x86_64-linux/lts-5.5/7.10.3/pkgdb
text-1.2.2.0
/home/epsilonhalbe/programming/unicode/.stack-work/install/x86_64-linux/lts-5.5/7.10.3/pkgdb
和语言环境
> locale
LANG=en_US.UTF-8
LANGUAGE=
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC=de_AT.UTF-8
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY=de_AT.UTF-8
LC_MESSAGES="en_US.UTF-8"
LC_PAPER=de_AT.UTF-8
LC_NAME=de_AT.UTF-8
LC_ADDRESS=de_AT.UTF-8
LC_TELEPHONE=de_AT.UTF-8
LC_MEASUREMENT=de_AT.UTF-8
LC_IDENTIFICATION=de_AT.UTF-8
LC_ALL=
答案 0 :(得分:1)
这不是终端问题,而是在转换为ByteString的早期问题发生。请记住,因为您使用了OverloadedStrings
inputB = "ДЕЖЗИЙКЛМНОПРСТУФ"
是
的简写inputB = fromString "ДЕЖЗИЙКЛМНОПРСТУФ"::ByteString
使用UTF8不会转换为字节字符串。
相反,如果您希望bytestring包含utf8编码的字符,请使用
import qualified Data.ByteString.UTF8 as BU
inputB = BU.fromString "ДЕЖЗИЙКЛМНОПРСТУФ"
然后这将起作用
B.putStrLn inputB
为什么第二行的“p”缺失?
我不会详细说明(因为我不知道它们),但行为是预期的....因为你的终端期待UTF8,俄语字符串不是UTF8。
UTF8使用可变长度字节字符编码....根据char中的第一个字节,它可能会有更多。很明显,俄语字符串中的最后一个字节开始需要更多字节的UTF8编码,并且“p”被读入该字符串。你的终端似乎只是忽略它无法打印的字符(我的打印垃圾),所以俄罗斯字符串和下一个字符都丢失了。
你会注意到“p”在xxd输出中....终端只是认为它是未知字符的一部分而不是打印它。
答案 1 :(得分:1)
引自Data.ByteString.Char8
的文件
(强调我的)
使用Char操作处理ByteStrings。 所有的Chars都会 截断为8位。可以预期这些函数将运行 与Data.ByteString中的Word8等效速度相同。
更具体地说,这些字节字符串被认为是在子集中 代码点0-255涵盖的Unicode。这包括Unicode Basic Latin, Latin-1 Supplement和C0 + C1 Controls。
Cyrillic未在代码点0x00-0xFF中分配,因此可以预期编码问题。
除非您处理纯ASCII,否则我建议反对 Data.ByteString.Char8
。即使拉丁-1编码的文本可能在某些环境中起作用,拉丁-1编码也会过时并且应该死掉。
要处理常规字符串,请改用Data.Text
。转换功能从ByteString
s到Text
,反之亦然,are provided。当然,这些功能必须依赖于某些编码。