使用Java实现对dbf文件的简单读写
我将dbf文件的读写基本分成四个类,Writer,Reader, Field, Exception,内容如下,如果在使用该程序包时有什么问题或者好的建议,请发mail到 iiihero#hotmail.com
下载的过程详见:http://computer.mblogger.cn/ehero/posts/31204.aspx
如果您能多Re几下本文,我将更为高兴。
/**
* <p>Title: java访问DBF文件的接口</p>
* <p>Description: 这个类用于表示DBF文件中的写操作</p>
* <p>Copyright: Copyright (c) 2004</p>
* <p>Company: ict</p>
* @author : He Xiong
* @version 1.0
*/
package com.hexiong.jdbf;
import java.io.*;
import java.util.Calendar;
// Referenced classes of package com.hexiong.jdbf:
// JDBFException, JDBField
public class DBFWriter
{
public DBFWriter(String s, JDBField ajdbfield[])
throws JDBFException
{
stream = null;
recCount = 0;
fields = null;
fileName = null;
dbfEncoding = null;
fileName = s;
try
{
init(new FileOutputStream(s), ajdbfield);
}
catch(FileNotFoundException filenotfoundexception)
{
throw new JDBFException(filenotfoundexception);
}
}
public DBFWriter(OutputStream outputstream, JDBField ajdbfield[])
throws JDBFException
{
stream = null;
recCount = 0;
fields = null;
fileName = null;
dbfEncoding = null;
init(outputstream, ajdbfield);
}
public DBFWriter(String s, JDBField ajdbfield[], String s1)
throws JDBFException
{
stream = null;
recCount = 0;
fields = null;
fileName = null;
dbfEncoding = null;
fileName = s;
try
{
dbfEncoding = s1;
init(new FileOutputStream(s), ajdbfield);
}
catch(FileNotFoundException filenotfoundexception)
{
throw new JDBFException(filenotfoundexception);
}
}
private void init(OutputStream outputstream, JDBField ajdbfield[])
throws JDBFException
{
fields = ajdbfield;
try
{
stream = new BufferedOutputStream(outputstream);
writeHeader();
for(int i = 0; i < ajdbfield.length; i++)
writeFieldHeader(ajdbfield[i]);
stream.write(13);
stream.flush();
}
catch(Exception exception)
{
throw new JDBFException(exception);
}
}
private void writeHeader()
throws IOException
{
byte abyte0[] = new byte[16];
abyte0[0] = 3;
Calendar calendar = Calendar.getInstance();
abyte0[1] = (byte)(calendar.get(1) - 1900);
abyte0[2] = (byte)calendar.get(2);
abyte0[3] = (byte)calendar.get(5);
abyte0[4] = 0;
abyte0[5] = 0;
abyte0[6] = 0;
abyte0[7] = 0;
int i = (fields.length + 1) * 32 + 1;
abyte0[8] = (byte)(i % 256);
abyte0[9] = (byte)(i / 256);
int j = 1;
for(int k = 0; k < fields.length; k++)
j += fields[k].getLength();
abyte0[10] = (byte)(j % 256);
abyte0[11] = (byte)(j / 256);
abyte0[12] = 0;
abyte0[13] = 0;
abyte0[14] = 0;
abyte0[15] = 0;
stream.write(abyte0, 0, abyte0.length);
for(int l = 0; l < 16; l++)
abyte0[l] = 0;
stream.write(abyte0, 0, abyte0.length);
}
private void writeFieldHeader(JDBField jdbfield)
throws IOException
{
byte abyte0[] = new byte[16];
String s = jdbfield.getName();
int i = s.length();
if(i > 10)
i = 10;
for(int j = 0; j < i; j++)
abyte0[j] = (byte)s.charAt(j);
for(int k = i; k <= 10; k++)
abyte0[k] = 0;
abyte0[11] = (byte)jdbfield.getType();
abyte0[12] = 0;
abyte0[13] = 0;
abyte0[14] = 0;
abyte0[15] = 0;
stream.write(abyte0, 0, abyte0.length);
for(int l = 0; l < 16; l++)
abyte0[l] = 0;
abyte0[0] = (byte)jdbfield.getLength();
abyte0[1] = (byte)jdbfield.getDecimalCount();
stream.write(abyte0, 0, abyte0.length);
}
public void addRecord(Object aobj[])
throws JDBFException
{
if(aobj.length != fields.length)
throw new JDBFException("Error adding record: Wrong number of values. Expected " + fields.length + ", got " + aobj.length + ".");
int i = 0;
for(int j = 0; j < fields.length; j++)
i += fields[j].getLength();
byte abyte0[] = new byte[i];
int k = 0;
for(int l = 0; l < fields.length; l++)
{
String s = fields[l].format(aobj[l]);
byte abyte1[];
try
{
if(dbfEncoding != null)
abyte1 = s.getBytes(dbfEncoding);
else
abyte1 = s.getBytes();
}
catch(UnsupportedEncodingException unsupportedencodingexception)
{
throw new JDBFException(unsupportedencodingexception);
}
for(int i1 = 0; i1 < fields[l].getLength(); i1++)
abyte0[k + i1] = abyte1[i1];
k += fields[l].getLength();
}
try
{
stream.write(32);
stream.write(abyte0, 0, abyte0.length);
stream.flush();
}
catch(IOException ioexception)
{
throw new JDBFException(ioexception);
}
recCount++;
}
public void close()
throws JDBFException
{
try
{
stream.write(26);
stream.close();
RandomAccessFile randomaccessfile = new RandomAccessFile(fileName, "rw");
randomaccessfile.seek(4L);
byte abyte0[] = new byte[4];
abyte0[0] = (byte)(recCount % 256);
abyte0[1] = (byte)((recCount / 256) % 256);
abyte0[2] = (byte)((recCount / 0x10000) % 256);
abyte0[3] = (byte)((recCount / 0x1000000) % 256);
randomaccessfile.write(abyte0, 0, abyte0.length);
randomaccessfile.close();
}
catch(IOException ioexception)
{
throw new JDBFException(ioexception);
}
}
private BufferedOutputStream stream;
private int recCount;
private JDBField fields[];
private String fileName;
private String dbfEncoding;
}
/**
* <p>Title: java访问DBF文件的接口</p>
* <p>Description: 这个类用于表示DBF文件中的字段</p>
* <p>Copyright: Copyright (c) 2004</p>
* <p>Company: ict</p>
* @author : He Xiong
* @version 1.0
*/
package com.hexiong.jdbf;
import java.text.*;
import java.util.Date;
// Referenced classes of package com.hexiong.jdbf:
// JDBFException
public class JDBField
{
public JDBField(String s, char c, int i, int j)
throws JDBFException
{
if(s.length() > 10)
throw new JDBFException("The field name is more than 10 characters long: " + s);
if(c != 'C' && c != 'N' && c != 'L' && c != 'D' && c != 'F')
throw new JDBFException("The field type is not a valid. Got: " + c);
if(i < 1)
throw new JDBFException("The field length should be a positive integer. Got: " + i);
if(c == 'C' && i >= 254)
throw new JDBFException("The field length should be less than 254 characters for character fields. Got: " + i);
if(c == 'N' && i >= 21)
throw new JDBFException("The field length should be less than 21 digits for numeric fields. Got: " + i);
if(c == 'L' && i != 1)
throw new JDBFException("The field length should be 1 characater for logical fields. Got: " + i);
if(c == 'D' && i != 8)
throw new JDBFException("The field length should be 8 characaters for date fields. Got: " + i);
if(c == 'F' && i >= 21)
throw new JDBFException("The field length should be less than 21 digits for floating point fields. Got: " + i);
if(j < 0)
throw new JDBFException("The field decimal count should not be a negative integer. Got: " + j);
if((c == 'C' || c == 'L' || c == 'D') && j != 0)
throw new JDBFException("The field decimal count should be 0 for character, logical, and date fields. Got: " + j);
if(j > i - 1)
{
throw new JDBFException("The field decimal count should be less than the length - 1. Got: " + j);
} else
{
name = s;
type = c;
length = i;
decimalCount = j;
return;
}
}
public String getName()
{
return name;
}
public char getType()
{
return type;
}
public int getLength()
{
return length;
}
public int getDecimalCount()
{
return decimalCount;
}
public String format(Object obj)
throws JDBFException
{
if(type == 'N' || type == 'F')
{
if(obj == null)
obj = new Double(0.0D);
if(obj instanceof Number)
{
Number number = (Number)obj;
StringBuffer stringbuffer = new StringBuffer(getLength());
for(int i = 0; i < getLength(); i++)
stringbuffer.append("#");
if(getDecimalCount() > 0)
stringbuffer.setCharAt(getLength() - getDecimalCount() - 1, '.');
DecimalFormat decimalformat = new DecimalFormat(stringbuffer.toString());
String s1 = decimalformat.format(number);
int k = getLength() - s1.length();
if(k < 0)
throw new JDBFException("Value " + number + " cannot fit in pattern: '" + stringbuffer + "'.");
StringBuffer stringbuffer2 = new StringBuffer(k);
for(int l = 0; l < k; l++)
stringbuffer2.append(" ");
return stringbuffer2 + s1;
} else
{
throw new JDBFException("Expected a Number, got " + obj.getClass() + ".");
}
}
if(type == 'C')
{
if(obj == null)
obj = "";
if(obj instanceof String)
{
String s = (String)obj;
if(s.length() > getLength())
throw new JDBFException("'" + obj + "' is longer than " + getLength() + " characters.");
StringBuffer stringbuffer1 = new StringBuffer(getLength() - s.length());
for(int j = 0; j < getLength() - s.length(); j++)
stringbuffer1.append(' ');
return s + stringbuffer1;
} else
{
throw new JDBFException("Expected a String, got " + obj.getClass() + ".");
}
}
if(type == 'L')
{
if(obj == null)
obj = new Boolean(false);
if(obj instanceof Boolean)
{
Boolean boolean1 = (Boolean)obj;
return boolean1.booleanValue() ? "Y" : "N";
} else
{
throw new JDBFException("Expected a Boolean, got " + obj.getClass() + ".");
}
}
if(type == 'D')
{
if(obj == null)
obj = new Date();
if(obj instanceof Date)
{
Date date = (Date)obj;
SimpleDateFormat simpledateformat = new SimpleDateFormat("yyyyMMdd");
return simpledateformat.format(date);
} else
{
throw new JDBFException("Expected a Date, got " + obj.getClass() + ".");
}
} else
{
throw new JDBFException("Unrecognized JDBFField type: " + type);
}
}
public Object parse(String s)
throws JDBFException
{
s = s.trim();
if(type == 'N' || type == 'F')
{
if(s.equals(""))
s = "0";
try
{
if(getDecimalCount() == 0)
return new Long(s);
else
return new Double(s);
}
catch(NumberFormatException numberformatexception)
{
throw new JDBFException(numberformatexception);
}
}
if(type == 'C')
return s;
if(type == 'L')
{
if(s.equals("Y") || s.equals("y") || s.equals("T") || s.equals("t"))
return new Boolean(true);
if(s.equals("N") || s.equals("n") || s.equals("F") || s.equals("f"))
return new Boolean(false);
else
throw new JDBFException("Unrecognized value for logical field: " + s);
}
if(type == 'D')
{
SimpleDateFormat simpledateformat = new SimpleDateFormat("yyyyMMdd");
try
{
if("".equals(s))
return null;
else
return simpledateformat.parse(s);
}
catch(ParseException parseexception)
{
throw new JDBFException(parseexception);
}
} else
{
throw new JDBFException("Unrecognized JDBFField type: " + type);
}
}
public String toString()
{
return name;
}
private String name;
private char type;
private int length;
private int decimalCount;
}
/**
* <p>Title: java访问DBF文件的接口</p>
* <p>Description: 这个类用于表示DBF文件中的读写异常</p>
* <p>Copyright: Copyright (c) 2004</p>
* <p>Company: ict</p>
* @author : He Xiong
* @version 1.0
*/
package com.hexiong.jdbf;
import java.io.PrintStream;
import java.io.PrintWriter;
public class JDBFException extends Exception
{
public JDBFException(String s)
{
this(s, null);
}
public JDBFException(Throwable throwable)
{
this(throwable.getMessage(), throwable);
}
public JDBFException(String s, Throwable throwable)
{
super(s);
detail = throwable;
}
public String getMessage()
{
if(detail == null)
return super.getMessage();
else
return super.getMessage();
}
public void printStackTrace(PrintStream printstream)
{
if(detail == null)
{
super.printStackTrace(printstream);
return;
}
PrintStream printstream1 = printstream;
printstream1.println(this);
detail.printStackTrace(printstream);
return;
}
public void printStackTrace()
{
printStackTrace(System.err);
}
public void printStackTrace(PrintWriter printwriter)
{
if(detail == null)
{
super.printStackTrace(printwriter);
return;
}
PrintWriter printwriter1 = printwriter;
printwriter1.println(this);
detail.printStackTrace(printwriter);
return;
}
private Throwable detail;
}
/**
* <p>Title: java访问DBF文件的接口</p>
* <p>Description: 这个类用于表示DBF文件中的读操作</p>
* <p>Copyright: Copyright (c) 2004</p>
* <p>Company: ict</p>
* @author : He Xiong
* @version 1.0
*/
package com.hexiong.jdbf;
import java.io.*;
// Referenced classes of package com.hexiong.jdbf:
// JDBFException, JDBField
public class DBFReader
{
public DBFReader(String s)
throws JDBFException
{
stream = null;
fields = null;
nextRecord = null;
try
{
init(new FileInputStream(s));
}
catch(FileNotFoundException filenotfoundexception)
{
throw new JDBFException(filenotfoundexception);
}
}
public DBFReader(InputStream inputstream)
throws JDBFException
{
stream = null;
fields = null;
nextRecord = null;
init(inputstream);
}
private void init(InputStream inputstream)
throws JDBFException
{
try
{
stream = new DataInputStream(inputstream);
int i = readHeader();
fields = new JDBField[i];
int j = 1;
for(int k = 0; k < i; k++)
{
fields[k] = readFieldHeader();
j += fields[k].getLength();
}
if(stream.read() < 1)
throw new JDBFException("Unexpected end of file reached.");
nextRecord = new byte[j];
try
{
stream.readFully(nextRecord);
}
catch(EOFException eofexception)
{
nextRecord = null;
stream.close();
}
}
catch(IOException ioexception)
{
throw new JDBFException(ioexception);
}
}
private int readHeader()
throws IOException, JDBFException
{
byte abyte0[] = new byte[16];
try
{
stream.readFully(abyte0);
}
catch(EOFException eofexception)
{
throw new JDBFException("Unexpected end of file reached.");
}
int i = abyte0[8];
if(i < 0)
i += 256;
i += 256 * abyte0[9];
i = --i / 32;
i--;
try
{
stream.readFully(abyte0);
}
catch(EOFException eofexception1)
{
throw new JDBFException("Unexpected end of file reached.");
}
return i;
}
private JDBField readFieldHeader()
throws IOException, JDBFException
{
byte abyte0[] = new byte[16];
try
{
stream.readFully(abyte0);
}
catch(EOFException eofexception)
{
throw new JDBFException("Unexpected end of file reached.");
}
StringBuffer stringbuffer = new StringBuffer(10);
for(int i = 0; i < 10; i++)
{
if(abyte0[i] == 0)
break;
stringbuffer.append((char)abyte0[i]);
}
char c = (char)abyte0[11];
try
{
stream.readFully(abyte0);
}
catch(EOFException eofexception1)
{
throw new JDBFException("Unexpected end of file reached.");
}
int j = abyte0[0];
int k = abyte0[1];
if(j < 0)
j += 256;
if(k < 0)
k += 256;
return new JDBField(stringbuffer.toString(), c, j, k);
}
public int getFieldCount()
{
return fields.length;
}
public JDBField getField(int i)
{
return fields[i];
}
public boolean hasNextRecord()
{
return nextRecord != null;
}
public Object[] nextRecord()
throws JDBFException
{
if(!hasNextRecord())
throw new JDBFException("No more records available.");
Object aobj[] = new Object[fields.length];
int i = 1;
for(int j = 0; j < aobj.length; j++)
{
int k = fields[j].getLength();
StringBuffer stringbuffer = new StringBuffer(k);
stringbuffer.append(new String(nextRecord, i, k));
aobj[j] = fields[j].parse(stringbuffer.toString());
i += fields[j].getLength();
}
try
{
stream.readFully(nextRecord);
}
catch(EOFException eofexception)
{
nextRecord = null;
}
catch(IOException ioexception)
{
throw new JDBFException(ioexception);
}
return aobj;
}
public void close()
throws JDBFException
{
nextRecord = null;
try
{
stream.close();
}
catch(IOException ioexception)
{
throw new JDBFException(ioexception);
}
}
private DataInputStream stream;
private JDBField fields[];
private byte nextRecord[];
}
最后,给出一个简单的测试样例程序
/**
* <p>Title: java访问DBF文件的接口</p>
* <p>Description: 测试DBF文件的读写</p>
* <p>Copyright: Copyright (c) 2004</p>
* <p>Company: ict</p>
* @author : He Xiong
* @version 1.0
*/
import com.hexiong.jdbf.DBFReader;
import java.io.PrintStream;
import java.net.URL;
public class Test
{
public Test()
{
}
public static void main(String args[])
throws Exception
{
DBFReader dbfreader = new DBFReader("E://lakes.dbf");
int i;
for(i = 0; dbfreader.hasNextRecord(); i++)
{
Object aobj[] = dbfreader.nextRecord();
for (int j=0; j<aobj.length; j++)
System.out.print(aobj[j]+" | ");
System.out.print("/n");
}
System.out.println("Total Count: " + i);
}
}