Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
读取由Python代码创建的Fortran二进制文件_Python_Fortran_Binaryfiles - Fatal编程技术网

读取由Python代码创建的Fortran二进制文件

读取由Python代码创建的Fortran二进制文件,python,fortran,binaryfiles,Python,Fortran,Binaryfiles,我有一个使用Python代码创建的二进制文件。这段代码主要编写一系列任务的脚本,以预处理一组数据文件。我现在想用Fortran阅读这个二进制文件。二进制文件的内容是简单格式的点坐标,例如:点数、x0、y0、z0、x1、y1、z1等 这些二进制文件是使用numpy中的“tofile”函数创建的。到目前为止,我用Fortran编写了以下代码: integer:: intValue double precision:: dblValue integer:: counter integer:: chec

我有一个使用Python代码创建的二进制文件。这段代码主要编写一系列任务的脚本,以预处理一组数据文件。我现在想用Fortran阅读这个二进制文件。二进制文件的内容是简单格式的点坐标,例如:点数、x0、y0、z0、x1、y1、z1等

这些二进制文件是使用numpy中的“tofile”函数创建的。到目前为止,我用Fortran编写了以下代码:

integer:: intValue
double precision:: dblValue
integer:: counter
integer:: check
open(unit=10, file='file.bin', form='unformatted', status='old', access='stream')

counter = 1

do 

  if ( counter == 1 ) then
    read(unit=10, iostat=check) intValue
    if ( check < 0 ) then
      print*,"End Of File"
      stop
    else if ( check > 0 ) then
      print*, "Error Detected"
      stop
    else if ( check == 0 ) then
      counter = counter + 1
      print*, intValue
    end if
  else if ( counter > 1 ) then
    read(unit=10, iostat=check) dblValue
    if ( check < 0 ) then
      print*,"End Of File"
      stop
    else if ( check > 0 ) then
      print*, "Error Detected"
      stop
    else if ( check == 0 ) then
      counter = counter + 1
      print*,dblValue
    end if
  end if

end do

close(unit=10)
integer::intValue
双精度::dblValue
整数::计数器
整数::检查
打开(单位=10,文件='file.bin',格式='unformatted',状态='old',访问='stream')
计数器=1
做
如果(计数器==1),则
读取(单位=10,iostat=check)intValue
如果(检查<0),则
打印*,“文件结束”
停止
否则,如果(选中>0),则
打印*,“检测到错误”
停止
否则,如果(检查==0),则
计数器=计数器+1
打印*,intValue
如果结束
否则,如果(计数器>1),则
读取(单位=10,iostat=check)数据左值
如果(检查<0),则
打印*,“文件结束”
停止
否则,如果(选中>0),则
打印*,“检测到错误”
停止
否则,如果(检查==0),则
计数器=计数器+1
打印*,数据左值
如果结束
如果结束
结束
关闭(单位=10)
不幸的是,这不起作用,我得到了垃圾编号(例如6.4731191026611484E+212、2.2844499004808491E-279等)。有没有人能给点建议如何正确地做到这一点? 另外,在Python和Fortran之间交替编写和读取二进制文件的好方法是什么?因为这似乎将是我的应用程序的要求之一


感谢

这里有一个简单的示例,说明如何以二进制方式将使用numpy生成的数据转换为Fortran

我计算了
[0,2π)
上的
sin
的360个值

#!/usr/bin/env python3
import numpy as np

with open('sin.dat', 'wb') as outfile:
    np.sin(np.arange(0., 2*np.pi, np.pi/180.,
                     dtype=np.float32)).tofile(outfile)
将其导出为二进制文件
'sin.dat'
,其大小为
1440字节(360*sizeof(float32))
,使用此Fortran95(gfortran-O3-Wall-pedantic)程序读取该文件,该程序输出[0,2π]中x的
1.-(val**2+cos(x)**2)

因此,如果
val==sin(x)
,则float32类型的数值结果必须以良好的近似值消失

事实上:

输出:

360 x 0.0000

