Skip to content

Commit

Permalink
Merge pull request #32 from ActioPtyLtd/master
Browse files Browse the repository at this point in the history
add support to view deleted records
  • Loading branch information
albfernandez authored Jul 28, 2017
2 parents 0d5beda + 9661700 commit 9f44839
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 13 deletions.
59 changes: 51 additions & 8 deletions src/main/java/com/linuxense/javadbf/DBFReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ public class DBFReader extends DBFBase implements Closeable {
private DataInputStream dataInputStream;
private DBFHeader header;
private boolean trimRightSpaces = true;
private boolean showDeletedRows = false;

private DBFMemoFile memoFile = null;

Expand All @@ -159,26 +160,55 @@ public class DBFReader extends DBFBase implements Closeable {
* @param in the InputStream where the data is read from.
*/
public DBFReader(InputStream in) {
this(in,null);
this(in,null,false);
}


/**
* Intializes a DBFReader object.
*
* Tries to detect charset from file, if failed uses default charset ISO-8859-1
* When this constructor returns the object will have completed reading the
* header (meta date) and header information can be queried there on. And it
* will be ready to return the first row.
*
* @param in the InputStream where the data is read from.
* @param showDeletedRows can be used to identify records that have been deleted.
*/
public DBFReader(InputStream in, Boolean showDeletedRows) {
this(in,null, showDeletedRows);
}

/**
* Initializes a DBFReader object.
*
*
* When this constructor returns the object will have completed reading the
* header (meta date) and header information can be queried there on. And it
* will be ready to return the first row.
*
*
* @param in the InputStream where the data is read from.
* @param charset charset used to decode field names and field contents. If null, then is autedetected from dbf file
*/
public DBFReader(InputStream in,Charset charset) {
public DBFReader(InputStream in,Charset charset) { this(in, charset, false); }

/**
* Initializes a DBFReader object.
*
* When this constructor returns the object will have completed reading the
* header (meta date) and header information can be queried there on. And it
* will be ready to return the first row.
*
* @param in the InputStream where the data is read from.
* @param charset charset used to decode field names and field contents. If null, then is autedetected from dbf file
* @param showDeletedRows can be used to identify records that have been deleted.
*/
public DBFReader(InputStream in,Charset charset,Boolean showDeletedRows) {
try {

this.dataInputStream = new DataInputStream(in);
this.header = new DBFHeader();
this.header.read(this.dataInputStream, charset);
setCharset(this.header.getUsedCharset());
this.showDeletedRows = showDeletedRows;

/* it might be required to leap to the start of records at times */
int fieldSize = this.header.getFieldDescriptorSize();
Expand Down Expand Up @@ -234,14 +264,23 @@ public Date getLastModificationDate() {
* @param index Index of the field. Index of the first field is zero.
*/
public DBFField getField(int index) {

// if showing deleted rows, ensure first column is the deleted flag field
if(showDeletedRows) {
if(index == 0)
return new DBFField("DELETED", DBFDataType.LOGICAL);
else
return new DBFField(this.header.fieldArray[index-1]);
}

return new DBFField(this.header.fieldArray[index]);
}

/**
* Returns the number of field in the DBF.
*/
public int getFieldCount() {
return this.header.userFieldArray.length;
return this.header.userFieldArray.length + (this.showDeletedRows ? 1 : 0);
}

/**
Expand All @@ -257,16 +296,20 @@ public Object[] nextRecord() {
List<Object> recordObjects = new ArrayList<>(this.getFieldCount());
try {
boolean isDeleted = false;

do {
if (isDeleted) {
if (isDeleted && !showDeletedRows) {
skip(this.header.recordLength - 1);
}
int t_byte = this.dataInputStream.readByte();
if (t_byte == END_OF_DATA) {
return null;
}
isDeleted = t_byte == '*';
} while (isDeleted);
} while (isDeleted && !showDeletedRows);

if(showDeletedRows)
recordObjects.add(isDeleted);

for (int i = 0; i < this.header.fieldArray.length; i++) {
DBFField field = this.header.fieldArray[i];
Expand Down
12 changes: 10 additions & 2 deletions src/test/java/com/linuxense/javadbf/DBFReaderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,16 @@ public void testToString () throws IOException {
DBFUtils.close(reader);
}
}



@Test
public void testReadBooksAddedDeleteField() throws IOException {
ReadDBFAssert.testReadDBFFile("books", 12, 10, true);
}

@Test
public void testReadDBFFileDeletedRecords() throws IOException {
ReadDBFAssert.testReadDBFFileDeletedRecords("test_delete",3,1);
}

@Test(expected=DBFException.class)
public void testFailStream() throws DBFException, IOException{
Expand Down
34 changes: 31 additions & 3 deletions src/test/java/com/linuxense/javadbf/ReadDBFAssert.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,17 @@ private ReadDBFAssert() {
}

public static void testReadDBFFile(String fileName, int expectedColumns, int expectedRows) throws DBFException, IOException {
testReadDBFFile(new File("src/test/resources/" + fileName + ".dbf"), expectedColumns, expectedRows);
testReadDBFFile(fileName, expectedColumns, expectedRows, false);
}

public static void testReadDBFFile(File file, int expectedColumns, int expectedRows) throws DBFException, IOException {
public static void testReadDBFFile(String fileName, int expectedColumns, int expectedRows, Boolean showDeletedRows) throws DBFException, IOException {
testReadDBFFile(new File("src/test/resources/" + fileName + ".dbf"), expectedColumns, expectedRows, showDeletedRows);
}

public static void testReadDBFFile(File file, int expectedColumns, int expectedRows, Boolean showDeletedRows) throws DBFException, IOException {
DBFReader reader = null;
try {
reader = new DBFReader(new BufferedInputStream(new FileInputStream(file)));
reader = new DBFReader(new BufferedInputStream(new FileInputStream(file)), showDeletedRows);
testReadDBFFile(reader, expectedColumns, expectedRows);
} finally {
DBFUtils.close(reader);
Expand Down Expand Up @@ -68,4 +72,28 @@ public static void testReadDBFFile(DBFReader reader, int expectedColumns, int ex
Assert.assertEquals(expectedRows, countedRows);
Assert.assertEquals(expectedRows, reader.getRecordCount());
}

public static void testReadDBFFileDeletedRecords(String fileName, int expectedRows, int expectedDeleted) throws DBFException, IOException {

DBFReader reader = null;
try {
reader = new DBFReader(new BufferedInputStream(new FileInputStream(new File("src/test/resources/" + fileName + ".dbf"))), true);
Object[] rowObject;

int countedRows = 0;
int countedDeletes = 0;
while ((rowObject = reader.nextRecord()) != null) {
if(rowObject[0] == Boolean.TRUE)
countedDeletes++;
countedRows++;
}

Assert.assertEquals(countedRows, expectedRows);
Assert.assertEquals(countedDeletes, expectedDeleted);
} finally {
DBFUtils.close(reader);
}


}
}
Binary file added src/test/resources/test_delete.dbf
Binary file not shown.

0 comments on commit 9f44839

Please sign in to comment.