【问题标题】:Read file as bytestring and write this bytestring to a file: issue on a network drive将文件读取为字节串并将此字节串写入文件:网络驱动器上的问题
【发布时间】:2017-11-20 08:24:59
【问题描述】:

考虑以下简单的 Haskell 程序,它将文件作为字节串读取并从该字节串写入文件tmp.tmp

module Main
  where
import System.Environment
import qualified Data.ByteString.Lazy as B

main :: IO ()
main = do
  [file] <- getArgs
  bs <- B.readFile file
  action <- B.writeFile "tmp.tmp" bs
  putStrLn "done"

它被编译成一个名为tmptmp的可执行文件。

我的电脑上有两个硬盘驱动器:C 驱动器和 U 驱动器,这个是网络驱动器,这个网络驱动器处于脱机状态

现在,让我们试试tmptmp

当我从C 运行它时,没有问题;我在下面运行了两次,第一次使用C 上的文件,第二次使用U 上的文件:

C:\HaskellProjects\imagelength> tmptmp LICENSE
done

C:\HaskellProjects\imagelength> tmptmp U:\Data\ztemp\test.xlsx
done

现在我从U 运行它,在C 驱动器上有一个文件,没问题:

U:\Data\ztemp> tmptmp C:\HaskellProjects\imagelength\LICENSE
done

当我使用U 驱动器上的文件从U 运行它时会出现问题

U:\Data\ztemp> tmptmp test.xlsx
tmptmp: tmp.tmp: openBinaryFile: resource busy (file is locked)

如果在我的程序中我使用严格字节串而不是惰性字节串(通过将Data.ByteString.Lazy 替换为Data.ByteString),这个问题不会再发生。 p>

我想明白这一点。有什么解释吗? (我特别想知道如何解决这个问题但仍然使用惰性字节串)

编辑

也许更准确地说,这个程序仍然存在问题:

import qualified Data.ByteString as SB
import qualified Data.ByteString.Lazy as LB

main :: IO ()
main = do
  [file] <- getArgs
  bs <- LB.readFile file
  action <- SB.writeFile "tmp.tmp" (LB.toStrict bs)
  putStrLn "done"

当问题消失时:

  bs <- SB.readFile file
  action <- LB.writeFile "tmp.tmp" (LB.fromStrict bs)

看起来问题的关键在于readFile的懒惰。

【问题讨论】:

  • 1.如果你给它一个绝对路径(即cd U:/ ; tmptmp U:/&lt;..&gt;/test.xlsx?(谁知道,这可能就是它。Windows 有时很奇怪)2。你的意思是“这个网络驱动器离线”是什么意思?我想尝试重现,但我不确定如何访问离线的网络驱动器(显然我在这里误解了“离线”的含义!)。3.为什么需要使用惰性BS?看来你已经发现Strict 是适合这项工作的工具。4. 如果强制输入(即写入前的evaluate (length bs))是否有效?
  • 嗨@user2407038。 1) 没有。 2) 这是我工作的笔记本电脑,我没有连接到域。在 Windows 资源管理器中,您有一个“离线工作/在线工作”按钮。如果要复制,请单击“脱机工作”。 3)这只是一个最小的可重现示例。在现实生活中,我使用的是处理惰性字节串的xlsx 库。 4)我不知道evaluate函数,我试试。
  • 2) 或者干脆断开您的计算机与 Internet 的连接。
  • 我刚刚通过使用我编辑的最后一点的策略解决了我的现实问题,LB.readFile 然后fromStrict。但显然这并不能提供解释。
  • 不幸的是,我无法重现(在 W7 上)。我认为这是因为我没有可以通过这种方式访问​​的实际远程位置,但 Windows 允许我使用本地(共享)文件夹“映射网络驱动器”。使用此设置,没有“脱机工作”按钮,它与惰性 ByteString 一起工作得很好。

标签: haskell lazy-evaluation network-drive


【解决方案1】:

根据最近的Data.ByteString.Lazy docs

使用 readFile 或 hGetContents 等惰性 I/O 函数意味着关闭文件句柄等操作的顺序由 RTS 自行决定。

给出的离线网络驱动器示例可能会导致 RTS 从 readFile 继续而不关闭文件。有一个几乎相同的例子的文档说

下次执行 writeFile 时,[tmp.tmp] 仍处于打开状态进行读取,RTS 会注意避免同时打开它进行写入,而是返回错误。

据我所知,Data.ByteString.Lazy 中没有解决方案——文档中建议了您的解决方案(使用严格读取)和其他包。有时读取和写入同一个文件可以工作,但你不能保证。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多