Следующее решение не использует отдельный буфер в качестве решения, которое уже было опубликовано. Вместо этого он записывает непосредственно в буфер целевого потока памяти.
Это быстрее, потому что другое решение копирует дважды, сначала во временный буфер и, наконец, в поток памяти.
...
try
MemoryStream.SetSize(NumberOfBytes); // Allocating buffer
FileStream.ReadBuffer(MemoryStream.Memory^, NumberOfBytes);
finally
MemoryStream.Free();
...
Это работает, потому что SetSize также выделяет буфер потока памяти.
См. документация SetSize .
Используйте SetSize , чтобы установить размер потока памяти перед заполнением его данными. SetSize выделяет буфер памяти для хранения байтов NewSize [...].
Я также протестировал решение с CopyFrom, но это решение очень медленно работает с гигантскими файлами, потому что кажется, что оно использует очень маленький буфер.
Если файлы слишком удобны для чтения напрямую описанным выше способом, это можно сделать с помощью собственной функции, которая считывает фрагменты непосредственно в поток памяти. Чтобы быть быстрее метода CopyFrom, эти куски должны быть больше. В следующем коде используется гибкий буфер, например 256 МиБ. Пожалуйста, не стесняйтесь сделать из этого функцию.
var
...
MemoryStreamPointer: Pointer;
BlockSize: Integer;
BytesToRead: Integer;
BytesRead: Integer;
RemainingBytes: Integer;
begin
...
BlockSize := 256 * 1024 * 1024; // 256 MiB block size
MemoryStream.SetSize(NumberOfBytes); // Allocating buffer
MemoryStreamPointer := MemoryStream.Memory;
RemainingBytes := NumberOfBytes;
while RemainingBytes > 0 do
begin
BytesToRead := min(RemainingBytes, BlockSize);
BytesRead := FileStream.Read(MemoryStreamPointer^, BytesToRead);
RemainingBytes := RemainingBytes - BytesRead;
MemoryStreamPointer := Pointer(NativeInt(MemoryStreamPointer) + BytesRead);
end;
...
end;
Пожалуйста, обратите внимание, что приведенный выше код не содержит обработки ошибок.
Далее подумайте об установке позиции потоков файлов в 0 перед чтением.