直接在C#wout复制中读取大型二进制文件

直接在C#wout复制中读取大型二进制文件,第1张

概述我正在寻找最有效/直接的方式来做这个简单的C/C++ *** 作: void ReadData(FILE *f, uint16 *buf, int startsamp, int nsamps){ fseek(f, startsamp*sizeof(uint16), SEEK_SET); fread(buf, sizeof(uint16), nsamps, f);} 在C#/.NET中. ( 我正在寻找最有效/直接的方式来做这个简单的C/C++ *** 作:
voID ReadData(file *f,uint16 *buf,int startsamp,int nsamps){   fseek(f,startsamP*sizeof(uint16),SEEK_SET);   fread(buf,sizeof(uint16),nsamps,f);}

在C#/.NET中. (为了清晰起见,我忽略了返回值 – 生产代码会检查它们.)具体来说,我需要读取许多(可能是10到100的数百万)2字节(16位)“ushort”整数数据样本(固定格式),不需要解析)以二进制形式存储在磁盘文件中.关于C方式的好处是它将样本直接读入“uint16 *”缓冲区,没有cpu参与,也没有复制.是的,它可能是“不安全的”,因为它使用voID *指针指向未知大小的缓冲区,但似乎应该有一个“安全”的.NET替代品.

在C#中实现这一目标的最佳方法是什么?我环顾四周,发现了一些提示(使用FIEldOffset的“工会”,使用指针编组的“不安全”代码,编组),但似乎没有一个适用于这种情况,没有使用某种复制/转换.我想避免使用BinaryReader.ReadUInt16(),因为这非常慢并且cpu密集.在我的机器上,带有ReadUInt16()的for()循环与使用单个Read()直接读入byte []数组之间的速度差异约为25倍.使用非阻塞I / O(在等待磁盘I / O时重叠“有用”处理),该比率可能更高.

理想情况下,我想简单地“伪装”一个ushort []数组作为byte []数组,这样我就可以用Read()直接填充它,或者以某种方式让Read()直接填充ushort []数组:

// DOES NOT WORK!!public voID GetData(fileStream f,ushort [] buf,int nsamps){    f.position = startsamP*sizeof(ushort);    f.Read(buf,nsamps);}

但是没有Read()方法接受一个ushort []数组,只有一个byte []数组.

这可以直接在C#中完成,还是需要使用非托管代码或第三方库,还是必须采用cpu密集型逐个样本转换?虽然“安全”是首选,但我可以使用“不安全”的代码,或者使用Marshal的一些技巧,我还没想到它.

谢谢你的指导!

[UPDATE]

我想按照dtb的建议添加一些代码,因为似乎有很少的ReadArray实例.这是一个非常简单的,没有显示错误检查.

public voID ReadMap(string fname,short [] data,int nsamps){    var mmf = MemoryMappedfile.CreateFromfile(fname);    var mmacc = mmf.CreateVIEwAccessor();    mmacc.ReadArray(startsamP*sizeof(short),data,nsamps);}

数据被安全地转储到您传递的数组中.您还可以为更复杂的类型指定类型.它似乎能够自己推断出简单类型,但是使用类型说明符,它看起来像这样:

mmacc.ReadArray<short>(startsamP*sizeof(short),nsamps);

[UPATE2]

我希望按照Ben的获胜答案添加代码,以“裸骨”形式(类似于上面)进行比较.此代码经过编译和测试,可以正常运行.我直接在Dllimport(而不是更常用的IntPtr)中使用SafefileHandle类型来简化 *** 作.

[Dllimport("kernel32.dll",SetLastError=true)][return:MarshalAs(UnmanagedType.Bool)]static extern bool Readfile(SafefileHandle handle,IntPtr buffer,uint numBytesToRead,out uint numBytesRead,IntPtr overlapped);[Dllimport("kernel32.dll",SetLastError=true)][return:MarshalAs(UnmanagedType.Bool)]static extern bool SetfilePointerEx(SafefileHandle hfile,long lidistancetoMove,out long lpNewfilePointer,uint DWMoveMethod);unsafe voID ReadPINV(fileStream f,short[] buffer,int nsamps){    long unused; uint BytesRead;    SafefileHandle nativeHandle = f.SafefileHandle; // clears position property    SetfilePointerEx(nativeHandle,startsamP*sizeof(short),out unused,0);    fixed(short* pFirst = &buffer[0])        Readfile(nativeHandle,(IntPtr)pFirst,(uint)nsamps*sizeof(short),out BytesRead,IntPtr.Zero);}
解决方法 dtb’s answer是一个更好的方法(实际上,它也必须复制数据,没有增益),但我只想指出从字节数组中提取ushort值你应该使用 BitConverter而不是BinaryReader

编辑:p /调用ReadFile的示例代码:

[Dllimport("kernel32.dll",SetLastError=true)][return:MarshalAs(UnmanagedType.Bool)]static extern bool Readfile(IntPtr handle,SetLastError=true)][return:MarshalAs(UnmanagedType.Bool)]static extern bool SetfilePointerEx(IntPtr hfile,uint DWMoveMethod);unsafe bool read(fileStream fs,ushort[] buffer,int offset,int count){  if (null == fs) throw new ArgumentNullException();  if (null == buffer) throw new ArgumentNullException();  if (offset < 0 || count < 0 || offset + count > buffer.Length) throw new ArgumentException();  uint bytesToRead = 2 * count;  if (bytesToRead < count) throw new ArgumentException(); // detect integer overflow  long offset = fs.position;  SafefileHandle nativeHandle = fs.SafefileHandle; // clears position property  try {    long unused;    if (!SetfilepositionEx(nativeHandle,offset,0);    fixed (ushort* pFirst = &buffer[offset])      if (!Readfile(nativeHandle,new IntPtr(pFirst),bytesToRead,out bytesToRead,IntPtr.Zero)        return false;    if (bytesToRead < 2 * count)      return false;    offset += bytesToRead;    return true;  }  finally {    fs.position = offset; // restore position property  }}
总结

以上是内存溢出为你收集整理的直接在C#w / out复制中读取大型二进制文件全部内容,希望文章能够帮你解决直接在C#w / out复制中读取大型二进制文件所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1254869.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-07
下一篇 2022-06-07

发表评论

登录后才能评论

评论列表(0条)

保存