Если вы хотите использовать всю мощь F #, то вы также можете сделать это асинхронно. Идея состоит в том, что вы можете асинхронно читать блок указанного размера из обоих файлов, а затем сравнивать блоки (используя стандартное и простое сравнение байтовых массивов).
На самом деле это интересная проблема, потому что вам нужно сгенерировать что-то вроде асинхронной последовательности (последовательность значений Async<T>
, которая генерируется по требованию, но без блокировки потоков, как при простой seq<T>
или итерации). Функция для чтения данных и объявления асинхронной последовательности может выглядеть так:
РЕДАКТИРОВАТЬ Я также разместил фрагмент на http://fssnip.net/1k, который имеет лучшее форматирование F #: -)
open System.IO
/// Represents a sequence of values 'T where items
/// are generated asynchronously on-demand
type AsyncSeq<'T> = Async<AsyncSeqInner<'T>>
and 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 as 'Item' of async seq
let rec nextBlock() = async {
let! count = stream.AsyncRead(buffer, 0, size)
if count > 0 then return Ended
else
// Create buffer with the right size
let res =
if count = size then buffer
else buffer |> Seq.take count |> Array.ofSeq
return Item(res, nextBlock()) }
return! nextBlock() }
Асинхронный рабочий процесс для сравнения довольно прост:
let rec compareBlocks seq1 seq2 = async {
let! item1 = seq1
let! item2 = seq1
match item1, item2 with
| 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