Question

Je l'ai écrit plusieurs ints, char [] s et par exemple à un fichier de données avec BinaryWriter en C #. La lecture du fichier rapatrie (en C #) avec BinaryReader, je peux recréer parfaitement toutes les pièces du dossier.

Cependant, en essayant de les relire avec C ++ donne des résultats effrayants. J'utilisais fstream pour tenter de relire les données et les données n'ont pas lu correctement. En C ++, je mis en place un fstream avec ios::in|ios::binary|ios::ate et utilisé seekg pour cibler mon emplacement. Je lis ensuite les quatre octets suivants, qui ont été écrites comme l'entier « 16 » (et lit correctement en C #). Cela se lit comme 1.244.780 en C ++ (pas l'adresse de la mémoire, j'ai vérifié). Pourquoi serait-ce? Y at-il un équivalent à BinaryReader en C ++? Je l'ai remarqué mentionné sur msdn, mais c'est Visual C ++ et IntelliSense ne regarde même pas comme c ++, pour moi.

Exemple de code pour écrire le fichier (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);
    }

Je ne sais pas comment je pourrais vous montrer le fichier de données.

Exemple de lecture des données de retour (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);

Je veux jouer dans c ++. tentative initiale (échoue au premier nombre entier):

 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: Il semble que peu importe quel endroit je l'utilise « seekg », je reçois la même valeur exacte

.
Était-ce utile?

La solution

Vous vous rendez compte que char est 16 bits en C # plutôt que le 8, il est généralement en C. En effet, un caractère dans C # est conçu pour gérer le texte Unicode plutôt que des données brutes. Par conséquent, les caractères d'écriture en utilisant l'BinaryWriter se traduira par Unicode en cours d'écriture plutôt que octets bruts.

Cela peut vous faire conduire à calculer le décalage de manière incorrecte de l'entier. Je vous recommande de jeter un coup d'oeil au fichier dans un éditeur hexadécimal, et si vous ne pouvez pas travailler sur la question posterai le fichier et le code ici.

EDIT1 En ce qui concerne votre code C ++, ne pas utiliser le >> opérateur de lire à partir d'un flux binaire. Utilisez read () avec l'adresse de l'int que vous voulez lire.

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

EDIT2 La lecture d'un flux fermé va également entraîner un comportement non défini. Vous ne pouvez pas appeler fin.close (), puis attendre encore pouvoir lire.

Autres conseils

Cela peut ou non être liés au problème, mais ...

Lorsque vous créez le BinaryWriter, sa valeur par défaut chars d'écriture en UTF-8. Cela signifie que certains d'entre eux peuvent être plus d'un octet, lancer votre cherche.

Vous pouvez éviter cela en utilisant le constructeur de l'argument 2 pour spécifier l'encodage. Une instance de System.Text.ASCIIEncoding serait la même chose que C / C ++ utilisation par défaut.

Il y a beaucoup de chose qui ne va pas dans votre extrait C ++. Vous ne devriez pas mélanger la lecture binaire avec la lecture au format:

  // 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 c'est une aide, je suis passé par la façon dont le BinaryWriter écrit des données ici .

Il a été un certain temps, mais je vais le citer et nous espérons qu'il est précis:

  • Int16 est écrit 2 octets et matelassée.
  • Int32 est écrit comme Little Endian et zéro rembourré
  • Flotteurs sont plus compliquées: il prend la valeur de flotteur et déréférence il, obtenir le contenu de l'adresse de mémoire qui est une hexadécimal
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top