i wrote quick , dirty function compare file contents (btw, have tested of equal size):
let eqfiles f1 f2 = let bytes1 = seq.ofarray (file.readallbytes f1) let bytes2 = seq.ofarray (file.readallbytes f2) let res = seq.comparewith (fun x y -> (int x) - (int y)) bytes1 bytes2 res = 0
i'm not happy reading whole contents array. i'd rather have lazy sequence of bytes, can't find right api in f#.
if want use full power of f#, can asynchronously. idea can asynchronously read block of specified size both files , compare blocks (using standard & simple comparison of byte arrays).
this interesting problem, because need generate asynchronous sequence (a sequence of async<t>
values generated on demand, without blocking threads simple seq<t>
or iteration). function read data , declaration of async sequence this:
edit posted snippet http://fssnip.net/1k has nicer f# formatting :-)
open system.io /// represents sequence of values 't items /// generated asynchronously on-demand type asyncseq<'t> = async<asyncseqinner<'t>> , asyncseqinner<'t> = | ended | item of 't * asyncseq<'t> /// read file 'fn' in blocks of size 'size' /// (returns on-demand asynchronous sequence) let readinblocks fn size = async { let stream = file.openread(fn) let buffer = array.zerocreate size /// returns next block 'item' of async seq let rec nextblock() = async { let! count = stream.asyncread(buffer, 0, size) if count > 0 return ended else // create buffer right size let res = if count = size buffer else buffer |> seq.take count |> array.ofseq return item(res, nextblock()) } return! nextblock() }
the asynchronous workflow comparison quite simple:
let rec compareblocks seq1 seq2 = async { let! item1 = seq1 let! item2 = seq1 match item1, item2 | item(b1, ns1), item(b2, ns2) when b1 <> b2 -> return false | item(b1, ns1), item(b2, ns2) -> return! compareblocks ns1 ns2 | ended, ended -> return true | _ -> return failwith "size doesn't match" } let s1 = readinblocks "f1" 1000 let s2 = readinblocks "f2" 1000 compareblocks s1 s2
Comments
Post a Comment