使用 MemoryMappedFile 作为 BinaryReader
Use MemoryMappedFile as BinaryReader
我正在使用 MemoryMappedFile(MMF) 将大文件放入内存。使用内存限制 32MB。使用 MMF 加载 50MB 文件需要 2-3 秒。从 MMF 读取数据工作正常且快速。
对我来说唯一的问题是:我有一个大项目,在多个地方大量使用 BigEndianReader(派生自 BinaryReader)。与其重写代码,我更喜欢修改此 class 以将 BinaryReader 调用替换为 MMF 调用。有人知道如何从 MMF 创建 strteam 吗?我有 MMF 的 IntPtr,但我不明白如何从中创建 Stream。
您必须子class Stream
,跟踪流的 Position
和当前映射的片段:
public class MmfStream : Stream
{
private IntPtr currentMap;
private long mapOffset;
private long mapSize;
private long position;
Stream
基础 class 要求您实现 Read
和 Write
方法,因此每当应用程序尝试读取或写入时,您都可以使用 Marshal.Copy
从当前映射段复制数据。
如果流的 Position
超出映射段,您将创建一个新映射并提供来自新映射段的信息。您还必须处理必须从当前 和 新映射的视图访问数据的问题。类似于:
public override int Read(byte[] buffer, int offset, int size)
{
// current position not in current mapping?
if (position < mapOffset)
{
// relocate the view
}
// compute how many bytes can be read from the current segment
int read = Math.Min(size, (mapOffset + mapSize) - position);
// copy those bytes to the buffer
Marshal.Copy(...);
position += read;
if (size > read)
{
// recurse for the remaining bytes
read += Read(buffer, offset + read, size - read);
}
return read;
}
(此代码片段中可能存在一次性错误;这只是对想法的说明)
我正在使用 MemoryMappedFile(MMF) 将大文件放入内存。使用内存限制 32MB。使用 MMF 加载 50MB 文件需要 2-3 秒。从 MMF 读取数据工作正常且快速。 对我来说唯一的问题是:我有一个大项目,在多个地方大量使用 BigEndianReader(派生自 BinaryReader)。与其重写代码,我更喜欢修改此 class 以将 BinaryReader 调用替换为 MMF 调用。有人知道如何从 MMF 创建 strteam 吗?我有 MMF 的 IntPtr,但我不明白如何从中创建 Stream。
您必须子class Stream
,跟踪流的 Position
和当前映射的片段:
public class MmfStream : Stream
{
private IntPtr currentMap;
private long mapOffset;
private long mapSize;
private long position;
Stream
基础 class 要求您实现 Read
和 Write
方法,因此每当应用程序尝试读取或写入时,您都可以使用 Marshal.Copy
从当前映射段复制数据。
如果流的 Position
超出映射段,您将创建一个新映射并提供来自新映射段的信息。您还必须处理必须从当前 和 新映射的视图访问数据的问题。类似于:
public override int Read(byte[] buffer, int offset, int size)
{
// current position not in current mapping?
if (position < mapOffset)
{
// relocate the view
}
// compute how many bytes can be read from the current segment
int read = Math.Min(size, (mapOffset + mapSize) - position);
// copy those bytes to the buffer
Marshal.Copy(...);
position += read;
if (size > read)
{
// recurse for the remaining bytes
read += Read(buffer, offset + read, size - read);
}
return read;
}
(此代码片段中可能存在一次性错误;这只是对想法的说明)