C#和IStream.读
我正在尝试使用C#中的System.Runtime.InteropServices.ComTypes.IStream,但遇到了一些问题。根据MSDN,C#的定义如下:C#和IStream.读,c#,istream,C#,Istream,我正在尝试使用C#中的System.Runtime.InteropServices.ComTypes.IStream,但遇到了一些问题。根据MSDN,C#的定义如下: void Read( byte[] pv, int cb, IntPtr pcbRead ) myPtr = (IntPtr)0; int buffSize = 8192; byte[] buffer = new byte[buffSize]; while (true) { strm.Read(buf
void Read(
byte[] pv,
int cb,
IntPtr pcbRead
)
myPtr = (IntPtr)0;
int buffSize = 8192;
byte[] buffer = new byte[buffSize];
while (true)
{
strm.Read(buffer, buffSize, myPtr);
fs.Write(buffer, 0, myPtr.ToInt32());
if (myPtr.ToInt32() < buffSize) break;
}
基本上,我可以从流中读取数据,但上面的“pcbRead”值始终为“0”(即使字节数组包含我的数据)。在阅读时,pcbRead参数似乎有点难以正确设置(尽管我对C#还是相当陌生)
总之,我的代码基本上如下所示:
void Read(
byte[] pv,
int cb,
IntPtr pcbRead
)
myPtr = (IntPtr)0;
int buffSize = 8192;
byte[] buffer = new byte[buffSize];
while (true)
{
strm.Read(buffer, buffSize, myPtr);
fs.Write(buffer, 0, myPtr.ToInt32());
if (myPtr.ToInt32() < buffSize) break;
}
myPtr=(IntPtr)0;
int buffSize=8192;
字节[]缓冲区=新字节[buffSize];
while(true)
{
strm.Read(缓冲区、buffSize、myPtr);
写入(缓冲区,0,myPtr.ToInt32());
如果(myPtr.ToInt32()
同样,问题是“myPtr”在读取后仍然包含“0”,尽管“buffer”似乎包含有效数据。我没有使用IStream的经验,但查看您的代码,我发现一些潜在错误。
变量myPtr在开始时设置为零。ItPtR像C++中的指针一样工作,所以我认为这个方法希望它把值写入MypTR点的位置。 你能试着这样做吗
unsafe
{
int pcbRead = 0;
int buffSize = 8192;
byte[] buffer = new byte[buffSize];
while (true)
{
// taking address of pcbRead
strm.Read(buffer, buffSize, new IntPtr(&pcbRead));
fs.Write(buffer, 0, pcbRead);
if (pcbRead < buffSize) break;
}
}
不安全
{
int pcbRead=0;
int buffSize=8192;
字节[]缓冲区=新字节[buffSize];
while(true)
{
//获取pcbRead的地址
strm.Read(缓冲区、buffSize、新IntPtr(&pcbRead));
fs.写入(缓冲区,0,pcbRead);
如果(pcbRead
您应该为该参数传递一个指针。函数的作用是:将实际读取的字节数写入指向的位置。这需要C#中的不安全代码,例如:
unsafe static int Read(System.Runtime.InteropServices.ComTypes.IStream strm,
byte[] buffer) {
int bytesRead = 0;
int* ptr = &bytesRead;
strm.Read(buffer, buffer.Length, (IntPtr)ptr);
return bytesRead;
}
也可以在不使用不安全关键字的情况下执行此操作:
private static IntPtr ReadBuffer;
static int Read(System.Runtime.InteropServices.ComTypes.IStream strm,
byte[] buffer) {
if (ReadBuffer == IntPtr.Zero) ReadBuffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(int)));
strm.Read(buffer, buffer.Length, ReadBuffer);
return Marshal.ReadInt32(ReadBuffer);
}
如果您只是偶尔使用此方法,则应该使用Marshal.CoTaskMemFree()来释放内存。以下是一个基于Hans答案的解决方案,它为您提供了一个类,您可以直接将其放入项目中。它为所有IStream对象提供扩展方法 这会将数据传输到.net内存流,但如果愿意,可以将其更改为文件
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
namespace YourProject
{
public static class IStreamExtensions
{
private const int bufferSize = 8192;
public static MemoryStream ReadToMemoryStream(this IStream comStream)
{
var memoryStream = new MemoryStream();
var amtRead = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(int)));
Marshal.WriteInt32(amtRead, bufferSize);
var buffer = new byte[bufferSize];
while (Marshal.ReadInt32(amtRead) > 0)
{
comStream.Read(buffer, buffer.Length, amtRead);
memoryStream.Write(buffer, 0, Marshal.ReadInt32(amtRead));
}
memoryStream.Position = 0;
return memoryStream;
}
}
}
用法:
IStream istream = (IStream) someCOMclass.giveMeAStream();
MemoryStream netStream = istream.ReadToMemoryStream();