我已经用C#中的BinaryWriter写了几个整数,char []和其他数据文件。使用BinaryReader读回(在C#中)文件,我可以完美地重新创建文件的所有部分。
然而,尝试用C ++读取它们会产生一些可怕的结果。我正在使用fstream尝试回读数据并且数据未正确读取。在C ++中,我使用ios::in|ios::binary|ios::ate
设置了一个fstream并使用seekg来定位我的位置。然后我读取接下来的四个字节,它们写成整数“16”(并正确读入C#)。这在C ++中读作1244780(不是内存地址,我检查过)。为什么会这样?在C ++中是否有与BinaryReader相同的东西?我注意到它在msdn上提到过,但对我来说,Visual C ++和intellisense看起来并不像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”到哪个位置,我都会得到完全相同的值。
答案 0 :(得分:5)
你意识到C#中的字符是16位而不是C中的8位。这是因为C#中的char设计用于处理Unicode文本而不是原始数据。因此,使用BinaryWriter编写字符将导致写入Unicode而不是原始字节。
这可能会导致您错误地计算整数的偏移量。我建议您在十六进制编辑器中查看该文件,如果您无法解决该问题,请在此处发布文件和代码。
<强> EDIT1 强>
关于您的C ++代码,请不要使用&gt;&gt;运算符从二进制流中读取。将read()与要读取的int的地址一起使用。
int i;
fin.read((char*)&i, sizeof(int));
<强> EDIT2 强>
从封闭流中读取也会导致未定义的行为。你不能调用fin.close()然后仍然希望能够从中读取它。
答案 1 :(得分:3)
这可能与问题有关,也可能与此无关,但......
创建BinaryWriter时,默认以UTF-8编写char
s。这意味着它们中的一些可能超过一个字节,从而放弃了你的搜索。
您可以通过使用2参数构造函数来指定编码来避免这种情况。 System.Text.ASCIIEncoding
的实例与C / C ++默认使用的实例相同。
答案 2 :(得分:1)
如果有任何帮助,我会了解BinaryWriter如何写入数据here。
已经有一段时间但我会引用它并希望它是准确的:
答案 3 :(得分:1)
您的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;