C++ 中是否有 BinaryReader 可以读取从 C# 中的 BinaryWriter 写入的数据?
-
20-09-2019 - |
题
我已经用 C# 中的 BinaryWriter 将几个 int、char[] 等写入数据文件。使用 BinaryReader 读回文件(在 C# 中),我可以完美地重新创建文件的所有部分。
然而,尝试用 C++ 读回它们会产生一些可怕的结果。我正在使用 fstream 尝试读回数据,但数据未正确读入。在 C++ 中,我设置了一个 fstream ios::in|ios::binary|ios::ate
并使用eekg来定位我的位置。然后,我读取接下来的四个字节,它们被写为整数“16”(并正确读入 C#)。这在 C++ 中读作 1244780 (不是内存地址,我检查过)。为什么会这样呢?C++ 中是否有与 BinaryReader 等效的工具?我注意到 msdn 上提到了它,但那是 Visual C++,而智能感知对我来说甚至看起来都不像 C++。
写入文件的示例代码(C#):
public static void OpenFile(string filename)
{
fs = new FileStream(filename, FileMode.Create);
w = new BinaryWriter(fs);
}
public static void WriteHeader()
{
w.Write('A');
w.Write('B');
}
public static byte[] RawSerialize(object structure)
{
Int32 size = Marshal.SizeOf(structure);
IntPtr buffer = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(structure, buffer, true);
byte[] data = new byte[size];
Marshal.Copy(buffer, data, 0, size);
Marshal.FreeHGlobal(buffer);
return data;
}
public static void WriteToFile(Structures.SomeData data)
{
byte[] buffer = Serializer.RawSerialize(data);
w.Write(buffer);
}
我不确定如何向您展示数据文件。
读回数据的示例(C#):
BinaryReader reader = new BinaryReader(new FileStream("C://chris.dat", FileMode.Open));
char[] a = new char[2];
a = reader.ReadChars(2);
Int32 numberoffiles;
numberoffiles = reader.ReadInt32();
Console.Write("Reading: ");
Console.WriteLine(a);
Console.Write("NumberOfFiles: ");
Console.WriteLine(numberoffiles);
我想用 C++ 执行此操作。初始尝试(在第一个整数处失败):
fstream fin("C://datafile.dat", ios::in|ios::binary|ios::ate);
char *memblock = 0;
int size;
size = 0;
if (fin.is_open())
{
size = static_cast<int>(fin.tellg());
memblock = new char[static_cast<int>(size+1)];
memset(memblock, 0, static_cast<int>(size + 1));
fin.seekg(0, ios::beg);
fin.read(memblock, size);
fin.close();
if(!strncmp("AB", memblock, 2)){
printf("test. This works.");
}
fin.seekg(2); //read the stream starting from after the second byte.
int i;
fin >> i;
编辑:似乎无论我在哪个位置使用“seekg”,我都会收到完全相同的值。
解决方案
您意识到,char是在C#,而不是8通常是在C.这是因为在C#中的炭被设计为处理Unicode文本而不是原始数据的16位。因此,使用的BinaryWriter将导致的Unicode字符写入被写入,而不是原始字节。
这可以具有引线你计算偏移的整数的不正确。我建议你看看在十六进制编辑器的文件,如果你不能尝试解决问题发布文件,这里的代码。
<强> EDIT1 强>结果 关于你的C ++代码,不使用>>操作从二进制流中读取。使用与你想读为int的地址读取()。
int i;
fin.read((char*)&i, sizeof(int));
<强> EDIT2 强>结果 从一个封闭的流读数也将导致不确定的行为。你不能调用fin.close()之后,还期望能够从中读取数据。
其他提示
这可以或可以不涉及到这个问题,但...
当创建的BinaryWriter,则默认为写入char
s在UTF-8。这意味着,它们中的一些可能长于一个字节,摆脱你的目的。
可以通过使用2参数构造指定编码避免这种情况。 System.Text.ASCIIEncoding
将是一样的东西默认为C / C ++使用。
有许多事情在你的C ++代码段会错。你不应该与格式读取二进制阅读混合:
// The file is closed after this line. It is WRONG to read from a closed file.
fin.close();
if(!strncmp("AB", memblock, 2)){
printf("test. This works.");
}
fin.seekg(2); // You are moving the "get pointer" of a closed file
int i;
// Even if the file is opened, you should not mix formatted reading
// with binary reading. ">>" is just an operator for reading formatted data.
// In other words, it is for reading "text" and converting it to a
// variable of a specific data type.
fin >> i;
如果有任何帮助,我了解了 BinaryWriter 如何写入数据 这里.
已经有一段时间了,但我会引用它并希望它是准确的:
- Int16 被写入 2 个字节并进行填充。
- Int32 被写为 Little Endian 和零填充
- 浮动更复杂:它获取浮点值并取消引用它,获取十六进制的内存地址内容