📄 dbffile.java
字号:
// **********************************************************************// // <copyright>// // BBN Technologies// 10 Moulton Street// Cambridge, MA 02138// (617) 873-8000// // Copyright (C) BBNT Solutions LLC. All rights reserved.// // </copyright>// **********************************************************************// // $Source: /cvs/distapps/openmap/src/openmap/com/bbn/openmap/dataAccess/shape/DbfFile.java,v $// $RCSfile: DbfFile.java,v $// $Revision: 1.1.2.2 $// $Date: 2007/06/21 21:41:35 $// $Author: dietrick $// // **********************************************************************package com.bbn.openmap.dataAccess.shape;import java.io.EOFException;import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStream;import java.net.URL;import java.text.DecimalFormatSymbols;import java.util.ArrayList;import java.util.List;import java.util.Locale;import com.bbn.openmap.dataAccess.shape.input.DbfInputStream;import com.bbn.openmap.dataAccess.shape.output.DbfOutputStream;import com.bbn.openmap.io.BinaryBufferedFile;import com.bbn.openmap.io.BinaryFile;import com.bbn.openmap.io.FormatException;import com.bbn.openmap.util.ArgParser;import com.bbn.openmap.util.Debug;import com.bbn.openmap.util.FileUtils;/** * An extension to DbfTableModel that handles reading only certain records when * needed, in conjuction with some spatial indexing mechanism. Can be told to * which columns to read and which to skip, so unnecessary/unused information * isn't held in memory. * * @author dietrick */public class DbfFile extends DbfTableModel { protected int _rowCount; protected int _recordLength; protected int _headerLength; /** * This _columnMask variable is an array that either contains a Boolean.TRUE * for the indexes for columns that should be read, or a Integer object that * contans the byte length of the column entry, so the reader will know how * many bytes to skip for columns being ignored. The _length array contents * were modified to reflect the lengths of only the columns being read when * the column mask was set, as was the _names, _types, and _decimalCount * arrays. The order and length of those arrays match the order of the * Boolean.TRUE objects in the _columnMask array. */ protected Object[] _columnMask = null; protected java.text.DecimalFormat df; protected BinaryFile bf; protected DbfFile() { df = new java.text.DecimalFormat(); DecimalFormatSymbols dfs = new DecimalFormatSymbols(Locale.ENGLISH); df.setDecimalFormatSymbols(dfs); } /** * Creates a blank DbfTableModel * * @param columnCount The number of columns this model will manage */ public DbfFile(int columnCount) { this(); _columnCount = columnCount; _records = new ArrayList(); _lengths = new int[columnCount]; _decimalCounts = new byte[columnCount]; _types = new byte[columnCount]; _names = new String[columnCount]; } public DbfFile(BinaryFile bf) throws EOFException, FormatException, IOException { this(); setBinaryFile(bf); } public void readHeader(BinaryFile bf) throws FormatException, IOException { try { bf.seek(0); bf.byteOrder(false); /* byte description = */bf.read(); /* byte year = */bf.read(); /* byte month = */bf.read(); /* byte day = */bf.read(); _rowCount = bf.readInteger(); _headerLength = bf.readShort(); _recordLength = bf.readShort(); _columnCount = (_headerLength - 32 - 1) / 32; bf.skipBytes(20); _names = new String[_columnCount]; _types = new byte[_columnCount]; _lengths = new int[_columnCount]; _decimalCounts = new byte[_columnCount]; for (int n = 0; n <= _columnCount - 1; n++) { // 32 bytes for each column _names[n] = bf.readFixedLengthString(11); // // Some TIGER dbf files from ESRI have nulls // in the column names. Delete them. // int ix = _names[n].indexOf((char) 0); if (ix > 0) { _names[n] = _names[n].substring(0, ix); } _types[n] = (byte) bf.read(); bf.skipBytes(4); _lengths[n] = bf.readUnsigned(); _decimalCounts[n] = (byte) bf.read(); bf.skipBytes(14); } if (DEBUG && _headerLength != bf.getFilePointer()) { Debug.output("DbfFile: Header length specified in file doesn't match current pointer location"); } } catch (EOFException eofe) { throw new FormatException(eofe.getMessage()); } } /** * Reads the data and puts data in an ArrayList of records. */ public void readData() throws IOException, FormatException { readData(0, _rowCount); } /** * Read in a set of records from the dbf file, starting at the provided * index and continuing for the provided count. * * @param startingRecordIndex, 0 is the first record index. * @param numRecordsToRead * @throws IOException * @throws FormatException */ public void readData(int startingRecordIndex, int numRecordsToRead) throws IOException, FormatException { if (startingRecordIndex < 0) { startingRecordIndex = 0; } if (numRecordsToRead < 0 || numRecordsToRead > _rowCount - startingRecordIndex) { numRecordsToRead = _rowCount - startingRecordIndex; } _records = new ArrayList(numRecordsToRead); for (int r = startingRecordIndex; r <= numRecordsToRead - 1; r++) { List record = getRecordData(r); _records.add(record); } } /** * Fetches the record data for the given index. * * @param index the index of the data, starting at 0 for the first record. * @return List containing Strings and Numbers for the dbf entry for the * record. * @throws IOException * @throws FormatException */ public List getRecordData(int index) throws IOException, FormatException { if (bf == null) { throw new IOException("DbfFile not set with valid BinaryFile."); } bf.seek(_headerLength + index * _recordLength); /* int deleteFlag = */bf.read(); int columnCount = _columnCount; if (_columnMask != null) { columnCount = _columnMask.length; } // Here, even with the columnMask, the _columnCount is the target number // of columns to be stored out of the dbf file. The _columnMask.length // is the number of columns actually in the file (if that array is not // null). ArrayList record = new ArrayList(_columnCount); int targetColumnIndex = 0; for (int c = 0; c <= columnCount - 1; c++) { if (_columnMask == null || _columnMask[c] == Boolean.TRUE) { int length = _lengths[targetColumnIndex]; if (length == -1) length = 255; int type = _types[targetColumnIndex]; String cell = bf.readFixedLengthString(length).trim(); if (type == DbfTableModel.TYPE_NUMERIC && !cell.equals("")) { try { // record.add(c, new Double(cell)); record.add(targetColumnIndex, new Double(df.parse(cell) .doubleValue())); // } catch (NumberFormatException nfe) { // Debug.error("DbfInputStream: error reading // column " + c + ", row " + r + // ", expected number and got " + cell); // record.add(c, new Double(0)); } catch (java.text.ParseException pe) { if (Debug.debugging("shape")) { Debug.error("DbfInputStream: error parsing column " + targetColumnIndex + ", row " + index + ", expected number and got " + cell); } record.add(targetColumnIndex, DbfInputStream.ZERO); } } else { record.add(targetColumnIndex, cell); } targetColumnIndex++; } else { bf.skipBytes(((Integer) _columnMask[c]).intValue()); } } return record; } /** * Clear the record information from memory. * */ public void clearRecords() { if (_records != null) { _records.clear(); } } /** * Create another DbfTableModel with the same structure as this one (number * of columns, column names, lengths and decimal counts). */ public DbfTableModel headerClone() { int size = getColumnCount(); DbfFile dtm = new DbfFile(size); for (int i = 0; i < size; i++) { dtm.setColumnName(i, this.getColumnName(i)); dtm.setDecimalCount(i, this.getDecimalCount(i)); dtm.setLength(i, this.getLength(i)); dtm.setType(i, this.getType(i)); } return dtm; } /** * Creates a DbfTableModel for a given .dbf file * * @param dbf The url of the file to retrieve. * @return The DbfTableModel, null if there is a problem. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -