Запись двоичного файла из фортрана и чтение в C

0

Я пытаюсь прочитать двоичный файл, который был создан из программы fortran. Я получаю странные символы в своем выпуске, может быть, и у Fortran, и у C есть разные endianess?

  • 1
    Как вы пишете это на Фортране и как вы читаете это на С? Они оба могут ошибаться или у вас могут быть проблемы с упаковкой.
  • 0
    Я понятия не имею, как это написано на Фортране, вот в чем проблема :(. Все, что у меня есть, это исполняемый файл, который генерирует двоичный файл, который должен быть прочитан через программу C / C ++.
Показать ещё 2 комментария
Теги:
fortran

3 ответа

3

Вы должны использовать

     acces="stream"

и не отформатирован. Он непосредственно моделируется после CI/O, поэтому не должно быть никаких проблем с его пониманием. Это часть Fortran 2003, и все современные компиляторы реализуют ее AFAIK (даже менее продвинутый, такой как Open64 или NEC).

Оба Fortran и C используют один и тот же континент на той же машине, если вы не используете специальные функции компилятора. Это может быть проблематично при передаче файлов между платформами.

Если используется программа Fortran

     access="sequential", form="unformatted"

у вас будут проблемы с разделителями записей.

Файлы, написанные как

     access="direct", form="unformatted"

может быть в порядке.

0

Как другие (@cup) спросили, как вы пишете файл?

IO между Fortran и C может играть хорошо вместе, как сказал Владимир, будьте осторожны с энтузиазмом при написании. Если вы не укажете, что оба они должны писать/читать изначально. Это может быть опция компилятора или опция для open в Fortran.

Например

  • Ifort: -convert big_endian
  • Gfortran: -fconvert=big_endian
  • PGI: -byteswapio

И так далее. Пожалуйста, обратитесь к руководству по компилятору, чтобы узнать его флаг.

Поэтому давайте предположим, что вы пишете файл следующим образом:

program w
    implicit none

    integer, parameter :: max_i = 10
    integer, parameter :: max_j = 10

    integer :: i, j
    integer :: iunit, stat
    real    :: x(max_i,max_j)

    do j=1,max_j
            do i=1,max_i
                    x(i,j) = (i - 1) + (j -1)*max_i
            end do
    end do

    iunit = 7
    open(unit=iunit, file="data", iostat=stat, &
         form="unformatted")
    if (stat .ne. 0) then
            write(*,*) "unable to create data file"
            stop 1
    end if

    write(iunit) x

    close(iunit)

end program w

Если мы не посмотрим на файл,

-rw-r--r-- 1 tbrown users 408 Nov 15 13:16 data

Обратите внимание, что это 408 байт. Как сказал @leeladam, Fortran обычно помещает заголовок размера в начало и конец данных, в этом случае он использует 4 байтовые маркеры записи. Таким образом, два маркера записи и 100 элементов данных в виде 4 байтовых поплавков:

2 * 4 + (10*10*4) = 408

Дает хорошую проверку работоспособности файла данных.

Затем вы можете прочитать его на C с:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>

int
main(int argc, char **argv)
{

    int ifd = 0;
    int i = 0;
    int j = 0;
    int max_i = 10;
    int max_j = 10;
    int fsize = 0;
    int size = 0;
    int ierr = 0;
    float x[max_i][max_j];


    if ((ifd = open("data", O_RDONLY)) < 0) {
            perror("Unable to open data");
            return(EXIT_FAILURE);
        }

    /* read the data size at the start */
    if ((ierr = read(ifd, &fsize, 1*sizeof(int))) < 0) {
            perror("Size read error");
            close(ifd);
            return(EXIT_FAILURE);
    }

    /* compute the size of our data variable */
    size = max_i * max_j * sizeof(float);

    /* read the data */
    if (fsize != size) {
            printf("file and data size mismatch: %d != %d\n", fsize, size);
            close(ifd);
            return(EXIT_FAILURE);
    }

    if ((ierr = read(ifd, &x, size)) < 0) {
            perror("Data read error");
            close(ifd);
            return(EXIT_FAILURE);
    }

    /* read the data size at the end */
    if ((ierr = read(ifd, &fsize, 1*sizeof(int))) < 0) {
            perror("Size read error");
            close(ifd);
            return(EXIT_FAILURE);
    }

    close(ifd);

    for (i = 0; i <= max_i -1; ++i) {
            for (j = 0; j <= max_j -1; ++j) {
                printf("i: %d j: %d x: %f\n", i, j, x[i][j]);
        }
    }

    return(EXIT_SUCCESS);
}

Также обратите внимание, что вы можете проверить файл с помощью od.

Чтобы увидеть первый маркер записи:

$ od -d -N 4 data
0000000       400       0
0000004

Чтобы просмотреть данные:

$ od -j 4 -N 400 -f data
0000004     0.000000e+00    1.000000e+00    2.000000e+00    3.000000e+00
0000024     4.000000e+00    5.000000e+00    6.000000e+00    7.000000e+00
0000044     8.000000e+00    9.000000e+00    1.000000e+01    1.100000e+01

редактировать

Я забыл упомянуть, я предпочитаю всегда записывать бинарный вывод Fortran как большой endian и документировать его, чтобы люди всегда знали. Затем в C используйте процедуры xdr (или ntohl).

0

Fortran помещает заголовок в свои двоичные файлы, поэтому вы можете читать их напрямую с помощью Fortran. Используйте form='unformatted' при записи двоичного файла в Fortran, чтобы избежать этого. Способ читать неотформатированные бинарники показано здесь. Для более глубокого понимания того, как Fortran занимается двоичным вводом-выводом, хорошей отправной точкой является эта угроза.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню