Вычисление MD5-хэша частичного потока - PullRequest
7 голосов
/ 18 мая 2011

У меня большой набор данных (~ 1 ГБ), сохраненный в пользовательском формате файла, последние 16 байтов которого являются хешем MD5 всех предыдущих байтов файла.

Я хочу проверить MD5 этого файла по встроенному MD5, используя HashAlgorithm.ComputeHash (Stream), однако при этом будет вычисляться хэш всего файла, включая хэш за последние 16 байтов, что, очевидно, не будет работать.

Как вычислить MD5-хеш PART части потока? Я знаю, что могу прочитать поток в массив и передать его в HashAlgorithm.ComputeHash (Bytes), однако накладные расходы на дублирование этого 1 ГБ данных в памяти являются непомерно высокими.

Ответы [ 3 ]

5 голосов
/ 18 мая 2011

Взято из здесь , где вы также можете получить другие способы сделать это.

Создайте частичный класс файлового потока, прочитайте нужный размер и сделайте его хеш.

 class PartialFileStream : FileStream
{
    public PartialFileStream(string path, FileMode mode, long startPosition, long endPosition): base(path, mode)
{
  base.Seek(startPosition, SeekOrigin.Begin);
  ReadTillPosition = endPosition;
}

public long ReadTillPosition { get; set; }

public override int Read(byte[] array, int offset, int count)
{
 if (base.Position >= this.ReadTillPosition)
   return 0;

 if (base.Position + count > this.ReadTillPosition)
   count = (int)(this.ReadTillPosition - base.Position);

 return base.Read(array, offset, count);
  }
}
0 голосов
/ 13 июня 2019

Я обнаружил, что нуждаюсь в этом во второй раз в течение 6 месяцев, поэтому разместил свое решение для частичного потока ввода.

class PartialStream: Stream {
    public Stream Source { get; }
    public long Offset { get; }
    public override long Length { get; }

    private long End => Offset + Length;

    public override bool CanRead => true;

    public override bool CanSeek => false;

    public override bool CanWrite => false;

    public override long Position {
        get => Source.Position - Offset;
        set => throw new NotSupportedException();
    }

    public PartialStream(Stream source, long length) {
        Offset = source.Position;
        Length = length;
    }

    public PartialStream(Stream source, long offset, long length, bool seekToOffset = true) {
        if (seekToOffset) source.Seek(offset, SeekOrigin.Begin);
        Offset = offset;
        Length = length;
    }

    public override int Read(byte[] array, int offset, int count) {
        if (Source.Position >= End) return 0;

        if (Source.Position + count > End)
            count = (int)(End - Source.Position);

        return Source.Read(array, offset, count);
    }

    public override void Flush() => throw new NotSupportedException();
    public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
    public override void SetLength(long value) => throw new NotSupportedException();
    public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
}
0 голосов
/ 18 мая 2011

Вы можете использовать опцию FileStream.Seek для поиска определенной позиции потока и чтения оттуда.

...