我对字节串库中的 Data.ByteString.Lazy.Char8 库有疑问。具体来说,我的问题涉及 readFile 函数,其记录如下:
将整个文件延迟读取到 ByteString 中。在 Windows 上使用“文本模式”来解释换行符
我对这个函数将“使用 Windows 上的文本模式来解释换行符”的说法感兴趣。该函数的源码如下:
-- | Read an entire file /lazily/ into a 'ByteString'. Use 'text mode'
-- on Windows to interpret newlines
readFile :: FilePath -> IO ByteString
readFile f = openFile f ReadMode >>= hGetContents
我们看到,从某种意义上说,文档中的声明是完全正确的:openFile
函数(相对于openBinaryFile
) 已被使用,因此将为文件启用换行转换。
But,然后该文件将被传递给 hGetContents。这将调用Data.ByteString.hGetNonBlocking
(见源代码here http://hackage.haskell.org/packages/archive/bytestring/0.9.1.5/doc/html/src/Data-ByteString-Lazy.html#hGetContents and here http://hackage.haskell.org/packages/archive/bytestring/0.9.1.5/doc/html/src/Data-ByteString-Lazy.html#hGetContentsN),这意味着它是一个非阻塞版本Data.ByteString.hGet
(see 文档 http://hackage.haskell.org/packages/archive/bytestring/0.9.1.7/doc/html/Data-ByteString.html#v%3ahGetNonBlocking);和(最后)Data.ByteString.hGet
calls GHC.IO.Handle.hGetBuf
(see 文档 http://hackage.haskell.org/packages/archive/bytestring/0.9.1.7/doc/html/Data-ByteString.html#v%3ahGet or 源代码 http://hackage.haskell.org/packages/archive/bytestring/0.9.1.7/doc/html/src/Data-ByteString.html#hGet)。这个函数的文档 http://hackage.haskell.org/packages/archive/base/4.2.0.2/doc/html/GHC-IO-Handle.html#v%3ahGetBuf说
hGetBuf 忽略 Handle 当前使用的任何 TextEncoding,并直接从底层 IO 设备读取字节。
这表明我们使用打开文件的事实readFile
而不是readBinaryFile
是无关紧要的:尽管问题开头提到的文档中存在声明,但数据将在不转换换行符的情况下被读取。
那么,问题的核心是:
1.我错过了什么吗? “Data.ByteString.Lazy.Char8.readFile 在 Windows 上使用文本模式来解释换行符”这一说法是否正确?或者文档只是误导性的?
附:测试还表明,这个函数(至少当我简单地使用它时)在 Windows 上不会进行换行转换。
FWIW,软件包维护者 Duncan Coutts,回应了一些非常有帮助和启发性的评论。我已经请求他允许将它们张贴在这里,但在此期间,这里有一个释义。
基本点是文档曾经是正确的,但现在可能不正确了。特别是,当人们在 Windows 中打开文件时,操作系统本身允许您以“文本”或“二进制”模式打开它。和...之间的不同readFile
and readBinaryFile
used即在操作系统的文本模式下打开文件,在 Win32 上以二进制模式打开文件。 (它们在 POSIX 上都会做同样的事情。)重要的是,如果您以操作系统的二进制模式打开一个文件,就会有no way您可以从文件中读取而无需换行符转换:它发生了always.
当事情像这样设置时,问题中提到的文档是正确的——Data.ByteString.Lazy.Char8.readFile
会使用System.IO.readFile
;这将告诉操作系统打开文件“文本”,并且换行符将被转换,即使hGetBuf
正在被使用。
然后,后来,哈斯克尔的System.IO
进行了改进,使其对换行符的处理更加灵活——特别是允许在 POSIX 操作系统上运行 Haskell 版本,其中没有使用操作系统内置的换行符读取文件的功能,但支持使用 Windows 样式换行符读取文件;或者更准确地说,支持Python风格“通用”换行符转换 http://www.python.org/dev/peps/pep-0278/在两个操作系统上。这意味着:
- 换行符的处理被引入 Haskell 库;
- 文件是always在 Windows 上以二进制模式打开,无论您使用
readFile
or readBinaryFile
; and
- 相反,选择
readFile
and readBinaryFile
会影响是否System.IO
的库代码设置为nativeNewlineMode
or noNewlineTranslation
。这将导致 Haskell 库转换为您执行适当的换行符转换。您现在还可以选择询问universalNewlineMode
.
大约在同一时间,Haskell 获得了内置的适当编码支持System.IO
(而不是假设输入为 latin-1 并简单地将输出字符截断为前 8 位)。总的来说,这是一件好事。
但是,至关重要的是,新的换行符转换现在内置于库中,永远不会影响什么hPutBuf
does---大概是因为人们建造新的System.IO
功能认为,如果以二进制方式读取罚款,任何插入自身的换行转换都可能是not程序员想要的,即是一个错误。事实上,99% 的情况可能都是如此:但在这种情况下,它会导致上述问题:-)
邓肯说,这些文档可能会发生变化,以在该库的未来版本中反映这个美丽的新世界。在过渡期,这个问题的另一个答案中列出了一个解决方法。 https://stackoverflow.com/a/6860159/194894
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)