简体   繁体   English

C ++中是否有BinaryReader来读取从C#中的BinaryWriter写入的数据?

[英]Is there a BinaryReader in C++ to read data written from a BinaryWriter in C#?

I've written several ints, char[]s and the such to a data file with BinaryWriter in C#. 我已经用C#中的BinaryWriter将几个int,char []等写入了数据文件。 Reading the file back in (in C#) with BinaryReader, I can recreate all of the pieces of the file perfectly. 使用BinaryReader用C#读回文件,我可以完美地重新创建文件的所有部分。

However, attempting to read them back in with C++ yields some scary results. 但是,尝试用C ++读回它们会产生一些可怕的结果。 I was using fstream to attempt to read back the data and the data was not reading in correctly. 我正在使用fstream尝试读回数据,但数据未正确读入。 In C++, I set up an fstream with ios::in|ios::binary|ios::ate and used seekg to target my location. 在C ++中,我使用ios::in|ios::binary|ios::ate设置了一个fstream,并使用seekg来定位我的位置。 I then read the next four bytes, which were written as the integer "16" (and reads correctly into C#). 然后,我读取接下来的四个字节,它们被写为整数“ 16”(并正确地读入C#)。 This reads as 1244780 in C++ (not the memory address, I checked). 在C ++中,它读为1244780(不是我检查过的内存地址)。 Why would this be? 为什么会这样呢? Is there an equivalent to BinaryReader in C++? C ++中有与BinaryReader等效的东西吗? I noticed it mentioned on msdn, but that's Visual C++ and intellisense doesn't even look like c++, to me. 我注意到它在msdn上提到,但是对我来说,这是Visual C ++,而intellisense甚至看起来都不像c ++。

Example code for writing the file (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);
    }

I'm not sure how I could show you the data file. 我不确定如何显示数据文件。

Example of reading the data back (C#): 读回数据的示例(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);

This I want to perform in c++. 我想在c ++中执行此操作。 Initial attempt (fails at first integer): 初始尝试(以第一个整数失败):

 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;

Edit: It seems that no matter what location I use "seekg" to, I receive the exact same value. 编辑:看来,无论我使用“ seekg”到什么位置,我都会收到完全相同的值。

You realize that a char is 16 bits in C# rather than the 8 it usually is in C. This is because a char in C# is designed to handle Unicode text rather than raw data. 您意识到在C#中char是16位,而不是在C中通常是8位。这是因为C#中的char被设计为处理Unicode文本而不是原始数据。 Therefore, writing chars using the BinaryWriter will result in Unicode being written rather than raw bytes. 因此,使用BinaryWriter编写字符将导致写入Unicode而不是原始字节。

This may have lead you to calculate the offset of the integer incorrectly. 这可能导致您错误地计算了整数的偏移量。 I recommend you take a look at the file in a hex editor, and if you cannot work out the issue post the file and the code here. 我建议您在十六进制编辑器中查看文件,如果无法解决问题,请在此处发布文件和代码。

EDIT1 编辑1
Regarding your C++ code, do not use the >> operator to read from a binary stream. 关于您的C ++代码,请勿使用>>运算符从二进制流中读取。 Use read() with the address of the int that you want to read to. 将read()与要读取的int的地址一起使用。

int i;
fin.read((char*)&i, sizeof(int));

EDIT2 编辑2
Reading from a closed stream is also going to result in undefined behavior. 从关闭的流中读取也将导致未定义的行为。 You cannot call fin.close() and then still expect to be able to read from it. 您不能调用fin.close(),然后仍然希望能够从中读取。

This may or may not be related to the problem, but... 这可能与问题无关,但...

When you create the BinaryWriter, it defaults to writing char s in UTF-8. 创建BinaryWriter时,默认情况下是使用UTF-8编写char This means that some of them may be longer than one byte, throwing off your seeks. 这意味着它们中的一些可能会超过一个字节,从而使您的查找工作中断。

You can avoid this by using the 2 argument constructor to specify the encoding. 您可以通过使用2参数构造函数指定编码来避免这种情况。 An instance of System.Text.ASCIIEncoding would be the same as what C/C++ use by default. System.Text.ASCIIEncoding的实例与默认情况下C / C ++使用的实例相同。

If it's any help, I went through how the BinaryWriter writes data here . 如果有帮助,我会在这里介绍BinaryWriter如何写入数据。

It's been a while but I'll quote it and hope it's accurate: 已经有一段时间了,但我会引用它,希望它是准确的:

  • Int16 is written as 2 bytes and padded. Int16被写为2个字节并被填充。
  • Int32 is written as Little Endian and zero padded Int32编写为Little Endian,零填充
  • Floats are more complicated: it takes the float value and dereferences it, getting the memory address's contents which is a hexadecimal 浮点数更为复杂:它需要一个浮点数并对其进行解引用,从而获得内存地址的内容(为十六进制)

There are many thing going wrong in your C++ snippet. 您的C ++代码段中有很多错误。 You shouldn't mix binary reading with formatted reading: 您不应将二进制阅读与格式化阅读混合使用:

  // 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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM