我已经用 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,则默认为写入chars在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 和零填充
  • 浮动更复杂:它获取浮点值并取消引用它,获取十六进制的内存地址内容
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top