C++ : fichier Fortran binaire

De Wiki de Calcul Québec
Aller à : Navigation, rechercher
Autres langues :anglais 100% • ‎français 100%

Lire un fichier Fortran 'unformatted' en C++

Le langage Fortran a une façon bien particulière d'écrire des fichiers binaires. En effet, les fichiers créés avec l'attribut form='unformatted' ont une structure interne qui les distingue des suites brutes d'octets que l'on peut produire en C/C++. Sur les compilateurs Fortran installés à Calcul Québec, chaque opération d'écriture write produit un enregistrement, lequel est délimité par deux champs identiques de quatre octets (si le programme Fortran a été compilé avec le compilateur PGI, ces champs sont de huit octets). Ces champs indiquent la longueur totale des données de l'enregistrement. Ce format, bien que spécifique au Fortran, ne compromet pas la portabilité des données. L'exemple qui suit montre comment on peut lire des données binaires Fortran dans un programme C++.

Voici un extrait de code Fortran qui écrit un fichier binaire :

Fichier : unformatted.f90
parameter (length = 10)
type point
   double precision x, y, z
endtype
type(point) list(length)
...
open(80, file='test_output', form='unformatted')
write(80) length
do i=1, length
   write(80) list(i)%x, list(i)%y, list(i)%z
enddo
close(80)


En C++, on pourrait lire ce fichier binaire comme suit :

Fichier : readftn.cpp
#include <fstream>
#include <vector>
#include <string>
 
using namespace std;
 
struct Point
{
   double x, y, z;
};
 
const int RECORD_DELIMITER_LENGTH = 4;
 
bool ReadPoints(const string& fileName, vector& points)
{
   int nbPoints;
 
   // clear the points
   points.clear();
 
   // open file in binary mode
   ifstream input(fileName.c_str(), ios::binary);
 
   if (input.good())
   {
      // read number of points
      input.seekg(RECORD_DELIMITER_LENGTH, ios::cur);
      input.read((char*) &nbPoints, sizeof(nbPoints));
      input.seekg(RECORD_DELIMITER_LENGTH, ios::cur);
 
      // set vector size
      points.resize(nbPoints);
 
      // read each point
      for (int i = 0; i < nbPoints; ++i)
      {
         input.seekg(RECORD_DELIMITER_LENGTH, ios::cur);
 
         input.read((char*) &points[i].x, sizeof(points[i].x));
         input.read((char*) &points[i].y, sizeof(points[i].y));
         input.read((char*) &points[i].z, sizeof(points[i].z));
 
         input.seekg(RECORD_DELIMITER_LENGTH, ios::cur);
      }
 
      return true;
   }
   else
   {
      return false;
   }
}


Liens utiles :

Using C and C++ with Fortran
Outils personnels
Espaces de noms

Variantes
Actions
Navigation
Ressources de Calcul Québec
Outils
Partager