internal const int RESERVED_INDEX = 12; // 12-31 /** * Constructs a DBFHeader, read the data from file <br> * You need to supply an open file handle to read from * @param ff open file handle for read access */ internal DBFHeader(java.io.RandomAccessFile ff) //throws tinySQLException { try { ff.seek(FLAG_INDEX); file_type = Utils.fixByte(ff.readByte()); // get the last update date file_update_year = Utils.fixByte(ff.readByte()); file_update_month = Utils.fixByte(ff.readByte()); file_update_day = Utils.fixByte(ff.readByte()); // a byte array to hold little-endian long data // byte[] b = new byte[4]; // read that baby in... // ff.readFully(b); // convert the byte array into a long (really a double) // 4-7 number of records numRecords = (int)Utils.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) // 8-9 Length of header ff.readFully(b); headerLength = Utils.vax_to_short(b); // find out the length of the data portion // 10-11 Length of Record ff.readFully(b); recordLength = Utils.vax_to_short(b); // calculate the number of fields // numFields = (int)(headerLength - 33) / 32; // skip the next 20 bytes - looks like this is not needed... //ff.skipBytes(20); // 12-31 reserved Utils.log("HEADER=" + this.toString()); } catch (Exception e) { throw new TinySQLException(e.getMessage()); } }
/** * Retrieve a record (=row) * @param dbfHeader dBase meta info * @param recordNumber starts with 1 * @return the String with the complete record * or null if the record is marked as deleted * @see tinySQLTable#GetCol */ public String GetRecord(java.io.RandomAccessFile ff, DBFHeader dbfHeader, int recordNumber) //throws tinySQLException { if (recordNumber < 1) { throw new TinySQLException("Internal error - current record number < 1"); } try { // seek the starting offset of the current record, // as indicated by recordNumber ff.seek(dbfHeader.headerLength + (recordNumber - 1) * dbfHeader.recordLength); // fully read a byte array out to the length of // the record. byte[] b = new byte[dbfHeader.recordLength]; ff.readFully(b); // make it into a String String record = new java.lang.StringJ(b, Utils.encode); // remove deleted records if (DBFFileTable.isDeleted(record)) { return(null); } return(record); } catch (Exception e) { throw new TinySQLException(e.getMessage()); } }
/* * Retrieve a column's string value from the given row and given colName * @param ff the file handle * @param colName the column name * @param the wanted record (starts with 1) * @see tinySQLTable#GetCol * * @author Thomas Morgner <*****@*****.**> This function retrieves a * row, perhaps the name should changed to reflect the new function. */ public static String _GetCol(java.io.RandomAccessFile ff, DBFHeader dbfHeader, int currentRow) //throws TinySQLException { try { /* * Seek the starting offset of the current record, * as indicated by currentRow */ ff.seek(dbfHeader.headerLength + (currentRow - 1) * dbfHeader.recordLength); /* * Fully read a byte array out to the length of the record and convert * it into a String. */ byte[] b = new byte[dbfHeader.recordLength]; ff.readFully(b); return(new java.lang.StringJ(b, Utils.encode)); // "Cp437" } catch (Exception e) { throw new TinySQLException(e.getMessage()); } }
/** * Reads the central directory of the given archive and populates * the internal tables with ZipArchiveEntry instances. * * <p>The ZipArchiveEntrys will know all data that can be obtained from * the central directory alone, but not the data that requires the * local file header or additional data to be read.</p> * * @return a Map<ZipArchiveEntry, NameAndComment>> of * zipentries that didn't have the language encoding flag set when * read. */ private java.util.Map <ZipArchiveEntry, IAC_NameAndComment> populateFromCentralDirectory() //throws IOException { java.util.HashMap <ZipArchiveEntry, IAC_NameAndComment> noUTF8Flag = new java.util.HashMap <ZipArchiveEntry, IAC_NameAndComment>(); positionAtCentralDirectory(); byte[] cfh = new byte[CFH_LEN]; byte[] signatureBytes = new byte[WORD]; archive.readFully(signatureBytes); long sig = ZipLong.getValue(signatureBytes); long cfhSig = ZipLong.getValue(ZipArchiveOutputStream.CFH_SIG); if (sig != cfhSig && startsWithLocalFileHeader()) { throw new java.io.IOException("central directory is empty, can't expand" + " corrupt archive."); } while (sig == cfhSig) { archive.readFully(cfh); int off = 0; ZipArchiveEntry ze = new ZipArchiveEntry(); int versionMadeBy = ZipShort.getValue(cfh, off); off += SHORT; ze.setPlatform((versionMadeBy >> BYTE_SHIFT) & NIBLET_MASK); off += SHORT; // skip version info GeneralPurposeBit gpFlag = GeneralPurposeBit.parse(cfh, off); bool hasUTF8Flag = gpFlag.usesUTF8ForNames(); ZipEncoding entryEncoding = hasUTF8Flag ? ZipEncodingHelper.UTF8_ZIP_ENCODING : zipEncoding; ze.setGeneralPurposeBit(gpFlag); off += SHORT; ze.setMethod(ZipShort.getValue(cfh, off)); off += SHORT; // FIXME this is actually not very cpu cycles friendly as we are converting from // dos to java while the underlying Sun implementation will convert // from java to dos time for internal storage... long time = ZipUtil.dosToJavaTime(ZipLong.getValue(cfh, off)); ze.setTime(time); off += WORD; ze.setCrc(ZipLong.getValue(cfh, off)); off += WORD; ze.setCompressedSize(ZipLong.getValue(cfh, off)); off += WORD; ze.setSize(ZipLong.getValue(cfh, off)); off += WORD; int fileNameLen = ZipShort.getValue(cfh, off); off += SHORT; int extraLen = ZipShort.getValue(cfh, off); off += SHORT; int commentLen = ZipShort.getValue(cfh, off); off += SHORT; off += SHORT; // disk number ze.setInternalAttributes(ZipShort.getValue(cfh, off)); off += SHORT; ze.setExternalAttributes(ZipLong.getValue(cfh, off)); off += WORD; byte[] fileName = new byte[fileNameLen]; archive.readFully(fileName); ze.setName(entryEncoding.decode(fileName)); // LFH offset, IAC_OffsetEntry offset = new IAC_OffsetEntry(); offset.headerOffset = ZipLong.getValue(cfh, off); // data offset will be filled later entries.put(ze, offset); nameMap.put(ze.getName(), ze); byte[] cdExtraData = new byte[extraLen]; archive.readFully(cdExtraData); ze.setCentralDirectoryExtra(cdExtraData); byte[] comment = new byte[commentLen]; archive.readFully(comment); ze.setComment(entryEncoding.decode(comment)); archive.readFully(signatureBytes); sig = ZipLong.getValue(signatureBytes); if (!hasUTF8Flag && useUnicodeExtraFields) { noUTF8Flag.put(ze, new IAC_NameAndComment(fileName, comment)); } } return(noUTF8Flag); }
/** * Reading a column definition from file<br> * @param ff file handle (correctly positioned) * @param iCol index starts with 1 * @param locn offset to the current column * @return struct with column info */ internal static TsColumn readColdef(java.io.RandomAccessFile ff, String tableName, int iCol, int locn) //throws tinySQLException { try { // seek the position of the field definition data. // This information appears after the first 32 byte // table information, and lives in 32 byte chunks. // ff.seek((iCol - 1) * 32 + 32); // get the column name into a byte array // byte[] b = new byte[11]; ff.readFully(b); // convert the byte array to a String // Seek first 0x00 occurence and strip array after that // // some C-implementations do not set the remaining bytes // after the name to 0x00, so we have to correct this. //bool clear = false; int i = 0; while ((i < 11) && (b[i] != 0)) { i++; } while (i < 11) { b[i] = 0; i++; } String colName = (new java.lang.StringJ(b, Utils.encode)).trim(); // read in the column type which follows the 11 byte column name // byte[] c = new byte[1]; c[0] = ff.readByte(); String ftyp = new java.lang.StringJ(c, Utils.encode); // skip four bytes // ff.skipBytes(4); // get field length and precision which are in the two bytes following // the column type. // short flen = Utils.fixByte(ff.readByte()); // 16 short fdec = Utils.fixByte(ff.readByte()); // 17 if (ftyp.equals("N") & fdec == 0) { ftyp = "I"; } // bytes 18 - 31 are reserved // create a new tsColumn object and assign it the // attributes of the current field // if (TinySQLGlobals.DEBUG) { java.lang.SystemJ.outJ.println("Try and create tsColumn for " + colName); } TsColumn column = new TsColumn(colName); /* * The column type is now given as java.sql.Types constant */ column.type = typeToSQLType(ftyp); column.size = flen; column.decimalPlaces = fdec; column.position = locn + 1; // set the field position to the current column.tableName = tableName; return(column); } catch (Exception e) { throw new TinySQLException(e.getMessage()); } }