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.master
parent
f246d382bf
commit
21e85704aa
2 changed files with 100 additions and 0 deletions
@ -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 |
@ -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 |
||||||
|
|
Loading…
Reference in new issue