用python,浮点数和整数读取fortran二进制数据

时间:2017-01-24 17:34:15

标签: python binary fortran

A有一个可以使用fortran读取的文件,并产生以下输出:

  0     2044150      229424           0           0           0   
0.0000000000000000        0.0000000000000000       
2.97821895219385624E-003   0.0000000000000000        0.0000000000000000        
0.0000000000000000       7.81250000000000000E-003   127.00000000000000                0           0           0    91948296    10067568     7115688           0  
0           0          48   67.769999999999996       
0.30700001120567322       0.69300001859664917       0.67769998311996460 

基本上有一些int * 4值和一些float * 8值(在标题中)。 我希望能够使用python读取此数据文件。我使用了以下代码:

f = open(fname,'rb')
data = np.fromfile(file=f,dtype=np.int32)
print data

我得到了结果:

[       256          0    2044150     229424          0          0
      0          0          0          0          0  536870912
 1063806407          0          0          0          0          0
      0          0   ]

有些数字还可以,我相信256指的是记录大小。 但是,当我尝试读取浮点数(通过将np.int32更改为np.float64)时,我得到了

[  1.26480805e-321   4.86836763e-309   0.00000000e+000  0.00000000e+000
   0.00000000e+000   1.49166815e-154   5.25590200e-315       0.00000000e+000
   0.00000000e+000   0.00000000e+000   5.26354425e-315   5.33599245e-315
   0.00000000e+000   9.12063001e-306   3.51561699e-317   0.00000000e+000
  -1.02951130e-086   2.68156223e+154   2.68156222e+154  -2.68156222e+154]

对于int32s而言,这显然是错误的,但对于我试图阅读的浮动64也是如此。

我想也许这与大/小人有关,但是没有找到解决办法。我也确信我正在尝试读取正确的数据类型(float64)并尝试了许多其他数据类型,它们会产生类似(或更糟)的结果。

我知道标题的格式是 INT * 4(6),实* 8(6),实* 8,真实* 8,INT * 4,INT * 4,INT * 4(6),INT * 4,INT * 4,实* 8,实* 8,真实* 8,真实* 8字符(96)

2 个答案:

答案 0 :(得分:0)

您的数据文件缺乏结构。您应该首先知道文件中的内容然后选择阅读策略,否则您将读取数字但不知道它们的含义。正如Jean-FrançoisFabre所写,loadtxt无法处理您的情况,您将不得不自己编写文件的逻辑。您可以使用StringIO(例如https://docs.python.org/2/library/stringio.html#module-StringIO

将数字部分的解析分段委托给loadtxt

答案 1 :(得分:0)

最后我使用了上面建议的struct.unpack方法。 我的代码看起来像:

def read_block(start,data_format,data):

    p = start # Count block size

    # Read record size
    rf = 'i'
    rs = struct.calcsize(rf)
    record = struct.unpack(rf,data[p:p+rs])
    p += rs

    bs = record[0]
    body = list(struct.unpack(data_format,data[p:p+bs]))
    p += bs

    p += rs # Record size again

    return body,p-start


''' Read specific file architecture '''
''' Easily modified '''
def read_gadget(gdt_file):

    p = 0

    with open(gdt_file,'rb') as binary_file:
        data = binary_file.read()


    header_fmt = '=6i8d10i4d96s'    
    header,header_size = read_block(p,header_fmt,data)
    npart = header[:6]
    mpart = header[6:12]
    npart_tot = sum(npart)
    p += header_size


    pos_fmt = str(3*npart_tot)+'f'
    pos_list,pos_size = read_block(p,pos_fmt,data)
    pos_arr = np.zeros((npart_tot,3))
    for i in range(3):
        pos_arr[:,i] = np.array(pos_list)[i*npart_tot:(i+1)*npart_tot]
    p += pos_size


    vel_fmt = str(3*npart_tot)+'f'
    vel_list,vel_size = read_block(p,vel_fmt,data)
    vel_arr = np.zeros((npart_tot,3))
    for i in range(3):
        vel_arr[:,i] = np.array(vel_list)[i*npart_tot:(i+1)*npart_tot]
    p += vel_size

    id_fmt = str(npart_tot)+'l'
    id_list,id_size = read_block(p,id_fmt,data)
    p += id_size
    id_arr = np.array(id_list)


    mass_arr = np.array([])
    for i in range(6):
        if npart[i]==0:
            pass
        elif npart[i]!=0 and mpart[i]==0:
            mass_fmt = str(npart[i])+'f'
            mass_list,mass_size = read_block(p,mass_fmt,data)
            p += mass_size
            mass_arr = np.append(mass_arr,np.array(mass_list))
        elif npart[i]!=0 and mpart[i]!=0:
            mass_list = npart[i]*[mpart[i]]
            mass_arr = np.append(mass_arr,np.array(mass_list))


    return header,pos_arr,vel_arr,id_arr,mass_arr