我正在使用BinaryWriter将记录写入文件。记录由具有以下属性数据类型的类组成。
的Int32,
INT16,
字节[],
空字符
要编写每条记录,我会调用BinaryWriter.Write四次 - 每种数据类型一次。这工作正常,但我想知道是否有任何方法只使用所有这些数据类型一次调用BinaryWriter.Write()方法。这样做的原因是另一个程序正在读取我的二进制文件,偶尔只会读取部分记录,因为它会在我的写入调用之间开始读取。不幸的是,我无法控制其他程序的代码,否则我会修改它的读取方式。
答案 0 :(得分:2)
向您的类添加.ToBinary()
方法,返回byte []。
public byte[] ToBinary()
{
byte[] result= new byte[number_of_bytes_you_need];
// fill buf
return result;
}
在您的主叫代码中(近似我没有编译过)
stream.BinaryWrite(myObj.toBinary());
你仍然是独立编写每个值,但它会稍微清理一下代码。
此外,正如sindre所建议的那样,请考虑使用序列化,因为它使得从相关文件重新创建对象非常容易,并且比您尝试编写文件所需的工作量少。
同步:您无法依赖任何这些解决方案来修复文件同步问题。即使你设法将binaryWrite()调用减少到单个语句,而不是使用序列化或我概述的.ToBinary()方法,字节仍然由框架顺序编写。这是磁盘物理结构的限制。如果您可以控制文件格式,请添加在任何记录数据之前写入的记录长度字段。在正在读取文件的应用程序中,请确保在尝试处理文件中的下一条记录之前有record_length字节。当你在它的时候,把它放在一个数据库中。如果你无法控制文件格式,那就太不走运了。
答案 1 :(得分:1)
创建记录类并使用二进制格式化程序:
FileStream fs = new FileStream("file.dat", FileMode.Create);
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(fs, <insert instance of a class here>);
fs.Close();
我自己没有这样做,所以我不能确定它会起作用,这个类不能包含任何其他数据,这是肯定的。如果你没有运气,你可以尝试一个结构。
编辑: 刚刚想出了另一种可能的解决方案,创建数据结构并使用Buffer.BlockCopy函数:
byte[] writeBuffer = new byte[sizeof(structure)];
structure[] strucPtr = new structure[1]; // must be an array, 1 element is enough though
strucPtr[0].item1 = 0213; // initialize all the members
// Copy the structure array into the byte array.
Buffer.BlockCopy(strucPtr, 0, writeBuffer, 0, writeBuffer.Length);
现在您可以一次性将writeBuffer写入文件。
第二次编辑: 我不同意无法解决的同步问题。首先,数据在整个扇区中写入文件,而不是一次写入一个字节。并且在您刷新文件之前,文件实际上不会更新,从而写入数据并更新文件长度。最好和最安全的做法是独占打开文件,写一个记录(或几个),然后关闭文件。这要求阅读应用程序使用类似的方式来读取文件(打开ex,read,close),以及优雅地处理“拒绝访问”错误。
无论如何,无论如何,无论你一次写一整条记录,我都相信它会表现得更好。
答案 2 :(得分:1)
为了与您写入BinaryWriter一致,我希望该对象使用第二个BinaryWriter创建二进制记录,然后将其写入BinaryWriter。所以在你的课上你可以有这样的方法:
public void WriteTo(BinaryWriter writer)
{
MemoryStream ms = new MemoryStream();
BinaryWriter bw = new BinaryWriter(ms);
bw.Write(value1);
bw.Write(value2);
bw.Write(value3);
bw.Write(value4);
writer.Write(ms.ToArray());
}
这将创建一个与您已经写入主BinaryWriter的格式相同的单条记录,只需将其全部构建一次,然后将其写为字节数组。