多亏了这个伟大的社区,从我得到的所有建议,再加上一点修改,我想我找到了这个问题的稳定解决方案,我想与大家分享所有这些答案。我将在这里提供一个简单的例子,我想将一个可变大小的数组从Python写入一个二进制文件,并使用Fortran读取它。我假设行数
numRows
和列数
numCols
也与完整数组
datatArray
一起写入。以下Python脚本
writeBin.py
写入该文件:

import numpy as np
# Read in the numRows and numCols value 
# Read in the array values
numRowArr = np.array([numRows], dtype=np.float32)
numColArr = np.array([numCols], dtype=np.float32)
fileObj   = open('pybin.bin', 'wb')
numRowArr.tofile(fileObj)
numColArr.tofile(fileObj)
for i in range(numRows):
    lineArr = dataArray[i,:]
    lineArr.tofile(fileObj)
fileObj.close()
在此之后,从文件中读取阵列的fortran代码可以按如下方式编程:

program readBin

    use iso_fortran_env

    implicit none

    integer:: nR, nC, i

    real(kind=real32):: numRowVal, numColVal
    real(kind=real32), dimension(:), allocatable:: rowData
    real(kind=real32), dimension(:,:), allocatable:: fullData

    open(unit=10,file='pybin.bin',form='unformatted',status='old',access='stream')

    read(unit=10) numRowVal
    nR = int(numRowVal)

    read(unit=10) numColVal
    nC = int(numColVal)

    allocate(rowData(nC))
    allocate(fullData(nR,nC))

    do i = 1, nR

        read(unit=10) rowData
        fullData(i,:) = rowData(:)

    end do

    close(unit=10)

end program readBin
我从这个线程的讨论中收集到的主要观点是,尽可能地匹配读写操作,以及要读取的数据类型的精确规范、它们的写入方式等。正如您可能注意到的,这是一个虚构的示例,因此可能存在一些不完美的地方。但是,我使用了这个n如何编写一个有限元程序,网格数据就是我使用这个二进制读/写的地方,它工作得非常好

附言:如果你发现一些打字错误,请告诉我,我会马上把它编辑掉


非常感谢。

我添加了一个很好的详细答案,告诉您使用
access=stream
:)我刚刚意识到您已经在这样做了,所以我现在删除了我的答案。所以,问题:您确定python
int
和fortran
integer
的字节大小是相同的吗?您应该检查两者。如果有一个字节的差异,数据的不对准将导致
读取后产生垃圾。你使用的是什么fortran编译器?你如何声明你的
整数
s?你的python
int
s的具体类型是什么?如果你真的很绝望,你可以尝试生成使用fortran和python的同一个伪二进制文件,然后查看这两个文件的十六进制转储,看看有什么问题。此外,我前面关于
整数
大小的问题显然也适用于所涉及的
双精度
。即使类型已签出,如果在上使用这两个代码,仍然可能存在endianness问题两种完全不同的机器。关于互换性问题:我宁愿将元数据(如点数)放入一个单独的ASCII头文件中,该头文件易于读取,并且只将相同类型的数据放入一个二进制文件中,这也允许相当容易地转换endiannessse HDF5读取/写入数据。在python和Fortran以及许多其他软件上受支持。种类号通常不可移植,但
Kind=32
对于我所知道的所有编译器都无效。请使用
Kind=real32
Kind=real64
(常量来自模块
iso_Fortran_env
)。它们应等同于NumPy float32和float64。
program readBin

    use iso_fortran_env

    implicit none

    integer:: nR, nC, i

    real(kind=real32):: numRowVal, numColVal
    real(kind=real32), dimension(:), allocatable:: rowData
    real(kind=real32), dimension(:,:), allocatable:: fullData

    open(unit=10,file='pybin.bin',form='unformatted',status='old',access='stream')

    read(unit=10) numRowVal
    nR = int(numRowVal)

    read(unit=10) numColVal
    nC = int(numColVal)

    allocate(rowData(nC))
    allocate(fullData(nR,nC))

    do i = 1, nR

        read(unit=10) rowData
        fullData(i,:) = rowData(:)

    end do

    close(unit=10)

end program readBin