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

时间:2017-06-17 18:47:41

标签: haskell lazy-evaluation network-drive

考虑以下简单的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)

如果在我的程序中我使用 strict bytestrings而不是lazy bytestrings (将Data.ByteString.Lazy替换为Data.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"

虽然问题消失了:

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

导致问题的一点似乎是readFile的懒惰。

1 个答案:

答案 0 :(得分:0)

根据最新的Data.ByteString.Lazy docs

<块引用>

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

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

<块引用>

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

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