[DB-SIG] Clipper database?
Frederic Vander Elst
fe@phgroup.com
Tue, 07 Aug 2001 16:35:10 +0100
This is a multi-part message in MIME format.
--------------70CC157745C8512996C24A0A
Content-Type: multipart/alternative;
boundary="------------FD800CBABF6FC5931B58A796"
--------------FD800CBABF6FC5931B58A796
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Hi,
enclosed the self-documenting code. Readonly I'm afraid, you'll have to use some ODBC (mxODBC) for writing.
Original comments at top:
> A module for reading dbf files. Tested ONLY on linux.
>
> Author : Michal Spalinski (mspal@fuw.edu.pl)
> Copying policy: unlimited (do what you want with it)
> Warranty : none whatsoever
>
I've hacked it a bit and added some error-checking. If you improve it greatly, please let me/ the list have the update !
-freddie
to reply, try adding a v as the second letter of my uname.
Bill Moore wrote:
> Hi. I'm new to Python and this list. Has anyone written an interface to dBASE or Clipper tables?
>
> I would like to be able to view field names and browse the contents of the data file. Optionally, it would be nice to be able to actually lock a record and modify its contents.
>
> Thanks.
>
> Bill Moore
>
> _______________________________________________
> DB-SIG maillist - DB-SIG@python.org
> http://mail.python.org/mailman/listinfo/db-sig
--------------FD800CBABF6FC5931B58A796
Content-Type: text/html; charset=us-ascii
Content-Transfer-Encoding: 7bit
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<body text="#000000" bgcolor="#FFFFFF" link="#0000CC" vlink="#660066" alink="#660066">
Hi,
<p>enclosed the self-documenting code. Readonly I'm afraid, you'll
have to use some ODBC (mxODBC) for writing.
<p>Original comments at top:
<br>
<blockquote TYPE=CITE>
<pre>A module for reading dbf files. Tested ONLY on linux.
Author : Michal Spalinski (mspal@fuw.edu.pl)
Copying policy: unlimited (do what you want with it)
Warranty : none whatsoever</pre>
</blockquote>
<p><br>I've hacked it a bit and added some error-checking. If you
improve it greatly, please let me/ the list have the update !
<p>-freddie
<br>to reply, try adding a v as the second letter of my uname.
<br>
<p>Bill Moore wrote:
<blockquote TYPE=CITE>Hi. I'm new to Python and this list.
Has anyone written an interface to dBASE or Clipper tables?
<p>I would like to be able to view field names and browse the contents
of the data file. Optionally, it would be nice to be able to actually
lock a record and modify its contents.
<p>Thanks.
<p>Bill Moore
<p>_______________________________________________
<br>DB-SIG maillist - DB-SIG@python.org
<br><a href="http://mail.python.org/mailman/listinfo/db-sig">http://mail.python.org/mailman/listinfo/db-sig</a></blockquote>
</body>
</html>
--------------FD800CBABF6FC5931B58A796--
--------------70CC157745C8512996C24A0A
Content-Type: text/plain; charset=us-ascii;
name="dbf.py"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="dbf.py"
# -*- tab-width: 4 -*-
#
# A module for reading dbf files. Tested ONLY on linux.
#
# Author : Michal Spalinski (mspal@fuw.edu.pl)
# Copying policy: unlimited (do what you want with it)
# Warranty : none whatsoever
#
"""
This is a module for reading dbf files.
The code fragment
import dbf
db = dbf.dbf('mydata.dbf')
creates a dbf object db associated with an existing dbf file 'mydata.dbf'.
Then:
-- db.fields returns a a list of tuples describing the fields
-- db.nrecs returns the number of records
-- db[n] returns a tuple containing the contents of record number n (0 <= n < nrecs).
All field contents are represented as strings ...
-- db.status() prints some data about the dbf file
So, for example, to list the first two fields of all the records in mydata.dbf
one could try:
for r in db:
print r[0], r[1]
Good luck!
"""
from struct import unpack
from string import lower, strip
def int_o_strip(x):
if strip(x) == "":
return 0
else:
try:
return int(strip(x))
except ValueError:
return float(strip(x))
def float_o_strip(x):
if strip(x) == "":
return 0
else:
return float(strip(x))
class dbf:
def __init__(self, fname):
self.f = open(fname,'rb')
head = self.f.read(32)
if (head[0] != '\003') and (head[0] != '\203'):
raise TypeError, 'Not a Dbase III+ file!'
(self.nrecs, self.hlen, self.rlen) = unpack('4xihh20x', head)
fdalen = (self.hlen - 33)/32
# read the field descriptor array
fda = []
for k in range(fdalen):
fda.append(self.f.read(32))
# interpret the field descriptors
self.fields = []
for fd in fda:
bytes = unpack('12c4xBB14x', fd)
field = ''
for i in range(11):
if bytes[i] == '\000':
break
field = field+bytes[i]
type = bytes[11]
length = bytes[12]
dec = bytes[13]
self.fields.append((field,type,length,dec))
self.hook = {}
for i in range(len(self.fields)):
field, type, length, dec = self.fields[i]
pos = i
if type == 'N':
if dec == 0:
func = int_o_strip
else:
func = float_o_strip
else:
func = str
self.hook[lower(field)] = (pos, func, type, length, dec)
# record numbers go from 0 to self.nrecs-1
def _get(self, recno):
offs = self.hlen + recno*self.rlen
self.f.seek(offs,0)
return self.f.read(self.rlen)
def __getitem__(self, recno):
if recno < 0 or recno >= self.nrecs:
raise IndexError, 'No such record.'
else:
raw = self._get(recno)
res, pos = [], 0
for field in self.fields:
end = pos+field[2]
item = raw[pos+1:end+1]
pos=end
res.append(item)
# return tuple(res)
return row(tuple(res),
self.hook)
def status(self):
print ''
print 'Header length :', self.hlen
print 'Record length :', self.rlen
print 'Number of records :', self.nrecs
print ''
print '%-12s %-12s %-12s %-12s' % ('Field','Type','Length','Decimal')
print '%-12s %-12s %-12s %-12s' % ('-----','----','------','-------')
for k in self.fields:
print '%-12s %-12s %-12s %-12s' % k
print ''
class row:
def __init__(self, ptuple=None, hook=None):
if ptuple:
self.data = ptuple
else:
raise TypeError, 'pas de row vide !'
if hook:
self.hook = hook
else:
self.hook = None
def __repr__(self):
return `self.data`
def __len__(self):
return len( self.data)
def __getitem__(self, i):
return self.data[i]
def __setitem__(self, i, item):
raise TypeError, 'immutable row so far'
def __delitem__(self, i, item):
raise TypeError, 'immutable row so far'
def __getattr__(self, aname):
if not self.hook:
raise TypeError, 'need a hook'
if not self.hook.has_key(lower(aname)):
raise ValueError, ('"%s": no such field !' % aname)
pos, func, type, len, dec = self.hook[lower(aname)]
return func(self.data[pos])
--------------70CC157745C8512996C24A0A--