Consider the following simple Haskell program, which reads a file as a bytestring and writes the file tmp.tmp
from this bytestring:
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"
It is compiled to an executable named tmptmp
.
I have two hard drives on my computer: the C
drive and the U
drive, and this one is a network drive, and this network drive is offline.
Now, let's try tmptmp
.
When I run it from C
, there's no problem; I run it two times below, the first time with a file on C
and the second time with a file on U
:
C:\HaskellProjects\imagelength> tmptmp LICENSE
done
C:\HaskellProjects\imagelength> tmptmp U:\Data\ztemp\test.xlsx
done
Now I run it from U
, with a file on the C
drive, no problem:
U:\Data\ztemp> tmptmp C:\HaskellProjects\imagelength\LICENSE
done
The problem occurs when I run it from U
with a file on the U
drive:
U:\Data\ztemp> tmptmp test.xlsx
tmptmp: tmp.tmp: openBinaryFile: resource busy (file is locked)
If in my program I use strict bytestrings instead of lazy bytestrings (by replacing Data.ByteString.Lazy
with Data.ByteString
), this problem does not occur anymore.
I'd like to understand that. Any explanation? (I would particularly like to know how to solve this issue but still using lazy bytestrings)
EDIT
To be perhaps more precise, the problem still occurs with this program:
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"
while the problem disappears with:
bs <- SB.readFile file
action <- LB.writeFile "tmp.tmp" (LB.fromStrict bs)
It looks like the point causing the problem is the laziness of readFile
.
cd U:/ ; tmptmp U:/<..>/test.xlsx
? (who knows, this could be it. Windows is weird sometimes) 2. What do you mean by "this network drive is offline"? I'd like to try to reproduce but I'm not sure how one accesses a network drive which is offline (clearly I misunderstand the meaning of 'offline' here!). 3. Why do you need to use lazyBS
? It seems you've discovered thatStrict
is the right tool for the job. 4. Does it work if you force the input (i.e.evaluate (length bs)
before the write)? – Smasherxlsx
library which deals with lazy bytestrings. 4) I didn"t know theevaluate
function, I'll try. – TypehighLB.readFile
thenfromStrict
. But obviously that does not provide an explanation. – Typehighfile.access
function ofR
, the driveU
is not writeable (while it is writeable). But that would be strange thatU
is recognized as unwriteable only when I use a lazy bytestring. – TypehighgetPermissions
ofSystem.Directory
:getPermissions "U:/Data"
indicates thatU:/Data
is not writable... hmm but however it indicates thatU:/Data/zTemp
is writable. – Typehigh