Domanda

Ho scritto diversi int, caratteri[] e simili in un file di dati con BinaryWriter in C#.Rileggendo il file (in C#) con BinaryReader, posso ricreare perfettamente tutte le parti del file.

Tuttavia, tentare di rileggerli con C++ produce risultati spaventosi.Stavo usando fstream per tentare di rileggere i dati e i dati non venivano letti correttamente.In C++, ho configurato un fstream con ios::in|ios::binary|ios::ate e ho usato searchg per individuare la mia posizione.Quindi leggo i quattro byte successivi, che sono stati scritti come numero intero "16" (e letti correttamente in C#).Questo si legge come 1244780 in C++ (non l'indirizzo di memoria, ho controllato).Perché dovrebbe essere questo?Esiste un equivalente a BinaryReader in C++?Ho notato che è menzionato su msdn, ma è Visual C++ e intellisense non mi sembra nemmeno C++.

Codice di esempio per scrivere il file (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);
    }

Non sono sicuro di come potrei mostrarti il ​​file di dati.

Esempio di lettura dei dati (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);

Questo voglio eseguirlo in C++.Tentativo iniziale (fallisce al primo numero intero):

 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;

Modificare:Sembra che non importa in quale posizione utilizzo "seekg", ricevo esattamente lo stesso valore.

È stato utile?

Soluzione

Ti rendi conto che un char è di 16 bit in C #, piuttosto che l'8 di solito è in C. Questo perché un char in C # è stato progettato per gestire il testo Unicode invece di dati grezzi. Pertanto, la scrittura di caratteri che utilizzano il BinaryWriter si tradurrà in Unicode vengono scritti piuttosto che byte grezzi.

Questo può avere vantaggio di calcolare l'offset del numero intero in modo non corretto. Vi consiglio di dare un'occhiata al file in un editor esadecimale, e se non si può lavorare fuori la questione inserisco il file e il codice qui.

EDIT1
Per quanto riguarda il codice C ++, non utilizzare l'operatore >> di leggere da un flusso binario. Utilizzare read () con l'indirizzo del int che si desidera leggere a.

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

EDIT2
La lettura da un flusso chiuso è anche andare a tradursi in un comportamento indefinito. Non è possibile chiamare fin.close () e poi ancora si aspettano di essere in grado di leggere da esso.

Altri suggerimenti

Questo può o non può essere correlato al problema, ma ...

Quando si crea il BinaryWriter, il valore predefinito è di scrittura chars in UTF-8. Ciò significa che alcuni di loro possono essere più lungo di un byte, gettando via il tuo cerca.

È possibile evitare questo utilizzando il costruttore 2 argomento per specificare la codifica. Un esempio di System.Text.ASCIIEncoding sarebbe la stessa cosa C / C ++ uso per impostazione predefinita.

Ci sono molte cose che non va nel vostro frammento di C ++. Si consiglia di non mescolare la lettura binaria con la lettura in 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;

Se può esserti d'aiuto, ho spiegato come BinaryWriter scrive i dati Qui.

È passato un po' di tempo ma lo cito sperando che sia accurato:

  • Int16 è scritto come 2 byte e riempito.
  • Int32 è scritto come Little Endian e riempito con zero
  • I float sono più complicati:prende il valore float e lo dereferenzia, ottenendo il contenuto dell'indirizzo di memoria che è esadecimale
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top