Я хочу скопировать часть FileStream в MemoryStream.
FileStream.Write(Pointer(MemoryStream)^, MemoryStream.Size);
FileStream.Read(Pointer(MemoryStream)^, count);
Это правильно? Это не работает для меня.
Я хочу скопировать часть FileStream в MemoryStream.
FileStream.Write(Pointer(MemoryStream)^, MemoryStream.Size);
FileStream.Read(Pointer(MemoryStream)^, count);
Это правильно? Это не работает для меня.
Вы должны прочитать() из FileStream в отдельный буфер, а затем записать() в MemoryStream, то есть:
var
Buffer: PByte;
GetMem(Buffer, NumberOfBytes);
try
FileStream.ReadBuffer(Buffer^, NumberOfBytes);
MemoryStream.WriteBuffer(Buffer^, NumberOfBytes);
finally
FreeMem(Buffer);
end;
Поскольку вы имеете дело с двумя объектами TStream, было бы проще использовать метод TStream.CopyFrom(), а именно:
MemoryStream.CopyFrom(FileStream, NumberOfBytes);
Следующее решение не использует отдельный буфер в качестве решения, которое уже было опубликовано. Вместо этого он записывает непосредственно в буфер целевого потока памяти. Это быстрее, потому что другое решение копирует дважды, сначала во временный буфер и, наконец, в поток памяти.
...
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 перед чтением.