2015-06-23 97 views
6

我在Windows 7 64位上。 r n在Haskell中翻譯爲 r r n

我的程序需要從外部源檢索一些文本(Utf8編碼),用它做一些事情,然後將其保存到磁盤。原始文本使用「\ r \ n」序列來表示換行符(我很樂意保持這種方式)。

問題:當使用每個Data.Text.writeFile爲 「\ r \ n」 序列似乎被譯爲 「\ r \ r \ n」,這是每一個 '\ n' 被翻譯成「\ r \ n「,,即使在原始文本之前已經有'\ r'。我知道,在Windows操作系統上寫入文件時,'\ n'應該翻譯爲「\ r \ n」,當前還沒有以'\ r'開頭,但將「\ r \ n」翻譯爲「\ r \ r \ n」似乎不正確。

使用ByteString.writeLine應用到文本的encodeUtf8版本的效果很好,但(沒有額外的 「\ r」 插入 「\ r \ n」 個序列內)

一個簡單的例子:

{-# LANGUAGE OverloadedStrings #-} 
import qualified Data.ByteString as B 
import qualified Data.Text as T 
import qualified Data.Text.IO as T (writeFile) 
import qualified Data.Text.Encoding as T (encodeUtf8) 

str = "Line 1 is here\r\nLine 2 is here\r\nLine 3 is here" :: T.Text 

main = do 
    B.writeFile "byt.bin" $ T.encodeUtf8 str 
    T.writeFile "txt.bin" str 

用十六進制編輯器查看此代碼生成的每個文件,可以看到在通過T.writeFile行生成的文件中每個x0A前面添加的額外x0D。

B.writeFile: enter image description here

T.writeFile: enter image description here

我的問題:我做了什麼錯?有沒有辦法在Windows上使用T.writeFile,而不是將「\ r \ n」翻譯成「\ r \ r \ n」?

+0

爲什麼不將文件加載到Unix風格'「\ n」' - 只有?這肯定會讓你的程序變得更容易,而且輸出也會以''\ r \ n「'出來。 – leftaroundabout

+0

@leftaroundabout:我沒有講完整個故事,但原始文本位於base64格式的文件中。我首先需要從文件中讀取BytesStrings,將它們解碼(使用Data.ByteString.Base64),然後將它們轉換爲Text(並且我可以開始操作它)。在那個階段,我可以將所有「\ r \ n」替換爲「\ n」。這是你的建議嗎? – Janthelme

+0

我確實會這樣建議。如果程序中的字符串中有Windows風格的行結尾,它可能會導致各種其他麻煩。 – leftaroundabout

回答

10

你的答案是the docs

與GHC 6.12,文本開頭的I/O是利用系統或處理的當前區域和行結束約定執行。

鑑於您自己並未打開句柄,庫似乎很可能以文本模式打開文件,導致操作系統翻譯末尾字符。您可以改爲使用openBinaryFile以二進制模式打開該文件,然後使用Data.Text.hPutStr來防止出現這種情況。

但是,處理編碼的操作系統也可能不是您想要的。根據你的情況,像你使用ByteString一樣明確地編碼/解碼字符串可能是更好的主意。

+1

謝謝。我確認解決方案openBinaryFile和hPutStr起作用。 – Janthelme