Pregunta

He escrito varios enteros, char s [] y el tipo a un archivo de datos con BinaryWriter en C #. Al leer el archivo de nuevo en (en C #) con BinaryReader, puedo volver a crear todas las piezas del archivo de la perfección.

Sin embargo, intentar leer de nuevo en C ++ produce algunos resultados de miedo. Yo estaba usando fstream para intentar volver a leer los datos y los datos no estaba leyendo correctamente. En C ++, se configura un fstream con ios::in|ios::binary|ios::ate y se utiliza para apuntar seekg mi ubicación. luego leí los siguientes cuatro bytes, que fueron escritos como el número entero "16" (y lee correctamente en C #). Este texto es el 1244780 en C ++ (no la dirección de memoria, he comprobado). ¿Por qué sería esto? ¿Hay un equivalente a BinaryReader en C ++? Noté que se menciona en MSDN, pero eso es Visual C ++ y intelisense ni siquiera se parece a C ++, a mí.

Código de ejemplo para escribir el archivo (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);
    }

No estoy segura de lo que se podía mostrar el archivo de datos.

Ejemplo de lectura de los datos de nuevo (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);

Esto quiero realizar en C ++. intento inicial (falla en primer entero):

 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: Parece que no importa qué lugar utilizo "seekg" a, recibo el mismo valor exacto

.
¿Fue útil?

Solución

Se da cuenta de que un char es de 16 bits en C # en lugar del 8 por lo general es en C. Esto se debe a un char en C # está diseñado para manejar texto Unicode en lugar de los datos brutos. Por lo tanto, escribir caracteres utilizando el BinaryWriter resultará en Unicode se escriben en lugar de bytes sin formato.

Esto puede tener plomo a calcular la desviación del número entero de forma incorrecta. Le recomiendo que tome un vistazo al archivo en un editor hexadecimal, y si no se puede resolver el problema a publicar el archivo y el código aquí.

EDIT1
En cuanto a su código C ++, no utilice el operador >> para leer de un flujo binario. Utilice leer () con la dirección de la int que desea leer a.

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

Edit2
La lectura de una corriente cerrada también va a resultar en un comportamiento indefinido. No se puede llamar fin.close () y luego todavía esperan ser capaces de leer de él.

Otros consejos

Esto puede o no puede estar relacionado con el problema, pero ...

Cuando se crea el BinaryWriter, que por defecto es chars escritura en UTF-8. Esto significa que algunos de ellos pueden tener más de un byte, arrojando su busca.

Esto se puede evitar mediante el constructor 2 argumento para especificar la codificación. Una instancia de System.Text.ASCIIEncoding sería lo mismo que lo C / C ++ uso por defecto.

Hay muchas cosa va mal en su fragmento de código C ++. No hay que mezclar la lectura binaria con la lectura formato:

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

Si te sirve de ayuda, pasé por la forma en la BinaryWriter escribe datos aquí .

Ha sido un tiempo, pero voy a citar a él y espero que sea precisa:

  • Int16 se escribe como 2 bytes y acolchada.
  • Int32 se escribe como Little Endian y rellenar con ceros
  • Los flotadores son más complicados: Toma el valor del flotador y elimina referencias a ella, recibiendo el contenido de la dirección de memoria que es un hexadecimal
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top