将文件读取为bytestring并将此bytestring写入文件:在网络驱动器上发出问题

Sté*_*ent 6 haskell network-drive lazy-evaluation

考虑以下简单的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"
Run Code Online (Sandbox Code Playgroud)

它被编译为名为的可执行文件tmptmp.

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

现在,让我们试试吧tmptmp.

当我运行它时C,没有问题; 我在下面运行两次,第一次打开文件,C第二次打开文件U:

C:\HaskellProjects\imagelength> tmptmp LICENSE
done

C:\HaskellProjects\imagelength> tmptmp U:\Data\ztemp\test.xlsx
done
Run Code Online (Sandbox Code Playgroud)

现在我UC驱动器上的文件运行它,没问题:

U:\Data\ztemp> tmptmp C:\HaskellProjects\imagelength\LICENSE
done
Run Code Online (Sandbox Code Playgroud)

当我使用驱动器上的文件运行它UU时会发生此问题:

U:\Data\ztemp> tmptmp test.xlsx
tmptmp: tmp.tmp: openBinaryFile: resource busy (file is locked)
Run Code Online (Sandbox Code Playgroud)

如果我的节目,我用严格的字节串,而不是懒惰的字节串(替换Data.ByteString.LazyData.ByteString),不会再出现此问题.

我想明白这一点.任何解释?(我特别想知道如何解决这个问题,但仍然使用延迟字节串)

编辑

或许更精确一点,这个程序仍然会出现问题:

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"
Run Code Online (Sandbox Code Playgroud)

而问题消失了:

  bs <- SB.readFile file
  action <- LB.writeFile "tmp.tmp" (LB.fromStrict bs)
Run Code Online (Sandbox Code Playgroud)

看起来引起问题的一点是懒惰readFile.

小智 0

根据最新的Data.ByteString.Lazy 文档

\n
\n

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

\n
\n

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

\n
\n

当接下来执行 writeFile 时,[tmp.tmp] 仍然打开以供读取,并且 RTS 会注意避免同时打开它进行写入,而是返回错误。

\n
\n

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

\n