@ SuppressWarnings ( { "checkstyle:npathcomplexity" , "checkstyle:magicnumber" } ) public List < DBaseFileField > readDBFFields ( ) throws IOException , EOFException { if ( this . fields != null ) { return this . fields ; } if ( this . finished ) { throw new EOFDBaseFileException ( ) ; } if ( this . fieldCount == - 1 ) { throw new MustCallReadHeaderFunctionException ( ) ; } // //----------------------------------------------------------- // Bytes Size Content //----------------------------------------------------------- // 32-m n*32 bytes Field descriptors (see bellow) // m+1 1 byte terminator character 0x0D // A field contains at least the "removal flag" byte int byteSize = 1 ; final ArrayList < DBaseFileField > array = new ArrayList <> ( ) ; final Charset charSet = ( this . codePage == null ) ? null : this . codePage . getChatset ( ) ; String columnName ; for ( int idxFields = 0 ; idxFields < this . fieldCount ; ++ idxFields ) { // Read the field header // //----------------------------------------------------------- // Bytes Size Content //----------------------------------------------------------- // 0-10 11 bytes Field name, filled with 0x00 // 11 1 byte Field type (see bellow) // 12-15 4 bytes Field data address, not useful for disk // 16 1 byte Field length // 17 1 byte Field decimal count // 18-19 2 bytes Reserved for dBASE III+ on a Lan // 20 1 byte Work area ID // 21-22 2 bytes Reserved for dBASE III+ on a Lan // 23 1 byte SET FIELDS flag // 24-31 7 bytes Reserved final byte [ ] header = new byte [ 32 ] ; this . stream . readFully ( header ) ; // Update the offset of the first record with the end-of-header character this . firstRecordOffset += header . length ; // Read the name of the field until 0x00 int nbChars = 0 ; for ( int i = 0 ; i <= 10 ; ++ i ) { if ( header [ i ] == 0 ) { break ; } ++ nbChars ; } final byte [ ] bName = new byte [ nbChars ] ; System . arraycopy ( header , 0 , bName , 0 , nbChars ) ; if ( charSet != null ) { columnName = new String ( bName , charSet ) ; } else { columnName = new String ( bName ) ; } // Read the type final DBaseFieldType dbftype = DBaseFieldType . fromByte ( header [ 11 ] ) ; final DBaseFileField field = new DBaseFileField ( columnName , dbftype , // convert unsigned byte into int header [ 16 ] & 0xFF , // convert unsigned byte into int header [ 17 ] & 0xFF , idxFields ) ; array . add ( field ) ; byteSize += field . getLength ( ) ; } // Check if the byte size of the field list corresponds to size specified record size inside the header if ( byteSize != this . recordSize ) { throw new InvalidRecordSizeException ( this . recordSize , byteSize ) ; } // Read the terminator character 0x0D final byte bt = this . stream . readByte ( ) ; if ( bt != 0x0D ) { throw new InvalidDBaseFieldTerminationException ( bt ) ; } // Update the offset of the first record with the end-of-header character ++ this . firstRecordOffset ; this . fields = array ; // Save the position inside the input stream for seeking function if ( this . stream . markSupported ( ) ) { this . stream . mark ( this . recordSize * this . recordCount + this . firstRecordOffset + 1 ) ; } return array ; }
Read the field definitions . Multiple calls to this method will return always the same data structure . The column list is red only at the first call to this function . So you could use this method to obtain the list of the dBASE file s columns .