📄 dbffiletable.java
字号:
/* * * Extension of tinySQLTable which manipulates dbf files. * * Copyright 1996 John Wiley & Sons, Inc. All Rights Reserved. Reproduction * or translation of this work beyond that permitted in Section 117 of the 1976 * United States Copyright Act without the express written permission of the * copyright owner is unlawful. Requests for further information should be * addressed to Permissions Department, John Wiley & Sons, Inc. The * purchaser may make back-up copies for his/her own use only and not for * distribution or resale. The Publisher assumes no responsibility for errors, * omissions, or damages, caused by the use of this software or from the use * of the information contained herein. * */import java.util.*;import java.lang.*;import java.io.*;public class dbfFileTable extends tinySQLTable { // the full path to the file // String fullpath; // the file type (dbase, fox, etc) and the file update date values // short file_type, file_update_year, file_update_month, file_update_day; // number of records in the table // double file_numrecs; // data start position, and length of the data // int file_datap, file_datalength; // number of columns // int num_fields; // the object I'll use to manipulate the table // RandomAccessFile ftbl; // current record // long record_number = 0; // current record // end of file flag // boolean eof = false; /** * * Constructs a dbfFileTable. This is only called by getTable() * in dbfFile.java. * * @param dDir data directory * @param table_name the name of the table * */ dbfFileTable( String dDir, String table_name ) throws tinySQLException { // the full path to the file // fullpath = dDir + "/" + table_name; // strip the name out of the path // table = new File(table_name).getName(); // ensure that the full path includes the // .DBF suffix // if (! fullpath.toUpperCase().endsWith(".DBF") ) { fullpath = fullpath + ".DBF"; } // Open the DBF file // open_dbf(); } /** * * close method. Try not to call this until you are sure * the object is about to go out of scope. * */ public void close() throws tinySQLException { try { ftbl.close(); } catch (IOException e) { throw new tinySQLException(e.getMessage()); } } /** * * Returns the size of a column * * @param column name of the column * @see tinySQLTable#ColSize * */ public int ColSize(String col_name) { // retrieve the column object from the column_info Hashtable // dbfCol column = (dbfCol) column_info.get(col_name); // return its size // return column.size; } /** * * Returns the datatype of a column. * * @param column name of the column. * @see tinySQLTable#ColType * */ public String ColType(String col_name) { // retrieve the column object from the column_info Hashtable // dbfCol column = (dbfCol) column_info.get(col_name); // return its type // return column.type; } /** * * Updates the current row in the table. This fails because * dbfFileTable operates in read/only mode. * * @param c Ordered Vector of column names * @param v Ordered Vector (must match order of c) of values * @see tinySQLTable#UpdateCurrentRow * */ public void UpdateCurrentRow(Vector c, Vector v) throws tinySQLException { throw new tinySQLException("dbfFileTable operates in read/only mode."); } /** * * Position the record pointer at the top of the table. * * @see tinySQLTable#GoTop * */ public void GoTop() throws tinySQLException { record_number = 0; eof = false; } /** * * Advance the record pointer to the next record. * * @see tinySQLTable#NextRecord * */ public boolean NextRecord() throws tinySQLException { if (record_number < file_numrecs) { record_number++; eof = false; return true; } else { eof = true; return false; } } /** * * Insert a blank row. * * @see tinySQLTable#InsertRow() * */ public void InsertRow() throws tinySQLException { throw new tinySQLException("dbfFileTable operates in read/only mode."); } /** * * Retrieve a column's string value from the current row. * * @param column the column name * @see tinySQLTable#GetCol * */ public String GetCol(String col_name) throws tinySQLException { try { // retrieve the dbfCol object which corresponds // to this column. // dbfCol column = (dbfCol) column_info.get(col_name); // seek the starting offset of the current record, // as indicated by record_number // ftbl.seek( file_datap + (record_number - 1) * file_datalength); // fully read a byte array out to the length of // the record. // byte[] b = new byte[file_datalength]; ftbl.readFully(b); // make it into a String // String result = new String(b, "Cp437"); // if it's the pseudo column _DELETED, return // the first character in it // if (col_name.equals("_DELETED")) { return result.substring(0, 1); } // for all other columns, return the substring which begins at // the column's position within the record, and continues // for the column's size. // return result.substring(column.position, column.position + column.size); } catch (Exception e) { e.printStackTrace(); throw new tinySQLException(e.getMessage()); } } /** * * Update a single column. * * @param column the column name * @param value the String value with which update the column * @see tinySQLTable#UpdateCol * */ public void UpdateCol( String column, String value ) throws tinySQLException { throw new tinySQLException("dbfFileTable operates in read/only mode."); } /** * * Delete the current row. * * @see tinySQLTable#DeleteRow * */ public void DeleteRow() throws tinySQLException { throw new tinySQLException("dbfFileTable operates in read/only mode."); } /** * * Is the current row deleted? * * @see tinySQLTable#isDeleted() * */ public boolean isDeleted() throws tinySQLException { // this is real easy; just check the value of the _DELETED column // return (GetCol("_DELETED")).equals("*"); } // end methods implemented from tinySQLTable.java // the rest of this stuff is private methods // for dbfFileTable // /* * * opens a DBF file. This is based on Pratap Pereira's * Xbase.pm perl module * */ private void open_dbf() throws tinySQLException { try { // open the file // ftbl = new RandomAccessFile(fullpath, "r"); // position the record pointer at 0 // ftbl.seek(0); // read the file type // file_type = fixByte(ftbl.readByte()); // get the last update date // file_update_year = fixByte(ftbl.readByte()); file_update_month = fixByte(ftbl.readByte()); file_update_day = fixByte(ftbl.readByte()); // a byte array to hold little-endian long data // byte[] b = new byte[4]; // read that baby in... // ftbl.readFully(b); // convert the byte array into a long (really a double) // file_numrecs = vax_to_long(b); // a byte array to hold little-endian short data // b = new byte[2]; // get the data position (where it starts in the file) // ftbl.readFully(b); file_datap = vax_to_short(b); // find out the length of the data portion // ftbl.readFully(b); file_datalength = vax_to_short(b); // calculate the number of fields // num_fields = (int) (file_datap - 33)/32; // skip the next 20 bytes - looks like this is not needed... //ftbl.skipBytes(20); // read in the column data // int i; int locn = 0; // offset of the current column // process each field // for (i = 1; i <= num_fields; i++) { // seek the position of the field definition data. // This information appears after the first 32 byte // table information, and lives in 32 byte chunks. // ftbl.seek( (i - 1) * 32 + 32 ); // get the column name into a byte array // b = new byte[10]; ftbl.readFully(b); // convert the byte array to a String // String col_name = (new String(b, "Cp437")).trim(); // read in the column type // char c[] = new char[1]; c[0] = ftbl.readChar(); String ftyp = new String(c); // skip four bytes // ftbl.skipBytes(4); // get field length and precision // short flen = fixByte(ftbl.readByte()); short fdec = fixByte(ftbl.readByte()); // set the field position to the current // value of locn // int fpos = locn; // increment locn by the length of this field. // locn += flen; // create a new dbfCol object and assign it the // attributes of the current field // dbfCol column = new dbfCol(col_name); column.type = new String(c); column.size = flen; column.position = fpos + 1; column.table = table; // now, why don't we do it this way in // textFileTable.java??? // column_info.put(col_name, column); } } catch (Exception e) { e.printStackTrace(); throw new tinySQLException(e.getMessage()); } } /** * * Converts a little-endian four-byte array to a long, * represented as a double, since long is signed. * * I don't know why Java doesn't supply this. It could * be that it's there somewhere, but I looked and couldn't * find it. * */ public static double vax_to_long(byte[] b) { return fixByte(b[0]) + ( fixByte(b[1]) * 256) + ( fixByte(b[2]) * (256^2)) + ( fixByte(b[3]) * (256^3)); } /** * * Converts a little-endian four-byte array to a short, * represented as an int, since short is signed. * * I don't know why Java doesn't supply this. It could * be that it's there somewhere, but I looked and couldn't * find it. * */ public static int vax_to_short(byte[] b) { return (int) ( fixByte(b[0]) + ( fixByte(b[1]) * 256)); } /* * * bytes are signed; let's fix them... * */ public static short fixByte (byte b) { if (b < 0) { return (short) ( b + 256); } return b; }}/* * * extend tsColumn to hold the column's position, as well as all the * other groovy characteristics of a column. * */class dbfCol extends tsColumn { int position = 0; public dbfCol(String c) { super(c); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -