我正在使用旧文件格式。
该文件是使用非托管C ++创建的,该C ++使用WinBase.h CreateFile()& WriteFile()函数(在kernel32.dll中找到)。
我一直在使用P / Invoke互操作来访问这些本机函数,如下所示:
[DllImport("kernel32.dll")]
public static extern bool WriteFile(
IntPtr hFile,
byte[] lpBuffer,
uint nNumberOfBytesToWrite,
out uint lpNumberOfBytesWritten,
[In] ref NativeOverlapped lpOverlapped);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool WriteFileEx(
IntPtr hFile,
byte[] lpBuffer,
uint nNumberOfBytesToWrite,
[In] ref NativeOverlapped lpOverlapped,
WriteFileCompletionDelegate lpCompletionRoutine);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr CreateFile(
string lpFileName, uint dwDesiredAccess,
uint dwShareMode, IntPtr lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool CloseHandle(IntPtr hObject);
public delegate void WriteFileCompletionDelegate(
UInt32 dwErrorCode,
UInt32 dwNumberOfBytesTransfered,
ref NativeOverlapped lpOverlapped);
这个问题是当我调用WriteFile()时,文件总是被正在进行的调用覆盖。
首选我想使用兼容的.NET等价物,这样我就可以生成完全相同的输出格式。
C ++代码如下所示:(工作)
HANDLE hFile = CreateFile(sFileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
WriteFile(hFile, &someVar1, sizeof(bool), &dwWritten, NULL);
WriteFile(hFile, &someVar1, sizeof(long), &dwWritten, NULL);
WriteFile(hFile, &someVar2, sizeof(bool), &dwWritten, NULL);
WriteFile(hFile, sStr.GetBuffer(0), dwStrLen*sizeof(TCHAR), &dwWritten, NULL);
CloseHandle(hFile);
C#如下:( OVERWRITES PREVIOUS WRITE,即输出文件只包含'T')
{
var hFile = COMFileOps2.CreateFile(FILE_NAME, (uint) COMFileOps2.FILE_GENERIC_WRITE,
COMFileOps2.FILE_SHARE_WRITE, IntPtr.Zero, COMFileOps2.CREATE_ALWAYS,
COMFileOps2.FILE_ATTRIBUTE_NORMAL, IntPtr.Zero);
var natOverlap = new NativeOverlapped();
COMFileOps2.WriteFileEx(hFile, new byte[] {(byte) 't'}, 1, ref natOverlap, Callback);
COMFileOps2.WriteFileEx(hFile, new byte[] { (byte)'e' }, 1, ref natOverlap, Callback);
COMFileOps2.WriteFileEx(hFile, new byte[] { (byte)'s' }, 1, ref natOverlap, Callback);
COMFileOps2.WriteFileEx(hFile, new byte[] { (byte)'T' }, 1, ref natOverlap, Callback);
COMFileOps2.CloseHandle(hFile);
}
private static void Callback(uint dwerrorcode, uint dwnumberofbytestransfered, ref NativeOverlapped lpoverlapped)
{
throw new NotImplementedException();
}
更新:以下C#代码会写出“测试”:
uint written;
uint position = 0;
var natOverlap0 = new NativeOverlapped();
COMFileOps.WriteFile(hFile, new byte[] {(byte) 'T'}, 1, out written, ref natOverlap0);
position += written;
var natOverlap1 = new NativeOverlapped {OffsetLow = (int) position};
COMFileOps.WriteFile(hFile, new byte[] { (byte)'e' }, 1, out written, ref natOverlap1);
position += written;
var natOverlap2 = new NativeOverlapped { OffsetLow = (int)position };
COMFileOps.WriteFile(hFile, new byte[] { (byte)'s' }, 1, out written, ref natOverlap2);
position += written;
var natOverlap3 = new NativeOverlapped { OffsetLow = (int)position };
COMFileOps.WriteFile(hFile, new byte[] { (byte)'t' }, 1, out written, ref natOverlap3);
COMFileOps.CloseHandle(hFile);
感谢。
答案 0 :(得分:4)
您没有解释您尝试处理的格式,但File.WriteAllText是否足够?
File.WriteAllText("someFile.txt", "some format");
对于二进制文件,您可以使用File.WriteAllBytes:
File.WriteAllBytes("someFile.bin", new byte[] { 0x1, 0x2, 0x3 });
答案 1 :(得分:4)
WriteFileEx只能异步运行,您必须为每个挂起的调用提供OVERLAPPED的SEPARATE实例,并且必须设置OVERLAPPED成员,例如文件偏移量。然后,在完成所有操作之前,您无法调用CloseHandle。并使用局部变量OVERLAPPED并让它超出范围?被覆盖的数据是您显示的代码可能出错的最少。
这就是为什么你的代码不起作用的原因。我不知道为什么你首先从WriteFile切换到WriteFileEx。此外,从C#调用Win32 API非常不方便,尽管偶尔需要。但首先要看看.NET File API是否能满足您的需求。
由于.NET文件API倾向于使用字符串(在textmode中,注意换行符等)或字节数组,因此需要将其他变量转换为byte []。 BitConverter课程是你的朋友。
答案 2 :(得分:1)
查看他们提供您正在寻找的方法的System.IO.File
和System.IO.FileInfo
类。
答案 3 :(得分:1)
原始API调用没有什么特别之处。只需获得System.IO.FileStream并在其上调用Write。 (获取FileStream的一种方法是首先获取System.IO.File。