* Initial version of Fortran binary file reader.
Later a writing facility can be added as well. * Note that this module is intended only for reading/writing Fortran-generated files. It is not recommended for any other purpose because of its terrible feature: no metadata, no description whatsoever.
This commit is contained in:
11
iofmt/__init__.py
Normal file
11
iofmt/__init__.py
Normal file
@@ -0,0 +1,11 @@
|
||||
# $Id: __init__.py,v 1.1 2010-02-08 21:49:54 wirawan Exp $
|
||||
#
|
||||
# wpylib.iofmt module
|
||||
# Created: 20100208
|
||||
# Wirawan Purwanto
|
||||
#
|
||||
# I/O format-related stuff.
|
||||
|
||||
"""I/O format-related stuff."""
|
||||
|
||||
pass
|
||||
89
iofmt/fortbin.py
Normal file
89
iofmt/fortbin.py
Normal file
@@ -0,0 +1,89 @@
|
||||
# $Id: fortbin.py,v 1.1 2010-02-08 21:49:54 wirawan Exp $
|
||||
#
|
||||
# wpylib.iofmt.fortbin module
|
||||
# Created: 20100208
|
||||
# Wirawan Purwanto
|
||||
#
|
||||
"""
|
||||
Fortran binary format.
|
||||
|
||||
"""
|
||||
|
||||
import numpy
|
||||
import sys
|
||||
|
||||
from wpylib.sugar import ifelse
|
||||
|
||||
class fortran_bin_file(object):
|
||||
"""A tool for reading Fortran binary files."""
|
||||
def __init__(self, filename=None):
|
||||
self.record_marker_type = numpy.uint32
|
||||
self.debug = 100
|
||||
if filename:
|
||||
self.open(filename)
|
||||
|
||||
def open(self, filename):
|
||||
self.F = open(filename, "rb")
|
||||
|
||||
def read(self, *fields, **opts):
|
||||
"""Reads a Fortran record.
|
||||
The description of the fields are given as
|
||||
(name, dtype, length) tuples."""
|
||||
from numpy import fromfile as rd
|
||||
if self.debug:
|
||||
dbg = lambda msg : sys.stderr.write(msg)
|
||||
else:
|
||||
dbg = lambda msg : None
|
||||
def fld_count(f):
|
||||
if len(f) > 2:
|
||||
return f[2]
|
||||
else:
|
||||
return 1
|
||||
|
||||
reclen = numpy.fromfile(self.F, self.record_marker_type, 1)
|
||||
dbg("Record length = %d\n" % reclen)
|
||||
expected_len = sum([ fld_count(f) * numpy.dtype(f[1]).itemsize
|
||||
for f in fields ])
|
||||
dbg("Expected length = %d\n" % expected_len)
|
||||
if expected_len > reclen:
|
||||
raise IOError, \
|
||||
"Attempting to read %d bytes from a record of length %d bytes" \
|
||||
% (expected_len, reclen)
|
||||
|
||||
if "out" in opts:
|
||||
rslt = opts["out"]
|
||||
else:
|
||||
rslt = {}
|
||||
|
||||
if (issubclass(rslt.__class__, dict) and issubclass(dict, rslt.__class__)) \
|
||||
or "__setitem__" in dir(rslt):
|
||||
def setval(d, k, v):
|
||||
d[k] = v
|
||||
else:
|
||||
# Assume we can use setattr method:
|
||||
setval = setattr
|
||||
|
||||
for f in fields:
|
||||
if len(f) > 2:
|
||||
(name,Dtyp,Len) = f
|
||||
dtyp = numpy.dtype(Dtyp)
|
||||
setval(rslt, name, numpy.fromfile(self.F, dtyp, Len))
|
||||
else:
|
||||
# Special handling for scalars
|
||||
name = f[0]
|
||||
dtyp = numpy.dtype(f[1])
|
||||
setval(rslt, name, numpy.fromfile(self.F, dtyp, 1)[0])
|
||||
|
||||
if expected_len < reclen:
|
||||
self.F.seek(reclen - expected_len, 1)
|
||||
|
||||
reclen2 = numpy.fromfile(self.F, self.record_marker_type, 1)
|
||||
dbg("Record length tail = %d\n" % reclen2)
|
||||
|
||||
if reclen2 != reclen:
|
||||
raise IOError, \
|
||||
"Inconsistency in record: end-marker length = %d; was expecting %d" \
|
||||
% (reclen2, reclen)
|
||||
|
||||
return rslt
|
||||
|
||||
Reference in New Issue
Block a user