diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
new file mode 100644
index 00000000..0300e140
--- /dev/null
+++ b/.github/workflows/maven.yml
@@ -0,0 +1,25 @@
+# This workflow will build a Java project with Maven
+# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
+
+name: JavaDBF CI
+on:
+ push:
+ branches: [ main, 0.x ]
+ pull_request:
+ branches: [ main, 0.x ]
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ java: [ 8, 11 ]
+ name: Java ${{matrix.java}}
+ steps:
+ - uses: actions/checkout@v2
+ - name: Setup java
+ uses: actions/setup-java@v1
+ with:
+ java-version: ${{matrix.java}}
+ - name: Build with Maven
+ run: mvn -B -Dgpg.skip=true -Dmaven.javadoc.skip=true clean package verify
diff --git a/.gitignore b/.gitignore
index 8bd3a058..ea6ab823 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@
/.settings/
/.classpath
/.project
+/bin/
diff --git a/.travis.yml b/.travis.yml
index 69040a75..8aba7ea0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,7 +3,11 @@ language: java
install: mvn install -DskipTests=true -Dgpg.skip=true -Dmaven.javadoc.skip=true
jdk:
- - openjdk7
- - oraclejdk8
+ - openjdk8
+ - openjdk9
+ - openjdk10
+ - openjdk11
+ - openjdk12
+
-
\ No newline at end of file
+
diff --git a/README.md b/README.md
index fa402d1c..91d7d328 100644
--- a/README.md
+++ b/README.md
@@ -31,7 +31,7 @@ If you are using Maven, you can add JavaDBF to your project using this dependenc
com.github.albfernandez
javadbf
- 0.8.0
+ 0.11.1
```
@@ -333,9 +333,10 @@ Clone the repository or download de tar file from releases page on github, run t
git clone https://github.com/albfernandez/javadbf.git
cd javadbf
+ git checkout tags/v.0.10.0
mvn clean package
-The result file is ``target/javadbf-0.8.0.jar``
+The result file is ``target/javadbf-0.10.0.jar``
diff --git a/doc/old_javadbf_0.4.0_tuturial.md b/doc/old_javadbf_0.4.0_tuturial.md
new file mode 100644
index 00000000..abad6bec
--- /dev/null
+++ b/doc/old_javadbf_0.4.0_tuturial.md
@@ -0,0 +1,298 @@
+# JavaDBF Library Tutorial
+
+
+(for JavaDBF ver. 0.4.0 and above)\
+ Anil Kumar K.\
+ anil at linuxense dot com\
+ Linuxense Information Systems Pvt. Ltd.,
+Trivandrum, India
+
+## 1. Introduction
+
+
+JavaDBF is a Java library for reading and writing XBase files. There are
+plenty of legacy applications around with `.dbf` as their primary
+storage format. JavaDBF was initially written for data transfer with
+such applications.
+
+Other than that, there are requirements to export data from a Java
+application to a spreadshet program like GNumeric, Excel or Lotus 123. A
+DBF file would be more appropriate in such situations rather than a CSV
+or an HTML file because a DBF file can carry field type information.
+More over, XBase format is like an Open-standard; it is understood by
+almost all spreadsheet programms.
+
+## 2. Getting and Installing
+
+Obtain the latest version of JavaDBF from
+http://sarovar.org/projects/javadbf/.
+Create a folder in a convenient location and run:
+
+```bash
+ tar xvfz javadbf-x.x.x-tar.gz
+ cd javadbf-x.x.x
+```
+
+In this folder you will find `javadbf.jar` which contains the library.
+Include this jar file in your `$CLASSPATH` variable. You are ready to
+go.
+
+# 3. Overview of the Library
+
+JavaDBF has a simple API of its own and it does not implement the JDBC
+API. It is designed this way because JavaDBF is not indedned to support
+full-blown RDBMS-style database interaction. And you are not supposed to
+use it like a back-end; it just doesn't work that way. Also, JavaDBF is
+not designed to be thread-safe; keep that in mind when you design
+threaded applications.
+
+JavaDBF comes in the package `com.linuxense.javadbf`. Import that
+package in your Java code. Following examples will familiarise you with
+its APIs.
+
+### 3.1. Data Type Mapping
+
+In version 0.3.2, JavaDBF supports almost all XBase data types except
+Memo field. While reading, those types are interpretted as appropriate
+Java types. Following table shows the mapping scheme.
+
+| XBase Type | XBase Symbol | Java Type used in JavaDBF |
+|---------- | ------------ | ---------------------------
+|Character | C | java.lang.String |
+|Numeric | N | java.math.BigDecimal |
+|Double | F | java.math.BigDecimal |
+|Logical | L | java.lang.Boolean |
+|Date | D | java.util.Date |
+
+## 4. Reading a DBF File
+
+To read a DBF file, JavaDBF provides a DBFReader class. Following is a
+ready-to-compile, self-explanatory program describing almost all feature
+of the `DBFReader` class. Copy/paste this listing and compile it. Keep a
+`.dbf` file handy to pass to this program as its argument.
+
+```java
+ import java.io.*;
+ import com.linuxense.javadbf.*;
+
+ public class JavaDBFReaderTest {
+
+ public static void main( String args[]) {
+
+ try {
+
+ // create a DBFReader object
+ //
+ InputStream inputStream = new FileInputStream( args[ 0]); // take dbf file as program argument
+ DBFReader reader = new DBFReader( inputStream);
+
+ // get the field count if you want for some reasons like the following
+ //
+ int numberOfFields = reader.getFieldCount();
+
+ // use this count to fetch all field information
+ // if required
+ //
+ for( int i=0; i4.0.0
com.github.albfernandez
javadbf
- 0.9.0
+ 0.12.0-SNAPSHOT
https://github.com/albfernandez/javadbf
jar
javadbf
@@ -32,7 +32,10 @@
https://github.com/albfernandez/javadbf/issues
-
+
+ UTF-8
+ UTF-8
+
@@ -49,7 +52,7 @@
org.apache.maven.plugins
maven-compiler-plugin
- 3.3
+ 3.7.0
1.7
@@ -58,7 +61,7 @@
org.codehaus.mojo
findbugs-maven-plugin
- 3.0.3
+ 3.0.5
findbugs-check
@@ -75,7 +78,7 @@
org.apache.maven.plugins
maven-pmd-plugin
- 3.6
+ 3.8
true
@@ -91,9 +94,12 @@
org.apache.maven.plugins
maven-jar-plugin
- 2.6
+ 3.0.2
+
+ com.github.albfernandez.javadbf
+
true
true
@@ -104,7 +110,7 @@
org.apache.maven.plugins
maven-source-plugin
- 2.4
+ 3.0.1
attach-sources
@@ -117,7 +123,7 @@
org.apache.maven.plugins
maven-javadoc-plugin
- 2.10.3
+ 3.0.0
attach-javadocs
@@ -126,53 +132,27 @@
-
-
- org.apache.maven.plugins
- maven-gpg-plugin
- 1.6
-
- ${gpg.keyname}
- ${gpg.keyname}
-
-
-
- sign-artifacts
- verify
-
- sign
-
-
-
-
-
- org.sonatype.plugins
- nexus-staging-maven-plugin
- 1.6.6
- true
-
- ossrh
- https://oss.sonatype.org/
- true
-
-
-
+
-
+
+ org.apache.maven.plugins
+ maven-jxr-plugin
+ 2.5
+
org.apache.maven.plugins
maven-pmd-plugin
- 3.6
+ 3.7
org.codehaus.mojo
findbugs-maven-plugin
- 3.0.3
+ 3.0.4
org.apache.maven.plugins
@@ -189,9 +169,46 @@
+
+
+
+ deploy
+
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+ 1.6
+
+ ${gpg.keyname}
+ ${gpg.keyname}
+
+
+
+ sign-artifacts
+ verify
+
+ sign
+
+
+
+
+
+ org.sonatype.plugins
+ nexus-staging-maven-plugin
+ 1.6.8
+ true
+
+ ossrh
+ https://oss.sonatype.org/
+ true
+
+
+
+
+
+
+
+
-
- UTF-8
- UTF-8
-
\ No newline at end of file
diff --git a/src/main/java/com/linuxense/javadbf/DBFBase.java b/src/main/java/com/linuxense/javadbf/DBFBase.java
index f73a33b8..0de99c3d 100644
--- a/src/main/java/com/linuxense/javadbf/DBFBase.java
+++ b/src/main/java/com/linuxense/javadbf/DBFBase.java
@@ -64,7 +64,10 @@ public void setCharset(Charset charset) {
*/
@Deprecated
public String getCharactersetName() {
- return this.charset.displayName();
+ if (this.charset != null) {
+ return this.charset.displayName();
+ }
+ return null;
}
/**
@@ -80,7 +83,7 @@ public String getCharactersetName() {
*/
@Deprecated
public void setCharactersetName(String characterSetName) {
- this.charset = Charset.forName(characterSetName);
+ setCharset(Charset.forName(characterSetName));
}
}
diff --git a/src/main/java/com/linuxense/javadbf/DBFCharsetHelper.java b/src/main/java/com/linuxense/javadbf/DBFCharsetHelper.java
index d574f71b..6f7a6cfb 100644
--- a/src/main/java/com/linuxense/javadbf/DBFCharsetHelper.java
+++ b/src/main/java/com/linuxense/javadbf/DBFCharsetHelper.java
@@ -15,8 +15,8 @@ private DBFCharsetHelper() {
* (0x1D) is code page mark See
* https://msdn.microsoft.com/en-us/library/aa975345(v=vs.71).aspx
*
- * @param b
- * @return
+ * @param b the codepage to check
+ * @return Charset for the code page
*/
public static Charset getCharsetByByte(int b) {
switch (b) {
@@ -45,10 +45,10 @@ public static Charset getCharsetByByte(int b) {
return forName("IBM852");
case 0x65:
// Russian MS-DOS
- return forName("IBM865");
+ return forName("IBM866");
case 0x66:
// Nordic MS-DOS
- return forName("IBM866");
+ return forName("IBM865");
case 0x67:
// Icelandic MS-DOS
return forName("IBM861");
@@ -123,86 +123,86 @@ public static int getDBFCodeForCharset(Charset charset) {
if (charset == null) {
return 0;
}
- String charsetName = charset.toString().toLowerCase();
+ String charsetName = charset.toString();
- if ("ibm437".equals(charsetName)) {
+ if ("ibm437".equalsIgnoreCase(charsetName)) {
return 0x01;
}
- if ("ibm850".equals(charsetName)) {
+ if ("ibm850".equalsIgnoreCase(charsetName)) {
return 0x02;
}
- if ("windows-1252".equals(charsetName)) {
+ if ("windows-1252".equalsIgnoreCase(charsetName)) {
return 0x03;
}
- if ("iso-8859-1".equals(charsetName)) {
+ if ("iso-8859-1".equalsIgnoreCase(charsetName)) {
return 0x03;
}
- if ("MacRoman".equals(charsetName)) {
+ if ("MacRoman".equalsIgnoreCase(charsetName)) {
return 0x04;
}
- if ("IBM852".equals(charsetName)) {
+ if ("IBM852".equalsIgnoreCase(charsetName)) {
return 0x64;
}
- if ("IBM865".equals(charsetName)) {
- return 0x65;
- }
- if ("IBM866".equals(charsetName)) {
+ if ("IBM865".equalsIgnoreCase(charsetName)) {
return 0x66;
}
- if ("IBM861".equals(charsetName)) {
+ if ("IBM866".equalsIgnoreCase(charsetName)) {
+ return 0x65;
+ }
+ if ("IBM861".equalsIgnoreCase(charsetName)) {
return 0x67;
}
// 0x68
// 0x69
- if ("IBM737".equals(charsetName)) {
+ if ("IBM737".equalsIgnoreCase(charsetName)) {
return 0x6a;
}
- if ("IBM857".equals(charsetName)) {
+ if ("IBM857".equalsIgnoreCase(charsetName)) {
return 0x6b;
}
- if ("windows-950".equals(charsetName)) {
+ if ("windows-950".equalsIgnoreCase(charsetName)) {
return 0x78;
}
- if ("windows-949".equals(charsetName)) {
+ if ("windows-949".equalsIgnoreCase(charsetName)) {
return 0x79;
}
- if ("gbk".equals(charsetName)) {
+ if ("gbk".equalsIgnoreCase(charsetName)) {
return 0x7a;
}
- if ("windows-932".equals(charsetName)) {
+ if ("windows-932".equalsIgnoreCase(charsetName)) {
return 0x7b;
}
- if ("windows-874".equals(charsetName)) {
+ if ("windows-874".equalsIgnoreCase(charsetName)) {
return 0x7c;
}
- if ("windows-1255".equals(charsetName)) {
+ if ("windows-1255".equalsIgnoreCase(charsetName)) {
return 0x7d;
}
- if ("windows-1256".equals(charsetName)) {
+ if ("windows-1256".equalsIgnoreCase(charsetName)) {
return 0x7e;
}
- if ("x-MacCyrillic".equals(charsetName)) {
+ if ("x-MacCyrillic".equalsIgnoreCase(charsetName)) {
return 0x96;
}
- if ("x-MacCentralEurope".equals(charsetName)) {
+ if ("x-MacCentralEurope".equalsIgnoreCase(charsetName)) {
return 0x97;
}
- if ("x-MacGreek".equals(charsetName)) {
+ if ("x-MacGreek".equalsIgnoreCase(charsetName)) {
return 0x98;
}
- if ("windows-1250".equals(charsetName)) {
+ if ("windows-1250".equalsIgnoreCase(charsetName)) {
return 0xc8;
}
- if ("windows-1251".equals(charsetName)) {
+ if ("windows-1251".equalsIgnoreCase(charsetName)) {
return 0xc9;
}
- if ("windows-1254".equals(charsetName)) {
+ if ("windows-1254".equalsIgnoreCase(charsetName)) {
return 0xca;
}
- if ("windows-1253".equals(charsetName)) {
+ if ("windows-1253".equalsIgnoreCase(charsetName)) {
return 0xcb;
}
// Unsupported charsets returns 0
diff --git a/src/main/java/com/linuxense/javadbf/DBFDataType.java b/src/main/java/com/linuxense/javadbf/DBFDataType.java
index efadc027..b8d08e95 100644
--- a/src/main/java/com/linuxense/javadbf/DBFDataType.java
+++ b/src/main/java/com/linuxense/javadbf/DBFDataType.java
@@ -50,7 +50,7 @@ public enum DBFDataType {
/**
* Numeric data
*/
- NUMERIC ((byte) 'N', 1, 18, 0, true),
+ NUMERIC ((byte) 'N', 1, 32, 0, true),
/**
* Numeric long (FoxPro)
*/
@@ -90,6 +90,13 @@ private DBFDataType(byte code, int minSize, int maxSize, int defaultSize, boolea
public byte getCode() {
return this.code;
}
+ /**
+ * Gets the code as stored in the dbf file as character for display purposes.
+ * @return the code for this type
+ */
+ public char getCharCode() {
+ return (char) this.code;
+ }
/**
* Gets the minimum size for this type
@@ -133,5 +140,14 @@ public static DBFDataType fromCode(byte cod) {
throw new IllegalArgumentException("Unknown data type:" + cod);
}
+ /**
+ * Gets the DBFDataType from the code used in the file
+ * @param code the code used by dbase
+ * @return The DBFDataType from the code used in the file
+ */
+ public static DBFDataType fromCode(char code) {
+ return fromCode((byte) code);
+ }
+
}
diff --git a/src/main/java/com/linuxense/javadbf/DBFField.java b/src/main/java/com/linuxense/javadbf/DBFField.java
index db4ed0a7..c7ebca82 100644
--- a/src/main/java/com/linuxense/javadbf/DBFField.java
+++ b/src/main/java/com/linuxense/javadbf/DBFField.java
@@ -142,10 +142,19 @@ protected static DBFField createField(DataInput in, Charset charset) throws IOEx
field.setFieldsFlag = in.readByte(); /* 23 */
in.readFully(field.reserv4); /* 24-30 */
field.indexFieldFlag = in.readByte(); /* 31 */
-
+ adjustLengthForBigCharSupport(field);
return field;
}
-
+ private static void adjustLengthForBigCharSupport(DBFField field) {
+ // if field type is char, then read length and decimalCount as one number to allow char fields to be
+ // longer than 256 bytes.
+ // This is the way Clipper and FoxPro do it, and there is really no downside
+ // since for char fields decimal count should be zero for other versions that do not support this extended functionality.
+ if (field.type == DBFDataType.CHARACTER) {
+ field.fieldLength |= field.decimalCount << 8;
+ field.decimalCount = 0;
+ }
+ }
/**
* Writes the content of DBFField object into the stream as per DBF format
* specifications.
@@ -322,6 +331,15 @@ public void setDecimalCount(int size) {
}
this.decimalCount = (byte) size;
}
+
+ public String toString() {
+ return
+ this.name+"|" + this.type + " (" + this.type.getCharCode() + ")" +
+ "\nLength: " + this.fieldLength +
+ "\nDecimalCount:" + this.decimalCount +
+ "\nIndex:" + this.indexFieldFlag;
+ }
+
/**
* Sets the data type of the field.
diff --git a/src/main/java/com/linuxense/javadbf/DBFHeader.java b/src/main/java/com/linuxense/javadbf/DBFHeader.java
index 2e7efaa5..54d565cd 100644
--- a/src/main/java/com/linuxense/javadbf/DBFHeader.java
+++ b/src/main/java/com/linuxense/javadbf/DBFHeader.java
@@ -128,9 +128,17 @@ void write(DataOutput dataOutput) throws IOException {
this.numberOfRecords = DBFUtils.littleEndian(this.numberOfRecords);
dataOutput.writeInt(this.numberOfRecords); /* 4-7 */
- this.headerLength = findHeaderLength();
+ short oldHeaderLength = this.headerLength;
+ short newHeaderLength = findHeaderLength();
+ if (oldHeaderLength == 0) {
+ this.headerLength = newHeaderLength;
+ }
+ else if (newHeaderLength > oldHeaderLength) {
+ throw new IOException("Invalid header length");
+ }
dataOutput.writeShort(DBFUtils.littleEndian(this.headerLength)); /* 8-9 */
+
this.recordLength = sumUpLenghtOfFields();
dataOutput.writeShort(DBFUtils.littleEndian(this.recordLength)); /* 10-11 */
@@ -142,7 +150,15 @@ void write(DataOutput dataOutput) throws IOException {
dataOutput.writeInt(DBFUtils.littleEndian(this.reserv3)); /* 24-27 */
dataOutput.writeByte(this.mdxFlag); /* 28 */
- dataOutput.writeByte(this.languageDriver); /* 29 */
+ if (this.languageDriver != 0) {
+ dataOutput.writeByte(this.languageDriver); /* 29 */
+ }
+ else if (getUsedCharset() != null) {
+ dataOutput.writeByte(DBFCharsetHelper.getDBFCodeForCharset(getUsedCharset())); /* 29 */
+ }
+ else {
+ dataOutput.writeByte(0); /* 29 */
+ }
dataOutput.writeShort(DBFUtils.littleEndian(this.reserv4)); /* 30-31 */
for (DBFField field : this.fieldArray) {
field.write(dataOutput,getUsedCharset());
diff --git a/src/main/java/com/linuxense/javadbf/DBFReader.java b/src/main/java/com/linuxense/javadbf/DBFReader.java
index 8f9ab8d5..810db899 100644
--- a/src/main/java/com/linuxense/javadbf/DBFReader.java
+++ b/src/main/java/com/linuxense/javadbf/DBFReader.java
@@ -80,11 +80,12 @@
*/
public class DBFReader extends DBFBase {
- private DataInputStream dataInputStream;
- private DBFHeader header;
-
private static final long MILLISECS_PER_DAY = 24*60*60*1000;
private static final long MILLIS_SINCE_4713 = -210866803200000L;
+
+ private DataInputStream dataInputStream;
+ private DBFHeader header;
+ private boolean trimRightSpaces = false;
/**
* Initializes a DBFReader object.
@@ -190,34 +191,56 @@ public Object[] nextRecord() throws DBFException {
try {
boolean isDeleted = false;
do {
- if (isDeleted) {
- skip(this.header.recordLength - 1);
+ try {
+ if (isDeleted) {
+ skip(this.header.recordLength - 1);
+ }
+ int t_byte = this.dataInputStream.readByte();
+ if (t_byte == END_OF_DATA || t_byte == -1) {
+ return null;
+ }
+ isDeleted = t_byte == '*';
}
- int t_byte = this.dataInputStream.readByte();
- if (t_byte == END_OF_DATA) {
+ catch (EOFException e) {
return null;
}
- isDeleted = t_byte == '*';
} while (isDeleted);
-
+ int bytesReaded = 0;
for (int i = 0; i < this.header.fieldArray.length; i++) {
switch (this.header.fieldArray[i].getType()) {
case CHARACTER:
byte b_array[] = new byte[this.header.fieldArray[i].getFieldLength()];
- this.dataInputStream.read(b_array);
- recordObjects[i] = new String(b_array, getCharset());
+ bytesReaded = this.dataInputStream.read(b_array);
+ if (bytesReaded != b_array.length) {
+ throw new EOFException("Unexpected end of file");
+ }
+ if (this.trimRightSpaces) {
+ recordObjects[i] = new String(DBFUtils.trimRightSpaces(b_array), getCharset());
+ }
+ else {
+ recordObjects[i] = new String(b_array, getCharset());
+ }
break;
case DATE:
byte t_byte_year[] = new byte[4];
- this.dataInputStream.read(t_byte_year);
+ bytesReaded = this.dataInputStream.read(t_byte_year);
+ if (bytesReaded != 4) {
+ throw new EOFException("Unexpected end of file");
+ }
byte t_byte_month[] = new byte[2];
- this.dataInputStream.read(t_byte_month);
+ bytesReaded = this.dataInputStream.read(t_byte_month);
+ if (bytesReaded != 2) {
+ throw new EOFException("Unexpected end of file");
+ }
byte t_byte_day[] = new byte[2];
- this.dataInputStream.read(t_byte_day);
+ bytesReaded = this.dataInputStream.read(t_byte_day);
+ if (bytesReaded != 2) {
+ throw new EOFException("Unexpected end of file");
+ }
try {
GregorianCalendar calendar = new GregorianCalendar(Integer.parseInt(new String(t_byte_year, StandardCharsets.US_ASCII)),
@@ -238,10 +261,19 @@ public Object[] nextRecord() throws DBFException {
case NUMERIC:
try {
byte t_float[] = new byte[this.header.fieldArray[i].getFieldLength()];
- this.dataInputStream.read(t_float);
+ bytesReaded = this.dataInputStream.read(t_float);
+ if (bytesReaded != t_float.length) {
+ throw new EOFException("Unexpected end of file");
+ }
t_float = DBFUtils.removeSpaces(t_float);
if (t_float.length > 0 && !DBFUtils.contains(t_float, (byte) '?') && !DBFUtils.contains(t_float, (byte) '*')) {
- recordObjects[i] = new Double(new String(t_float, StandardCharsets.US_ASCII));
+ String aux = new String(t_float, StandardCharsets.US_ASCII).replace(',', '.');
+ if (".".equals(aux)) {
+ recordObjects[i] = Double.valueOf("0.0");
+ }
+ else {
+ recordObjects[i] = Double.valueOf(aux);
+ }
} else {
recordObjects[i] = null;
}
@@ -270,13 +302,19 @@ public Object[] nextRecord() throws DBFException {
case TIMESTAMP:
byte t_byte_date[] = new byte[4];
- this.dataInputStream.read(t_byte_date);
+ bytesReaded = this.dataInputStream.read(t_byte_date);
+ if (bytesReaded != t_byte_date.length) {
+ throw new EOFException("Unexpected end of file");
+ }
byte t_byte_date_reversed[] = {t_byte_date[3],t_byte_date[2],t_byte_date[1],t_byte_date[0]};
int days = ByteBuffer.wrap(t_byte_date_reversed).getInt();
byte t_byte_time[] = new byte[4];
- this.dataInputStream.read(t_byte_time);
+ bytesReaded = this.dataInputStream.read(t_byte_time);
+ if (bytesReaded != t_byte_time.length) {
+ throw new EOFException("Unexpected end of file");
+ }
byte t_byte_time_reversed[] = {t_byte_time[3],t_byte_time[2],t_byte_time[1],t_byte_time[0]};
int time = ByteBuffer.wrap(t_byte_time_reversed).getInt();
@@ -295,9 +333,8 @@ public Object[] nextRecord() throws DBFException {
recordObjects[i] = "null";
}
}
- } catch (EOFException e) {
- return null;
- } catch (IOException e) {
+ }
+ catch (IOException e) {
throw new DBFException(e.getMessage(), e);
}
@@ -320,4 +357,12 @@ protected DBFHeader getHeader() {
return this.header;
}
+ public boolean isTrimRightSpaces() {
+ return this.trimRightSpaces;
+ }
+
+ public void setTrimRightSpaces(boolean trimRightSpaces) {
+ this.trimRightSpaces = trimRightSpaces;
+ }
+
}
diff --git a/src/main/java/com/linuxense/javadbf/DBFUtils.java b/src/main/java/com/linuxense/javadbf/DBFUtils.java
index ddf47d7b..f855fe1f 100644
--- a/src/main/java/com/linuxense/javadbf/DBFUtils.java
+++ b/src/main/java/com/linuxense/javadbf/DBFUtils.java
@@ -22,6 +22,7 @@
package com.linuxense.javadbf;
import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
import java.io.DataInput;
import java.io.IOException;
import java.nio.charset.Charset;
@@ -173,33 +174,36 @@ public static byte[] textPadding(String text, Charset charset, int length, DBFAl
/**
* Format a number to write to a dbf file
- * @param num number to write
+ * @param doubleNumber number to write
* @param charset charset to use
* @param fieldLength
* @param sizeDecimalPart
* @return bytes to write to the dbf file
*/
- public static byte[] doubleFormating(Number num, Charset charset, int fieldLength, int sizeDecimalPart) {
- return doubleFormating(num.doubleValue(), charset, fieldLength, sizeDecimalPart);
+ public static byte[] doubleFormating(Double doubleNumber, Charset charset, int fieldLength, int sizeDecimalPart) {
+ return doubleFormating((Number) doubleNumber, charset, fieldLength, sizeDecimalPart);
}
/**
* Format a double number to write to a dbf file
- * @param doubleNum
- * @param charset
- * @param fieldLength
+ * @param num Number to write
+ * @param charset charset to use
+ * @param fieldLength
* @param sizeDecimalPart
* @return bytes to write to the dbf file
*/
- public static byte[] doubleFormating(Double doubleNum, Charset charset, int fieldLength, int sizeDecimalPart) {
+ public static byte[] doubleFormating(Number num, Charset charset, int fieldLength, int sizeDecimalPart) {
int sizeWholePart = fieldLength - (sizeDecimalPart > 0 ? (sizeDecimalPart + 1) : 0);
StringBuilder format = new StringBuilder(fieldLength);
- for (int i = 0; i < sizeWholePart; i++) {
+ for (int i = 0; i < sizeWholePart-1; i++) {
format.append("#");
}
+ if (format.length() < sizeWholePart) {
+ format.append("0");
+ }
if (sizeDecimalPart > 0) {
format.append(".");
for (int i = 0; i < sizeDecimalPart; i++) {
@@ -209,7 +213,7 @@ public static byte[] doubleFormating(Double doubleNum, Charset charset, int fiel
DecimalFormat df = (DecimalFormat) NumberFormat.getInstance(Locale.ENGLISH);
df.applyPattern(format.toString());
- return textPadding(df.format(doubleNum.doubleValue()).toString(), charset, fieldLength, DBFAlignment.RIGHT, (byte) ' ');
+ return textPadding(df.format(num).toString(), charset, fieldLength, DBFAlignment.RIGHT, (byte) ' ');
}
/**
@@ -236,10 +240,12 @@ public static boolean contains(byte[] array, byte value) {
* @return true if is ascci
*/
public static boolean isPureAscii(String stringToCheck) {
- if (stringToCheck == null) {
+ if (stringToCheck == null || stringToCheck.length() == 0) {
return true;
}
- return ASCII_ENCODER.canEncode(stringToCheck);
+ synchronized (ASCII_ENCODER) {
+ return ASCII_ENCODER.canEncode(stringToCheck);
+ }
}
/**
@@ -255,5 +261,39 @@ public static Object toBoolean(byte t_logical) {
}
return null;
}
+
+ public static byte[] trimRightSpaces(byte[] b_array) {
+ if (b_array == null || b_array.length == 0) {
+ return new byte[0];
+ }
+ int pos = getRightPos(b_array);
+ int length = pos+1;
+ byte[] newBytes = new byte[length];
+ System.arraycopy(b_array, 0, newBytes, 0, length);
+ return newBytes;
+ }
+
+ private static int getRightPos(byte[] b_array) {
+ int pos = b_array.length - 1;
+ while (pos >= 0 && b_array[pos] == (byte)' ') {
+ pos--;
+ }
+ return pos;
+ }
+
+ /**
+ * Closes silently a #{@link java.io.Closeable}.
+ * it can be null or throws an exception, will be ignored.
+ * @param closeable The item to close
+ */
+ public static void close(Closeable closeable) {
+ if (closeable != null) {
+ try {
+ closeable.close();
+ } catch (Exception e) { //NOPMD
+ // nop
+ }
+ }
+ }
}
diff --git a/src/main/java/com/linuxense/javadbf/DBFWriter.java b/src/main/java/com/linuxense/javadbf/DBFWriter.java
index 366ed3d9..4ea6b252 100644
--- a/src/main/java/com/linuxense/javadbf/DBFWriter.java
+++ b/src/main/java/com/linuxense/javadbf/DBFWriter.java
@@ -110,6 +110,9 @@ public DBFWriter(File dbfFile, Charset charset) throws DBFException {
*/
if (dbfFile.length() == 0) {
if (charset != null) {
+ if (DBFCharsetHelper.getDBFCodeForCharset(charset) == 0) {
+ throw new DBFException("Unssuported charset " + charset);
+ }
setCharset(charset);
this.header.setUsedCharset(charset);
}
@@ -123,9 +126,15 @@ public DBFWriter(File dbfFile, Charset charset) throws DBFException {
this.header.read(this.raf, charset);
setCharset(this.header.getUsedCharset());
- /* position file pointer at the end of the raf */
+ // position file pointer at the end of the raf
// to ignore the END_OF_DATA byte at EoF
- this.raf.seek(this.raf.length() - 1);
+ // Only if there are records (ignore if the file is only the header)
+ if (this.raf.length() > header.headerLength) {
+ this.raf.seek(this.raf.length() - 1);
+ }
+ else {
+ this.raf.seek(this.raf.length());
+ }
} catch (FileNotFoundException e) {
throw new DBFException("Specified file is not found. " + e.getMessage(), e);
} catch (IOException e) {
@@ -310,7 +319,8 @@ private void writeRecord(DataOutput dataOutput, Object[] objectArray) throws IOE
if (objectArray[j] != null) {
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTime((Date) objectArray[j]);
- dataOutput.write(String.valueOf(calendar.get(Calendar.YEAR)).getBytes(StandardCharsets.US_ASCII));
+ dataOutput.write(DBFUtils.textPadding(String.valueOf(calendar.get(Calendar.YEAR)),
+ StandardCharsets.US_ASCII, 4, DBFAlignment.RIGHT, (byte) '0'));
dataOutput.write(DBFUtils.textPadding(String.valueOf(calendar.get(Calendar.MONTH) + 1),
StandardCharsets.US_ASCII, 2, DBFAlignment.RIGHT, (byte) '0'));
dataOutput.write(DBFUtils.textPadding(String.valueOf(calendar.get(Calendar.DAY_OF_MONTH)),
@@ -351,4 +361,11 @@ private void writeRecord(DataOutput dataOutput, Object[] objectArray) throws IOE
}
}
}
+ @Override
+ public void setCharset(Charset charset) {
+ super.setCharset(charset);
+ if (this.header != null) {
+ this.header.setUsedCharset(charset);
+ }
+ }
}
diff --git a/src/test/java/com/linuxense/javadbf/DBFCharsetHelperTest.java b/src/test/java/com/linuxense/javadbf/DBFCharsetHelperTest.java
index 560b6f08..4e123c1e 100644
--- a/src/test/java/com/linuxense/javadbf/DBFCharsetHelperTest.java
+++ b/src/test/java/com/linuxense/javadbf/DBFCharsetHelperTest.java
@@ -87,6 +87,27 @@ public void listEncodings() {
}
}
+
+ @Test
+ public void testRussianAndNordicEncodingsBug35() {
+ /* Russian IBM866 and Nordic ISO865 has changed values.
+ *
+ * Correct values: https://msdn.microsoft.com/en-us/library/8t45x02s(v=vs.80).aspx
+ *
+ */
+
+ // Russian IBM866 0x65
+ Charset russian = Charset.forName("IBM866");
+
+ Assert.assertEquals(0x65, DBFCharsetHelper.getDBFCodeForCharset(russian));
+ Assert.assertEquals(russian, DBFCharsetHelper.getCharsetByByte(0x65));
+
+ // Nordic IBM865 0x66
+
+ Charset nordic = Charset.forName("IBM865");
+ Assert.assertEquals(0x66, DBFCharsetHelper.getDBFCodeForCharset(nordic));
+ Assert.assertEquals(nordic, DBFCharsetHelper.getCharsetByByte(0x66));
+ }
}
diff --git a/src/test/java/com/linuxense/javadbf/DBFReaderTest.java b/src/test/java/com/linuxense/javadbf/DBFReaderTest.java
index bbe8253c..277f7333 100644
--- a/src/test/java/com/linuxense/javadbf/DBFReaderTest.java
+++ b/src/test/java/com/linuxense/javadbf/DBFReaderTest.java
@@ -10,7 +10,7 @@
import org.junit.Assert;
import org.junit.Test;
-import com.linuxsense.javadbf.mocks.FailInputStream;
+import com.linuxense.javadbf.mocks.FailInputStream;
public class DBFReaderTest {
diff --git a/src/test/java/com/linuxense/javadbf/DBFWriterStreamTest.java b/src/test/java/com/linuxense/javadbf/DBFWriterStreamTest.java
index 5bdc88f4..0fb57704 100644
--- a/src/test/java/com/linuxense/javadbf/DBFWriterStreamTest.java
+++ b/src/test/java/com/linuxense/javadbf/DBFWriterStreamTest.java
@@ -6,7 +6,7 @@
import org.junit.Assert;
import org.junit.Test;
-import com.linuxsense.javadbf.mocks.NullOutputStream;
+import com.linuxense.javadbf.mocks.NullOutputStream;
public class DBFWriterStreamTest {
diff --git a/src/test/java/com/linuxense/javadbf/EncodingTest.java b/src/test/java/com/linuxense/javadbf/EncodingTest.java
index e09684cc..f3f5e374 100644
--- a/src/test/java/com/linuxense/javadbf/EncodingTest.java
+++ b/src/test/java/com/linuxense/javadbf/EncodingTest.java
@@ -1,12 +1,14 @@
package com.linuxense.javadbf;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
@@ -152,4 +154,37 @@ public void testSetEncoding() throws DBFException {
Assert.assertEquals(StandardCharsets.ISO_8859_1, writer.getCharset());
}
}
+
+ @Test
+ public void testSetEncodingCP866() throws DBFException {
+ DBFWriter writer = null;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try {
+ writer = new DBFWriter();
+ writer.setCharactersetName("CP866");
+ DBFField fields[] = new DBFField[1];
+
+ fields[0] = new DBFField();
+ fields[0].setName("emp_name");
+ fields[0].setType(DBFDataType.CHARACTER);
+ fields[0].setFieldLength(10);
+ writer.setFields(fields);
+ writer.addRecord(new Object[] { "Simon" });
+ writer.addRecord(new Object[] { "Julian"});
+ writer.write(baos);
+ }
+ finally {
+ DBFUtils.close(writer);
+ }
+ byte[] data = baos.toByteArray();
+ Assert.assertEquals(0x65, data[29]);
+ }
+
+ @Test
+ public void testSetEncodingCP866StringConversion() throws DBFException {
+ Charset charset = Charset.forName("CP866");
+ String charsetString = charset.toString().toLowerCase();
+
+ Assert.assertEquals("ibm866", charsetString);
+ }
}
diff --git a/src/test/java/com/linuxense/javadbf/FixtureCp1251Test.java b/src/test/java/com/linuxense/javadbf/FixtureCp1251Test.java
new file mode 100644
index 00000000..b3e85966
--- /dev/null
+++ b/src/test/java/com/linuxense/javadbf/FixtureCp1251Test.java
@@ -0,0 +1,102 @@
+/*
+
+(C) Copyright 2017 Alberto Fernández
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 3.0 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library. If not, see .
+
+*/
+package com.linuxense.javadbf;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class FixtureCp1251Test {
+ @Test
+ public void test8b() throws Exception {
+ File file = new File("src/test/resources/fixtures/cp1251.dbf");
+ DBFReader reader = null;
+ InputStream is = null;
+ try {
+ is = new FileInputStream(file);
+ reader = new DBFReader(is);
+
+ DBFHeader header = reader.getHeader();
+
+ Assert.assertNotNull(header);
+ Assert.assertEquals(2, header.fieldArray.length);
+
+ Assert.assertEquals("RN", header.fieldArray[0].getName());
+ Assert.assertEquals(DBFDataType.NUMERIC, header.fieldArray[0].getType());
+ Assert.assertEquals(0, header.fieldArray[0].getDecimalCount());
+ Assert.assertEquals(4, header.fieldArray[0].getFieldLength());
+
+ Assert.assertEquals("NAME", header.fieldArray[1].getName());
+ Assert.assertEquals(DBFDataType.CHARACTER, header.fieldArray[1].getType());
+ Assert.assertEquals(0, header.fieldArray[1].getDecimalCount());
+ Assert.assertEquals(100, header.fieldArray[1].getFieldLength());
+
+
+
+ Assert.assertEquals(4, header.numberOfRecords);
+
+
+ Object[] row = null;
+
+ row = reader.nextRecord();
+ Assert.assertEquals(1, ((Number) row[0]).intValue());
+ Assert.assertEquals("àìáóëàòîðíî-ïîëèêëèíè÷åñêîå", ((String)row[1]).trim());
+
+ row = reader.nextRecord();
+ Assert.assertEquals(2, ((Number) row[0]).intValue());
+ Assert.assertEquals("áîëüíè÷íîå", ((String)row[1]).trim());
+
+ row = reader.nextRecord();
+ Assert.assertEquals(3, ((Number) row[0]).intValue());
+ Assert.assertEquals("ÍÈÈ", ((String)row[1]).trim());
+
+ row = reader.nextRecord();
+ Assert.assertEquals(4, ((Number) row[0]).intValue());
+ Assert.assertEquals("îáðàçîâàòåëüíîå ìåäèöèíñêîå ó÷ðåæäåíèå", ((String)row[1]).trim());
+
+ row = reader.nextRecord();
+ Assert.assertNull(row);
+
+
+
+ } finally {
+ DBFUtils.close(is);
+ }
+
+ }
+}
+
+
+/*
+
+Database: cp1251.dbf
+Type: (30) Visual FoxPro
+Memo File: false
+Records: 4
+
+Fields:
+Name Type Length Decimal
+------------------------------------------------------------------------------
+RN N 4 0
+NAME C 100 0
+
+*/
\ No newline at end of file
diff --git a/src/test/java/com/linuxense/javadbf/FixtureDBase03Test.java b/src/test/java/com/linuxense/javadbf/FixtureDBase03Test.java
new file mode 100644
index 00000000..01ce0b60
--- /dev/null
+++ b/src/test/java/com/linuxense/javadbf/FixtureDBase03Test.java
@@ -0,0 +1,135 @@
+/*
+
+(C) Copyright 2017 Alberto Fernández
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 3.0 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library. If not, see .
+
+*/
+package com.linuxense.javadbf;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.linuxense.javadbf.testutils.AssertUtils;
+import com.linuxense.javadbf.testutils.DbfToTxtTest;
+
+public class FixtureDBase03Test {
+ @Test
+ public void test8b() throws Exception {
+ File file = new File("src/test/resources/fixtures/dbase_03.dbf");
+ DBFReader reader = null;
+ InputStream is = null;
+ try {
+ is = new FileInputStream(file);
+ reader = new DBFReader(is);
+
+ DBFHeader header = reader.getHeader();
+ Assert.assertNotNull(header);
+ Assert.assertEquals(31, header.fieldArray.length);
+ Assert.assertEquals(14, header.numberOfRecords);
+ DBFField []fieldArray = header.fieldArray;
+
+ int i = 0;
+
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "Point_ID" , DBFDataType.fromCode((byte) 'C'), 12, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "Type" , DBFDataType.fromCode((byte) 'C'), 20, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "Shape" , DBFDataType.fromCode((byte) 'C'), 20, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "Circular_D", DBFDataType.fromCode((byte) 'C'), 20, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "Non_circul", DBFDataType.fromCode((byte) 'C'), 60, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "Flow_prese", DBFDataType.fromCode((byte) 'C'), 20, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "Condition" , DBFDataType.fromCode((byte) 'C'), 20, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "Comments" , DBFDataType.fromCode((byte) 'C'), 60, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "Date_Visit", DBFDataType.fromCode((byte) 'D'), 8 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "Time" , DBFDataType.fromCode((byte) 'C'), 10, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "Max_PDOP" , DBFDataType.fromCode((byte) 'N'), 5 , 1);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "Max_HDOP" , DBFDataType.fromCode((byte) 'N'), 5 , 1);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "Corr_Type" , DBFDataType.fromCode((byte) 'C'), 36, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "Rcvr_Type" , DBFDataType.fromCode((byte) 'C'), 36, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "GPS_Date" , DBFDataType.fromCode((byte) 'D'), 8 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "GPS_Time" , DBFDataType.fromCode((byte) 'C'), 10, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "Update_Sta", DBFDataType.fromCode((byte) 'C'), 36, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "Feat_Name" , DBFDataType.fromCode((byte) 'C'), 20, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "Datafile" , DBFDataType.fromCode((byte) 'C'), 20, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "Unfilt_Pos", DBFDataType.fromCode((byte) 'N'), 10, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "Filt_Pos" , DBFDataType.fromCode((byte) 'N'), 10, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "Data_Dicti", DBFDataType.fromCode((byte) 'C'), 20, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "GPS_Week" , DBFDataType.fromCode((byte) 'N'), 6 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "GPS_Second", DBFDataType.fromCode((byte) 'N'), 12, 3);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "GPS_Height", DBFDataType.fromCode((byte) 'N'), 16, 3);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "Vert_Prec" , DBFDataType.fromCode((byte) 'N'), 16, 1);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "Horz_Prec" , DBFDataType.fromCode((byte) 'N'), 16, 1);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "Std_Dev" , DBFDataType.fromCode((byte) 'N'), 16, 6);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "Northing" , DBFDataType.fromCode((byte) 'N'), 16, 3);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "Easting" , DBFDataType.fromCode((byte) 'N'), 16, 3);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "Point_ID" , DBFDataType.fromCode((byte) 'N'), 9 , 0);
+
+ DbfToTxtTest.export(reader, File.createTempFile("javadbf-test", ".txt"));
+
+ } finally {
+ DBFUtils.close(is);
+ }
+
+ }
+}
+
+
+
+
+/*
+
+Database: dbase_03.dbf
+Type: (03) dBase III without memo file
+Memo File: false
+Records: 14
+
+Fields:
+Name Type Length Decimal
+------------------------------------------------------------------------------
+Point_ID C 12 0
+Type C 20 0
+Shape C 20 0
+Circular_D C 20 0
+Non_circul C 60 0
+Flow_prese C 20 0
+Condition C 20 0
+Comments C 60 0
+Date_Visit D 8 0
+Time C 10 0
+Max_PDOP N 5 1
+Max_HDOP N 5 1
+Corr_Type C 36 0
+Rcvr_Type C 36 0
+GPS_Date D 8 0
+GPS_Time C 10 0
+Update_Sta C 36 0
+Feat_Name C 20 0
+Datafile C 20 0
+Unfilt_Pos N 10 0
+Filt_Pos N 10 0
+Data_Dicti C 20 0
+GPS_Week N 6 0
+GPS_Second N 12 3
+GPS_Height N 16 3
+Vert_Prec N 16 1
+Horz_Prec N 16 1
+Std_Dev N 16 6
+Northing N 16 3
+Easting N 16 3
+Point_ID N 9 0
+
+*/
\ No newline at end of file
diff --git a/src/test/java/com/linuxense/javadbf/FixtureDBase30Test.java b/src/test/java/com/linuxense/javadbf/FixtureDBase30Test.java
new file mode 100644
index 00000000..17d9200c
--- /dev/null
+++ b/src/test/java/com/linuxense/javadbf/FixtureDBase30Test.java
@@ -0,0 +1,206 @@
+/*
+
+(C) Copyright 2017 Alberto Fernández
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 3.0 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library. If not, see .
+
+*/
+package com.linuxense.javadbf;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.linuxense.javadbf.testutils.AssertUtils;
+import com.linuxense.javadbf.testutils.DbfToTxtTest;
+
+public class FixtureDBase30Test {
+
+ @Test
+ public void test30 () throws Exception {
+ File file = new File("src/test/resources/fixtures/dbase_30.dbf");
+ DBFReader reader = null;
+ InputStream is = null;
+ try {
+ is = new FileInputStream(file);
+ reader = new DBFReader(is);
+
+ DBFHeader header = reader.getHeader();
+ Assert.assertNotNull(header);
+ Assert.assertEquals(145, header.fieldArray.length);
+ Assert.assertEquals(34, header.numberOfRecords);
+ DBFField []fieldArray = header.fieldArray;
+
+ int i = 0;
+
+
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "ACCESSNO", DBFDataType.fromCode((byte) 'C'), 15 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "ACQVALUE", DBFDataType.fromCode((byte) 'N'), 12 , 2);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "APPNOTES", DBFDataType.fromCode((byte) 'M'), 4 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "APPRAISOR", DBFDataType.fromCode((byte) 'C'), 75 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "CABINET", DBFDataType.fromCode((byte) 'C'), 25 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "CAPTION", DBFDataType.fromCode((byte) 'C'), 30 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "CAT", DBFDataType.fromCode((byte) 'C'), 1 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "CATBY", DBFDataType.fromCode((byte) 'C'), 25 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "CATDATE", DBFDataType.fromCode((byte) 'D'), 8 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "CATTYPE", DBFDataType.fromCode((byte) 'C'), 15 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "CLASSES", DBFDataType.fromCode((byte) 'M'), 4 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "COLLECTION", DBFDataType.fromCode((byte) 'C'), 75 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "CONDDATE", DBFDataType.fromCode((byte) 'D'), 8 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "CONDEXAM", DBFDataType.fromCode((byte) 'C'), 25 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "CONDITION", DBFDataType.fromCode((byte) 'C'), 35 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "CONDNOTES", DBFDataType.fromCode((byte) 'M'), 4 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "CONTAINER", DBFDataType.fromCode((byte) 'C'), 40 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "COPYRIGHT", DBFDataType.fromCode((byte) 'M'), 4 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "CREATOR", DBFDataType.fromCode((byte) 'C'), 80 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "CREDIT", DBFDataType.fromCode((byte) 'M'), 4 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "CURVALMAX", DBFDataType.fromCode((byte) 'N'), 12 , 2);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "CURVALUE", DBFDataType.fromCode((byte) 'N'), 12 , 2);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "DATASET", DBFDataType.fromCode((byte) 'C'), 15 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "DATE", DBFDataType.fromCode((byte) 'C'), 50 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "DESCRIP", DBFDataType.fromCode((byte) 'M'), 4 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "DIMNOTES", DBFDataType.fromCode((byte) 'M'), 4 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "DISPVALUE", DBFDataType.fromCode((byte) 'C'), 10 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "DRAWER", DBFDataType.fromCode((byte) 'C'), 20 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "EARLYDATE", DBFDataType.fromCode((byte) 'N'), 4 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "EVENT", DBFDataType.fromCode((byte) 'C'), 80 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "EXHIBITID", DBFDataType.fromCode((byte) 'C'), 36 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "EXHIBITNO", DBFDataType.fromCode((byte) 'N'), 7 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "EXHLABEL1", DBFDataType.fromCode((byte) 'M'), 4 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "EXHLABEL2", DBFDataType.fromCode((byte) 'M'), 4 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "EXHLABEL3", DBFDataType.fromCode((byte) 'M'), 4 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "EXHLABEL4", DBFDataType.fromCode((byte) 'M'), 4 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "EXHSTART", DBFDataType.fromCode((byte) 'D'), 8 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "FILMSIZE", DBFDataType.fromCode((byte) 'C'), 35 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "FLAGDATE", DBFDataType.fromCode((byte) 'T'), 8 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "FLAGNOTES", DBFDataType.fromCode((byte) 'M'), 4 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "FLAGREASON", DBFDataType.fromCode((byte) 'C'), 20 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "FRAME", DBFDataType.fromCode((byte) 'C'), 75 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "FRAMENO", DBFDataType.fromCode((byte) 'C'), 25 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "GPARENT", DBFDataType.fromCode((byte) 'C'), 45 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "HOMELOC", DBFDataType.fromCode((byte) 'C'), 60 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "IMAGEFILE", DBFDataType.fromCode((byte) 'C'), 60 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "IMAGENO", DBFDataType.fromCode((byte) 'N'), 3 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "INSCOMP", DBFDataType.fromCode((byte) 'C'), 30 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "INSDATE", DBFDataType.fromCode((byte) 'D'), 8 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "INSPHONE", DBFDataType.fromCode((byte) 'C'), 25 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "INSPREMIUM", DBFDataType.fromCode((byte) 'C'), 20 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "INSREP", DBFDataType.fromCode((byte) 'C'), 30 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "INSVALUE", DBFDataType.fromCode((byte) 'N'), 10 , 2);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "INVNBY", DBFDataType.fromCode((byte) 'C'), 25 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "INVNDATE", DBFDataType.fromCode((byte) 'D'), 8 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "LATEDATE", DBFDataType.fromCode((byte) 'N'), 4 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "LEGAL", DBFDataType.fromCode((byte) 'M'), 4 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "LOANCOND", DBFDataType.fromCode((byte) 'M'), 4 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "LOANDATE", DBFDataType.fromCode((byte) 'D'), 8 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "LOANDUE", DBFDataType.fromCode((byte) 'D'), 8 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "LOANID", DBFDataType.fromCode((byte) 'C'), 36 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "LOANINNO", DBFDataType.fromCode((byte) 'C'), 15 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "MAINTCYCLE", DBFDataType.fromCode((byte) 'C'), 10 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "MAINTDATE", DBFDataType.fromCode((byte) 'D'), 8 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "MAINTNOTE", DBFDataType.fromCode((byte) 'M'), 4 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "MEDIUM", DBFDataType.fromCode((byte) 'C'), 75 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "NEGLOC", DBFDataType.fromCode((byte) 'C'), 60 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "NEGNO", DBFDataType.fromCode((byte) 'C'), 25 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "NOTES", DBFDataType.fromCode((byte) 'M'), 4 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "OBJECTID", DBFDataType.fromCode((byte) 'C'), 25 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "OBJNAME", DBFDataType.fromCode((byte) 'C'), 40 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "OLDNO", DBFDataType.fromCode((byte) 'C'), 25 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "ORIGCOPY", DBFDataType.fromCode((byte) 'C'), 15 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "OTHERNO", DBFDataType.fromCode((byte) 'C'), 25 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "OUTDATE", DBFDataType.fromCode((byte) 'D'), 8 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "PARENT", DBFDataType.fromCode((byte) 'C'), 40 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "PEOPLE", DBFDataType.fromCode((byte) 'M'), 4 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "PLACE", DBFDataType.fromCode((byte) 'C'), 100 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "POLICYNO", DBFDataType.fromCode((byte) 'C'), 20 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "PRINTSIZE", DBFDataType.fromCode((byte) 'C'), 35 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "PROCESS", DBFDataType.fromCode((byte) 'C'), 75 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "PROVENANCE", DBFDataType.fromCode((byte) 'M'), 4 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "PUBNOTES", DBFDataType.fromCode((byte) 'M'), 4 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "RECAS", DBFDataType.fromCode((byte) 'C'), 20 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "RECDATE", DBFDataType.fromCode((byte) 'C'), 10 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "RECFROM", DBFDataType.fromCode((byte) 'C'), 120 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "RELATION", DBFDataType.fromCode((byte) 'C'), 36 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "RELNOTES", DBFDataType.fromCode((byte) 'M'), 4 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "ROOM", DBFDataType.fromCode((byte) 'C'), 25 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "SGFLAG", DBFDataType.fromCode((byte) 'C'), 1 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "SHELF", DBFDataType.fromCode((byte) 'C'), 20 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "SITE", DBFDataType.fromCode((byte) 'C'), 40 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "SITENO", DBFDataType.fromCode((byte) 'C'), 12 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "SLIDENO", DBFDataType.fromCode((byte) 'C'), 25 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "STATUS", DBFDataType.fromCode((byte) 'C'), 20 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "STATUSBY", DBFDataType.fromCode((byte) 'C'), 25 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "STATUSDATE", DBFDataType.fromCode((byte) 'D'), 8 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "STERMS", DBFDataType.fromCode((byte) 'M'), 4 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "STUDIO", DBFDataType.fromCode((byte) 'C'), 60 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "SUBJECTS", DBFDataType.fromCode((byte) 'M'), 4 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "TCABINET", DBFDataType.fromCode((byte) 'C'), 25 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "TCONTAINER", DBFDataType.fromCode((byte) 'C'), 40 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "TDRAWER", DBFDataType.fromCode((byte) 'C'), 20 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "TEMPAUTHOR", DBFDataType.fromCode((byte) 'C'), 25 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "TEMPBY", DBFDataType.fromCode((byte) 'C'), 25 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "TEMPDATE", DBFDataType.fromCode((byte) 'D'), 8 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "TEMPLOC", DBFDataType.fromCode((byte) 'C'), 60 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "TEMPNOTES", DBFDataType.fromCode((byte) 'M'), 4 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "TEMPREASON", DBFDataType.fromCode((byte) 'C'), 50 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "TEMPUNTIL", DBFDataType.fromCode((byte) 'C'), 10 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "TITLE", DBFDataType.fromCode((byte) 'M'), 4 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "TITLESORT", DBFDataType.fromCode((byte) 'C'), 100 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "TROOM", DBFDataType.fromCode((byte) 'C'), 25 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "TSHELF", DBFDataType.fromCode((byte) 'C'), 20 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "TWALL", DBFDataType.fromCode((byte) 'C'), 20 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "UDF1", DBFDataType.fromCode((byte) 'C'), 75 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "UDF10", DBFDataType.fromCode((byte) 'C'), 75 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "UDF11", DBFDataType.fromCode((byte) 'C'), 20 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "UDF12", DBFDataType.fromCode((byte) 'C'), 20 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "UDF13", DBFDataType.fromCode((byte) 'N'), 12 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "UDF14", DBFDataType.fromCode((byte) 'N'), 12 , 2);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "UDF15", DBFDataType.fromCode((byte) 'N'), 12 , 2);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "UDF16", DBFDataType.fromCode((byte) 'N'), 12 , 3);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "UDF17", DBFDataType.fromCode((byte) 'N'), 12 , 3);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "UDF18", DBFDataType.fromCode((byte) 'D'), 8 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "UDF19", DBFDataType.fromCode((byte) 'D'), 8 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "UDF20", DBFDataType.fromCode((byte) 'D'), 8 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "UDF21", DBFDataType.fromCode((byte) 'M'), 4 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "UDF22", DBFDataType.fromCode((byte) 'M'), 4 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "UDF2", DBFDataType.fromCode((byte) 'C'), 75 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "UDF3", DBFDataType.fromCode((byte) 'C'), 75 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "UDF4", DBFDataType.fromCode((byte) 'C'), 75 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "UDF5", DBFDataType.fromCode((byte) 'C'), 75 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "UDF6", DBFDataType.fromCode((byte) 'C'), 75 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "UDF7", DBFDataType.fromCode((byte) 'C'), 75 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "UDF8", DBFDataType.fromCode((byte) 'C'), 75 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "UDF9", DBFDataType.fromCode((byte) 'C'), 75 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "UPDATED", DBFDataType.fromCode((byte) 'T'), 8 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "UPDATEDBY", DBFDataType.fromCode((byte) 'C'), 25 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "VALUEDATE", DBFDataType.fromCode((byte) 'D'), 8 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "WALL", DBFDataType.fromCode((byte) 'C'), 20 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "WEBINCLUDE", DBFDataType.fromCode((byte) 'L'), 1 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "ZSORTER", DBFDataType.fromCode((byte) 'C'), 69 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "ZSORTERX", DBFDataType.fromCode((byte) 'C'), 44 , 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "PPID", DBFDataType.fromCode((byte) 'C'), 36 , 0);
+
+ DbfToTxtTest.export(reader, File.createTempFile("javadbf-test", ".txt"));
+
+
+ } finally {
+ DBFUtils.close(is);
+ }
+
+ }
+
+}
diff --git a/src/test/java/com/linuxense/javadbf/FixtureDBase31Test.java b/src/test/java/com/linuxense/javadbf/FixtureDBase31Test.java
new file mode 100644
index 00000000..297f0f6d
--- /dev/null
+++ b/src/test/java/com/linuxense/javadbf/FixtureDBase31Test.java
@@ -0,0 +1,95 @@
+/*
+
+(C) Copyright 2017 Alberto Fernández
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 3.0 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library. If not, see .
+
+*/
+package com.linuxense.javadbf;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.linuxense.javadbf.testutils.AssertUtils;
+import com.linuxense.javadbf.testutils.DbfToTxtTest;
+
+public class FixtureDBase31Test {
+
+ @Test
+ public void test31 () throws Exception {
+ File file = new File("src/test/resources/fixtures/dbase_31.dbf");
+ DBFReader reader = null;
+ java.io.InputStream is = null;
+ try {
+ is = new BufferedInputStream(new FileInputStream(file));
+ reader = new DBFReader(is);
+
+ DBFHeader header = reader.getHeader();
+ Assert.assertNotNull(header);
+ Assert.assertEquals(11, header.fieldArray.length);
+ Assert.assertEquals(77, header.numberOfRecords);
+ DBFField []fieldArray = header.fieldArray;
+
+ int i = 0;
+
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "PRODUCTID", DBFDataType.fromCode((byte) 'I'), 4 ,0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "PRODUCTNAM", DBFDataType.fromCode((byte) 'C'), 40 ,0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "SUPPLIERID", DBFDataType.fromCode((byte) 'I'), 4 ,0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "CATEGORYID", DBFDataType.fromCode((byte) 'I'), 4 ,0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "QUANTITYPE", DBFDataType.fromCode((byte) 'C'), 20 ,0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "UNITPRICE", DBFDataType.fromCode((byte) 'Y'), 8 ,4);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "UNITSINSTO", DBFDataType.fromCode((byte) 'I'), 4 ,0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "UNITSONORD", DBFDataType.fromCode((byte) 'I'), 4 ,0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "REORDERLEV", DBFDataType.fromCode((byte) 'I'), 4 ,0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "DISCONTINU", DBFDataType.fromCode((byte) 'L'), 1 ,0);
+// AssertUtils.assertColumnDefinition(fieldArray[i++], "_NullFlags", DBFDataType.NULL_FLAGS, 1 ,0);
+
+
+ DbfToTxtTest.export(reader, File.createTempFile("javadbf-test", ".txt"));
+
+ } finally {
+ DBFUtils.close(is);
+ }
+
+ }
+
+}
+
+
+
+/*
+ Database: dbase_31.dbf
+Type: (31) Visual FoxPro with AutoIncrement field
+Memo File: false
+Records: 77
+
+Fields:
+Name Type Length Decimal
+------------------------------------------------------------------------------
+PRODUCTID I 4 0
+PRODUCTNAM C 40 0
+SUPPLIERID I 4 0
+CATEGORYID I 4 0
+QUANTITYPE C 20 0
+UNITPRICE Y 8 4
+UNITSINSTO I 4 0
+UNITSONORD I 4 0
+REORDERLEV I 4 0
+DISCONTINU L 1 0
+_NullFlags 0 1 0
+*/
diff --git a/src/test/java/com/linuxense/javadbf/FixtureDBase7Test.java b/src/test/java/com/linuxense/javadbf/FixtureDBase7Test.java
new file mode 100644
index 00000000..909b080b
--- /dev/null
+++ b/src/test/java/com/linuxense/javadbf/FixtureDBase7Test.java
@@ -0,0 +1,78 @@
+/*
+
+(C) Copyright 2017 Alberto Fernández
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 3.0 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library. If not, see .
+
+*/
+package com.linuxense.javadbf;
+
+import static com.linuxense.javadbf.testutils.DateUtils.createDate;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.linuxense.javadbf.testutils.AssertUtils;
+
+public class FixtureDBase7Test {
+
+ @Test
+ @Ignore("dbase 7 not supported in 0.x")
+ public void test7 () throws Exception {
+ File file = new File("src/test/resources/fixtures/dbase_7.dbf");
+ InputStream is = null;
+ DBFReader reader = null;
+ try {
+ is = new BufferedInputStream(new FileInputStream(file));
+ reader = new DBFReader(is);
+
+ DBFHeader header = reader.getHeader();
+ Assert.assertNotNull(header);
+ Assert.assertEquals(4, header.fieldArray.length);
+ Assert.assertEquals(3, header.numberOfRecords);
+ DBFField []fieldArray = header.fieldArray;
+ AssertUtils.assertColumnDefinition(fieldArray[0], "ACTION", DBFDataType.MEMO, 10, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[1], "DATE", DBFDataType.DATE, 8, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[2], "USER", DBFDataType.CHARACTER, 20, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[3], "ID", DBFDataType.CHARACTER, 12, 0);
+
+ Object[] row = null;
+
+ row = reader.nextRecord();
+ Assert.assertEquals(createDate(2015,2,23), row[1]);
+ Assert.assertEquals("DFG", row[2]);
+ Assert.assertEquals("1", row[3]);
+
+ row = reader.nextRecord();
+ Assert.assertEquals(createDate(2013,1,31), row[1]);
+ Assert.assertEquals("GFS", row[2]);
+ Assert.assertEquals("2", row[3]);
+
+ row = reader.nextRecord();
+ Assert.assertEquals(createDate(2014,10,28), row[1]);
+ Assert.assertEquals("HSJ", row[2]);
+ Assert.assertEquals("3", row[3]);
+
+ }
+ finally {
+ DBFUtils.close(is);
+ }
+ }
+}
diff --git a/src/test/java/com/linuxense/javadbf/FixtureDBase83Test.java b/src/test/java/com/linuxense/javadbf/FixtureDBase83Test.java
new file mode 100644
index 00000000..3efdd017
--- /dev/null
+++ b/src/test/java/com/linuxense/javadbf/FixtureDBase83Test.java
@@ -0,0 +1,101 @@
+/*
+
+(C) Copyright 2017 Alberto Fernández
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 3.0 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library. If not, see .
+
+*/
+package com.linuxense.javadbf;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.linuxense.javadbf.testutils.AssertUtils;
+import com.linuxense.javadbf.testutils.DbfToTxtTest;
+
+public class FixtureDBase83Test {
+
+ @Test
+ public void test8b() throws Exception {
+ File file = new File("src/test/resources/fixtures/dbase_83.dbf");
+ InputStream inputStream = null;
+ try {
+ inputStream = new BufferedInputStream(new FileInputStream(file));
+ DBFReader reader = new DBFReader(inputStream);
+// reader.setMemoFile(new File("src/test/resources/fixtures/dbase_83.dbt"));
+
+ DBFHeader header = reader.getHeader();
+ Assert.assertNotNull(header);
+ Assert.assertEquals(15, header.fieldArray.length);
+ Assert.assertEquals(67, header.numberOfRecords);
+
+ DBFField[] fieldArray = header.fieldArray;
+
+ int i = 0;
+
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "ID", DBFDataType.fromCode('N'), 19, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "CATCOUNT", DBFDataType.fromCode('N'), 19, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "AGRPCOUNT", DBFDataType.fromCode('N'), 19, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "PGRPCOUNT", DBFDataType.fromCode('N'), 19, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "ORDER", DBFDataType.fromCode('N'), 19, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "CODE", DBFDataType.fromCode('C'), 50, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "NAME", DBFDataType.fromCode('C'), 100, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "THUMBNAIL", DBFDataType.fromCode('C'), 254, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "IMAGE", DBFDataType.fromCode('C'), 254, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "PRICE", DBFDataType.fromCode('N'), 13, 2);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "COST", DBFDataType.fromCode('N'), 13, 2);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "DESC", DBFDataType.fromCode('M'), 10, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "WEIGHT", DBFDataType.fromCode('N'), 13, 2);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "TAXABLE", DBFDataType.fromCode('L'), 1, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "ACTIVE", DBFDataType.fromCode('L'), 1, 0);
+
+ DbfToTxtTest.export(reader, File.createTempFile("javadbf-test", ".txt"));
+
+ } finally {
+ DBFUtils.close(inputStream);
+ }
+ }
+}
+
+/*
+Database: dbase_83.dbf
+Type: (83) dBase III with memo file
+Memo File: true
+Records: 67
+
+Fields:
+Name Type Length Decimal
+------------------------------------------------------------------------------
+ID N 19 0
+CATCOUNT N 19 0
+AGRPCOUNT N 19 0
+PGRPCOUNT N 19 0
+ORDER N 19 0
+CODE C 50 0
+NAME C 100 0
+THUMBNAIL C 254 0
+IMAGE C 254 0
+PRICE N 13 2
+COST N 13 2
+DESC M 10 0
+WEIGHT N 13 2
+TAXABLE L 1 0
+ACTIVE L 1 0
+
+*/
\ No newline at end of file
diff --git a/src/test/java/com/linuxense/javadbf/FixtureDBase8bTest.java b/src/test/java/com/linuxense/javadbf/FixtureDBase8bTest.java
new file mode 100644
index 00000000..4d0e9724
--- /dev/null
+++ b/src/test/java/com/linuxense/javadbf/FixtureDBase8bTest.java
@@ -0,0 +1,239 @@
+/*
+
+(C) Copyright 2017 Alberto Fernández
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 3.0 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library. If not, see .
+
+*/
+package com.linuxense.javadbf;
+
+import static com.linuxense.javadbf.testutils.DateUtils.createDate;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.Date;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class FixtureDBase8bTest {
+
+ @Test
+ public void test8b() throws Exception {
+ File file = new File("src/test/resources/fixtures/dbase_8b.dbf");
+ DBFReader reader = null;
+ InputStream is = null;
+ try {
+ is = new BufferedInputStream(new FileInputStream(file));
+ reader = new DBFReader(is);
+ reader.setTrimRightSpaces(true);
+
+ DBFHeader header = reader.getHeader();
+ Assert.assertNotNull(header);
+ Assert.assertEquals(6, header.fieldArray.length);
+
+ Assert.assertEquals("CHARACTER", header.fieldArray[0].getName());
+ Assert.assertEquals(DBFDataType.CHARACTER, header.fieldArray[0].getType());
+ Assert.assertEquals(0, header.fieldArray[0].getDecimalCount());
+ Assert.assertEquals(100, header.fieldArray[0].getFieldLength());
+
+ Assert.assertEquals("NUMERICAL", header.fieldArray[1].getName());
+ Assert.assertEquals(DBFDataType.NUMERIC, header.fieldArray[1].getType());
+ Assert.assertEquals(2, header.fieldArray[1].getDecimalCount());
+ Assert.assertEquals(20, header.fieldArray[1].getFieldLength());
+
+ Assert.assertEquals("DATE", header.fieldArray[2].getName());
+ Assert.assertEquals(DBFDataType.DATE, header.fieldArray[2].getType());
+ Assert.assertEquals(0, header.fieldArray[2].getDecimalCount());
+ Assert.assertEquals(8, header.fieldArray[2].getFieldLength());
+
+ Assert.assertEquals("LOGICAL", header.fieldArray[3].getName());
+ Assert.assertEquals(DBFDataType.LOGICAL, header.fieldArray[3].getType());
+ Assert.assertEquals(0, header.fieldArray[3].getDecimalCount());
+ Assert.assertEquals(1, header.fieldArray[3].getFieldLength());
+
+ Assert.assertEquals("FLOAT", header.fieldArray[4].getName());
+ Assert.assertEquals(DBFDataType.FLOATING_POINT, header.fieldArray[4].getType());
+ Assert.assertEquals(18, header.fieldArray[4].getDecimalCount());
+ Assert.assertEquals(20, header.fieldArray[4].getFieldLength());
+
+ Assert.assertEquals("MEMO", header.fieldArray[5].getName());
+ Assert.assertEquals(DBFDataType.MEMO, header.fieldArray[5].getType());
+ Assert.assertEquals(0, header.fieldArray[5].getDecimalCount());
+ Assert.assertEquals(10, header.fieldArray[5].getFieldLength());
+
+ Assert.assertEquals(10, header.numberOfRecords);
+
+
+ Object[] row = null;
+
+
+ row = reader.nextRecord();
+ Assert.assertEquals("One", row[0]);
+ Assert.assertTrue(row[1] instanceof Number);
+ Assert.assertEquals(1, ((Number)row[1]).intValue());
+ Assert.assertTrue(row[2] instanceof Date);
+ Assert.assertEquals(createDate(1970,1,1), row[2]);
+ Assert.assertTrue(row[3] instanceof Boolean);
+ Assert.assertTrue((Boolean) row[3]);
+ Assert.assertTrue(row[4] instanceof Number);
+ Assert.assertEquals(1.23456789012346, ((Number)row[4]).doubleValue(), 0.0001);
+// Assert.assertEquals("First memo\r\n", row[5]);
+
+ row = reader.nextRecord();
+ Assert.assertEquals("Two", row[0]);
+ Assert.assertTrue(row[1] instanceof Number);
+ Assert.assertEquals(2, ((Number)row[1]).intValue());
+ Assert.assertTrue(row[2] instanceof Date);
+ Assert.assertEquals(createDate(1970,12,31), row[2]);
+ Assert.assertTrue(row[3] instanceof Boolean);
+ Assert.assertTrue((Boolean) row[3]);
+ Assert.assertTrue(row[4] instanceof Number);
+ Assert.assertEquals(2.0, ((Number)row[4]).doubleValue(), 0.0001);
+// Assert.assertEquals("Second memo", row[5]);
+
+ row = reader.nextRecord();
+ Assert.assertEquals("Three", row[0]);
+ Assert.assertTrue(row[1] instanceof Number);
+ Assert.assertEquals(3, ((Number)row[1]).intValue());
+ Assert.assertTrue(row[2] instanceof Date);
+ Assert.assertEquals(createDate(1980,1,1), row[2]);
+ Assert.assertNull(row[3]);
+ Assert.assertTrue(row[4] instanceof Number);
+ Assert.assertEquals(3.0, ((Number)row[4]).doubleValue(), 0.0001);
+// Assert.assertEquals("Thierd memo", row[5]);
+
+ row = reader.nextRecord();
+ Assert.assertEquals("Four", row[0]);
+ Assert.assertTrue(row[1] instanceof Number);
+ Assert.assertEquals(4, ((Number)row[1]).intValue());
+ Assert.assertTrue(row[2] instanceof Date);
+ Assert.assertEquals(createDate(1900,1,1), row[2]);
+ Assert.assertNull(row[3]);
+ Assert.assertTrue(row[4] instanceof Number);
+ Assert.assertEquals(4.0, ((Number)row[4]).doubleValue(), 0.0001);
+// Assert.assertEquals("Fourth memo", row[5]);
+
+ row = reader.nextRecord();
+ Assert.assertEquals("Five", row[0]);
+ Assert.assertTrue(row[1] instanceof Number);
+ Assert.assertEquals(5, ((Number)row[1]).intValue());
+ Assert.assertTrue(row[2] instanceof Date);
+ Assert.assertEquals(createDate(1900,12,31), row[2]);
+ Assert.assertNull(row[3]);
+ Assert.assertTrue(row[4] instanceof Number);
+ Assert.assertEquals(5.0, ((Number)row[4]).doubleValue(), 0.0001);
+// Assert.assertEquals("Fifth memo", row[5]);
+
+ row = reader.nextRecord();
+ Assert.assertEquals("Six", row[0]);
+ Assert.assertTrue(row[1] instanceof Number);
+ Assert.assertEquals(6, ((Number)row[1]).intValue());
+ Assert.assertTrue(row[2] instanceof Date);
+ Assert.assertEquals(createDate(1901,1,1), row[2]);
+ Assert.assertNull(row[3]);
+ Assert.assertTrue(row[4] instanceof Number);
+ Assert.assertEquals(6.0, ((Number)row[4]).doubleValue(), 0.0001);
+// Assert.assertEquals("Sixth memo", row[5]);
+
+ row = reader.nextRecord();
+ Assert.assertEquals("Seven", row[0]);
+ Assert.assertTrue(row[1] instanceof Number);
+ Assert.assertEquals(7, ((Number)row[1]).intValue());
+ Assert.assertTrue(row[2] instanceof Date);
+ Assert.assertEquals(createDate(1999,12,31), row[2]);
+ Assert.assertNull(row[3]);
+ Assert.assertTrue(row[4] instanceof Number);
+ Assert.assertEquals(7.0, ((Number)row[4]).doubleValue(), 0.0001);
+// Assert.assertEquals("Seventh memo", row[5]);
+
+ row = reader.nextRecord();
+ Assert.assertEquals("Eight", row[0]);
+ Assert.assertTrue(row[1] instanceof Number);
+ Assert.assertEquals(8, ((Number)row[1]).intValue());
+ Assert.assertTrue(row[2] instanceof Date);
+ Assert.assertEquals(createDate(1919,12,31), row[2]);
+ Assert.assertNull(row[3]);
+ Assert.assertTrue(row[4] instanceof Number);
+ Assert.assertEquals(8.0, ((Number)row[4]).doubleValue(), 0.0001);
+// Assert.assertEquals("Eigth memo", row[5]);
+
+ row = reader.nextRecord();
+ Assert.assertEquals("Nine", row[0]);
+ Assert.assertTrue(row[1] instanceof Number);
+ Assert.assertEquals(9, ((Number)row[1]).intValue());
+ Assert.assertNull(row[2]);
+ Assert.assertNull(row[3]);
+ Assert.assertNull(row[4]);
+// Assert.assertEquals("Nineth memo", row[5]);
+
+
+ row = reader.nextRecord();
+ Assert.assertEquals("Ten records stored in this database", row[0]);
+ Assert.assertTrue(row[1] instanceof Number);
+ Assert.assertEquals(10, ((Number)row[1]).intValue());
+ Assert.assertNull(row[2]);
+ Assert.assertNull(row[3]);
+ Assert.assertTrue(row[4] instanceof Number);
+ Assert.assertEquals(0.1, ((Number)row[4]).doubleValue(), 0.0001);
+// Assert.assertNull(row[5]);
+
+ row = reader.nextRecord();
+
+ Assert.assertNull(row);
+
+
+
+
+ } finally {
+ DBFUtils.close(is);
+ }
+
+ }
+
+
+}
+
+
+/*
+Database: dbase_8b.dbf
+Type: (8b) dBase IV with memo file
+Memo File: true
+Records: 10
+
+Fields:
+Name Type Length Decimal
+------------------------------------------------------------------------------
+CHARACTER C 100 0
+NUMERICAL N 20 2
+DATE D 8 0
+LOGICAL L 1 0
+FLOAT F 20 18
+MEMO M 10 0
+*/
+
+/*
+One ;1.0;Thu Jan 01 00:00:00 CET 1970;true;1.23456789012346;null;
+Two ;2.0;Thu Dec 31 00:00:00 CET 1970;true;2.0;null;
+Three ;3.0;Tue Jan 01 00:00:00 CET 1980;null;3.0;null;
+Four ;4.0;Mon Jan 01 00:00:00 CET 1900;null;4.0;null;
+Five ;5.0;Mon Dec 31 00:00:00 CET 1900;null;5.0;null;
+Six ;6.0;Tue Jan 01 00:14:44 CET 1901;null;6.0;null;
+Seven ;7.0;Fri Dec 31 00:00:00 CET 1999;null;7.0;null;
+Eight ;8.0;Wed Dec 31 00:00:00 CET 1919;null;8.0;null;
+Nine ;9.0;null;null;null;null;
+Ten records stored in this database ;10.0;null;null;0.1;null;
+*/
\ No newline at end of file
diff --git a/src/test/java/com/linuxense/javadbf/FixtureDBaseF5Test.java b/src/test/java/com/linuxense/javadbf/FixtureDBaseF5Test.java
new file mode 100644
index 00000000..a8a6c84e
--- /dev/null
+++ b/src/test/java/com/linuxense/javadbf/FixtureDBaseF5Test.java
@@ -0,0 +1,194 @@
+/*
+
+(C) Copyright 2017 Alberto Fernández
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 3.0 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library. If not, see .
+
+*/
+package com.linuxense.javadbf;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.linuxense.javadbf.testutils.AssertUtils;
+import com.linuxense.javadbf.testutils.DbfToTxtTest;
+
+public class FixtureDBaseF5Test {
+
+ @Test
+ public void test31() throws Exception {
+ File file = new File("src/test/resources/fixtures/dbase_f5.dbf");
+ InputStream inputStream = null;
+ try {
+ inputStream = new BufferedInputStream(new FileInputStream(file));
+ DBFReader reader = new DBFReader(inputStream);
+// reader.setMemoFile(new File("src/test/resources/fixtures/dbase_f5.fpt"));
+ DBFHeader header = reader.getHeader();
+ Assert.assertNotNull(header);
+ Assert.assertEquals(59, header.fieldArray.length);
+ Assert.assertEquals(975, header.numberOfRecords);
+ DBFField[] fieldArray = header.fieldArray;
+
+ int i = 0;
+
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "NF", DBFDataType.fromCode((byte) 'N'), 5, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "SEXE", DBFDataType.fromCode((byte) 'C'), 1, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "NOM", DBFDataType.fromCode((byte) 'C'), 20, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "COG1", DBFDataType.fromCode((byte) 'C'), 15, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "COG2", DBFDataType.fromCode((byte) 'C'), 15, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "TELEFON", DBFDataType.fromCode((byte) 'C'), 9, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "RENOM", DBFDataType.fromCode((byte) 'C'), 15, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "NFP", DBFDataType.fromCode((byte) 'N'), 5, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "NFM", DBFDataType.fromCode((byte) 'N'), 5, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "ARXN", DBFDataType.fromCode((byte) 'C'), 10, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "DATN", DBFDataType.fromCode((byte) 'D'), 8, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "LLON", DBFDataType.fromCode((byte) 'C'), 15, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "MUNN", DBFDataType.fromCode((byte) 'C'), 15, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "COMN", DBFDataType.fromCode((byte) 'C'), 15, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "PROV", DBFDataType.fromCode((byte) 'C'), 15, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "PAIN", DBFDataType.fromCode((byte) 'C'), 15, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "OFIC", DBFDataType.fromCode((byte) 'C'), 15, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "ARXB", DBFDataType.fromCode((byte) 'C'), 10, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "DATB", DBFDataType.fromCode((byte) 'D'), 8, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "LLOB", DBFDataType.fromCode((byte) 'C'), 15, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "MUNB", DBFDataType.fromCode((byte) 'C'), 15, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "COMB", DBFDataType.fromCode((byte) 'C'), 15, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "PAIB", DBFDataType.fromCode((byte) 'C'), 15, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "DRIB", DBFDataType.fromCode((byte) 'C'), 30, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "INAB", DBFDataType.fromCode((byte) 'C'), 30, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "OFTB", DBFDataType.fromCode((byte) 'C'), 10, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "OFNB", DBFDataType.fromCode((byte) 'C'), 20, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "AXC1", DBFDataType.fromCode((byte) 'C'), 10, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "DTC1", DBFDataType.fromCode((byte) 'D'), 8, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "LLC1", DBFDataType.fromCode((byte) 'C'), 15, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "NFC1", DBFDataType.fromCode((byte) 'N'), 5, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "TCA1", DBFDataType.fromCode((byte) 'C'), 10, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "OTC1", DBFDataType.fromCode((byte) 'C'), 10, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "ONC1", DBFDataType.fromCode((byte) 'C'), 20, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "AXC2", DBFDataType.fromCode((byte) 'C'), 10, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "DTC2", DBFDataType.fromCode((byte) 'D'), 8, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "LLC2", DBFDataType.fromCode((byte) 'C'), 15, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "NFC2", DBFDataType.fromCode((byte) 'N'), 5, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "TCA2", DBFDataType.fromCode((byte) 'C'), 10, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "OTC2", DBFDataType.fromCode((byte) 'C'), 10, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "ONC2", DBFDataType.fromCode((byte) 'C'), 20, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "AXC3", DBFDataType.fromCode((byte) 'C'), 10, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "DTC3", DBFDataType.fromCode((byte) 'D'), 8, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "LLC3", DBFDataType.fromCode((byte) 'C'), 15, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "NFC3", DBFDataType.fromCode((byte) 'N'), 5, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "TCA3", DBFDataType.fromCode((byte) 'C'), 10, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "OTC3", DBFDataType.fromCode((byte) 'C'), 10, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "ONC3", DBFDataType.fromCode((byte) 'C'), 20, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "ARXD", DBFDataType.fromCode((byte) 'C'), 10, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "DATD", DBFDataType.fromCode((byte) 'D'), 8, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "LLOD", DBFDataType.fromCode((byte) 'C'), 15, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "OFTD", DBFDataType.fromCode((byte) 'C'), 10, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "OFND", DBFDataType.fromCode((byte) 'C'), 20, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "OBS1", DBFDataType.fromCode((byte) 'C'), 70, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "OBS2", DBFDataType.fromCode((byte) 'C'), 70, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "OBS3", DBFDataType.fromCode((byte) 'C'), 70, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "OBS4", DBFDataType.fromCode((byte) 'C'), 70, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "OBSE", DBFDataType.fromCode((byte) 'M'), 10, 0);
+ AssertUtils.assertColumnDefinition(fieldArray[i++], "GHD", DBFDataType.fromCode((byte) 'C'), 15, 0);
+
+
+ DbfToTxtTest.export(reader, File.createTempFile("javadbf-test", ".txt"));
+
+ } finally {
+ if (inputStream != null) {
+ inputStream.close();
+ }
+ }
+
+ }
+
+}
+
+/*
+
+
+
+Database: dbase_f5.dbf
+Type: (f5) FoxPro with memo file
+Memo File: true
+Records: 975
+
+Fields:
+Name Type Length Decimal
+------------------------------------------------------------------------------
+NF N 5 0
+SEXE C 1 0
+NOM C 20 0
+COG1 C 15 0
+COG2 C 15 0
+TELEFON C 9 0
+RENOM C 15 0
+NFP N 5 0
+NFM N 5 0
+ARXN C 10 0
+DATN D 8 0
+LLON C 15 0
+MUNN C 15 0
+COMN C 15 0
+PROV C 15 0
+PAIN C 15 0
+OFIC C 15 0
+ARXB C 10 0
+DATB D 8 0
+LLOB C 15 0
+MUNB C 15 0
+COMB C 15 0
+PAIB C 15 0
+DRIB C 30 0
+INAB C 30 0
+OFTB C 10 0
+OFNB C 20 0
+AXC1 C 10 0
+DTC1 D 8 0
+LLC1 C 15 0
+NFC1 N 5 0
+TCA1 C 10 0
+OTC1 C 10 0
+ONC1 C 20 0
+AXC2 C 10 0
+DTC2 D 8 0
+LLC2 C 15 0
+NFC2 N 5 0
+TCA2 C 10 0
+OTC2 C 10 0
+ONC2 C 20 0
+AXC3 C 10 0
+DTC3 D 8 0
+LLC3 C 15 0
+NFC3 N 5 0
+TCA3 C 10 0
+OTC3 C 10 0
+ONC3 C 20 0
+ARXD C 10 0
+DATD D 8 0
+LLOD C 15 0
+OFTD C 10 0
+OFND C 20 0
+OBS1 C 70 0
+OBS2 C 70 0
+OBS3 C 70 0
+OBS4 C 70 0
+OBSE M 10 0
+GHD C 15 0
+*/
diff --git a/src/test/java/com/linuxense/javadbf/UTF8Test.java b/src/test/java/com/linuxense/javadbf/UTF8Test.java
new file mode 100644
index 00000000..b3e0ee41
--- /dev/null
+++ b/src/test/java/com/linuxense/javadbf/UTF8Test.java
@@ -0,0 +1,79 @@
+/*
+
+(C) Copyright 2017 Alberto Fernández
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 3.0 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library. If not, see .
+
+*/
+package com.linuxense.javadbf;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+
+public class UTF8Test {
+
+ public UTF8Test () {
+ super();
+ }
+
+ @Test
+ @Ignore
+ public void testUTF8() throws Exception {
+ String testString = "Cộng hòa xã hội";
+ DBFField fields[] = new DBFField[1];
+ fields[0] = new DBFField();
+ fields[0].setName("abc");
+ fields[0].setType(DBFDataType.CHARACTER);
+ fields[0].setFieldLength(10);
+
+ DBFWriter writer = null;
+ ByteArrayOutputStream fos = null;
+ try {
+ fos = new ByteArrayOutputStream();
+ writer = new DBFWriter(Charset.forName("UTF-8"));
+ writer.setFields(fields);
+ Object rowData[] = new Object[1];
+
+ rowData[0] = testString;
+
+ writer.addRecord(rowData);
+
+ writer.write(fos);
+
+ }
+ finally {
+ DBFUtils.close(fos);
+ }
+ byte[] data = fos.toByteArray();
+
+
+ DBFReader reader = null;
+ InputStream is = null;
+ try {
+ is = new ByteArrayInputStream(data);
+ reader = new DBFReader(is);
+ Object[] rowObjects = reader.nextRecord();
+ Assert.assertEquals(testString, rowObjects[0]);
+ }
+ finally {
+ DBFUtils.close(is);
+ }
+ }
+}
diff --git a/src/test/java/com/linuxense/javadbf/UtilsTest.java b/src/test/java/com/linuxense/javadbf/UtilsTest.java
index 7895a3d6..701d9a02 100644
--- a/src/test/java/com/linuxense/javadbf/UtilsTest.java
+++ b/src/test/java/com/linuxense/javadbf/UtilsTest.java
@@ -8,6 +8,7 @@
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
+import org.junit.Assert;
import org.junit.Test;
@@ -51,7 +52,19 @@ public void testContains () {
}
@Test
public void doubleFormating() {
- // TODO
+ Assert.assertEquals(
+ " 0.00",
+ new String(DBFUtils.doubleFormating(new Double(0.0), Charset.defaultCharset(), 5, 2))
+ );
+
+ Assert.assertEquals(
+ "10.00",
+ new String(DBFUtils.doubleFormating(new Double(10.0), Charset.defaultCharset(), 5, 2))
+ );
+ Assert.assertEquals(
+ " 5.05",
+ new String(DBFUtils.doubleFormating(new Double(5.05), Charset.defaultCharset(), 5, 2))
+ );
}
@Test
public void testLittleEndian() {
diff --git a/src/test/java/com/linuxense/javadbf/bug33_corrupted_sync/Bug33CorruptedSyncModeTest.java b/src/test/java/com/linuxense/javadbf/bug33_corrupted_sync/Bug33CorruptedSyncModeTest.java
new file mode 100644
index 00000000..ede813a2
--- /dev/null
+++ b/src/test/java/com/linuxense/javadbf/bug33_corrupted_sync/Bug33CorruptedSyncModeTest.java
@@ -0,0 +1,68 @@
+package com.linuxense.javadbf.bug33_corrupted_sync;
+
+import java.io.File;
+import java.util.Date;
+
+import org.junit.Test;
+
+import com.linuxense.javadbf.DBFException;
+import com.linuxense.javadbf.DBFWriter;
+import com.linuxense.javadbf.testutils.DbfToTxtTest;
+import com.linuxense.javadbf.testutils.FileUtils;
+
+public class Bug33CorruptedSyncModeTest {
+
+ public Bug33CorruptedSyncModeTest() {
+ super();
+ }
+
+ @Test(expected=DBFException.class)
+ public void testCorruptedFile() throws Exception {
+ String fileName = "src/test/resources/bug-33-corrupted-file-sync-mode/myfileafter-corrupted.dbf";
+ DbfToTxtTest.writeToConsole(new File(fileName));
+ }
+
+
+
+ @Test
+ public void testBug() throws Exception {
+ File tmp = File.createTempFile("example", ".dbf");
+ File orig = new File("src/test/resources/bug-33-corrupted-file-sync-mode/myfilebefore.dbf");
+
+ FileUtils.copyFile(orig, tmp);
+
+ DBFWriter writer = new DBFWriter(tmp);
+
+ Object rowData[] = new Object[21];
+ rowData[0] = 702;
+ rowData[1] = "114";
+ rowData[2] = "57272";
+ rowData[3] = new Date(1493676000000L);// "Tue May 02 00:00:00 CEST 2017"
+ rowData[4] = "11044";
+ rowData[5] = "140-01";
+ rowData[6] = "AD";
+ rowData[7] = "";
+ rowData[8] = "";
+ rowData[9] = 80;
+ rowData[10] = "09";
+ rowData[11] = "LPG";
+ rowData[12] = new Double(0);
+ rowData[13] = new Double(0);
+ rowData[14] = new Double(3);
+ rowData[15] = new Double(0);
+ rowData[16] = new Double(0);
+ rowData[17] = new Double(0);
+ rowData[18] = new Double(0);
+ rowData[19] = new Double(0);
+ rowData[20] = "";
+
+ writer.addRecord(rowData);
+
+ writer.close();
+
+ DbfToTxtTest.writeToConsole(tmp);
+ }
+
+
+
+}
diff --git a/src/test/java/com/linuxense/javadbf/bug46_zero_field_count/ZeroFieldCountTest.java b/src/test/java/com/linuxense/javadbf/bug46_zero_field_count/ZeroFieldCountTest.java
new file mode 100644
index 00000000..96ccb4cf
--- /dev/null
+++ b/src/test/java/com/linuxense/javadbf/bug46_zero_field_count/ZeroFieldCountTest.java
@@ -0,0 +1,37 @@
+package com.linuxense.javadbf.bug46_zero_field_count;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.linuxense.javadbf.DBFReader;
+import com.linuxense.javadbf.DBFUtils;
+
+public class ZeroFieldCountTest {
+
+ public ZeroFieldCountTest() {
+ super();
+ }
+
+ @Test
+ public void test () throws Exception {
+ DBFReader dbfReader = null;
+ InputStream in = null;
+ File input = new File ("src/test/resources/bug-46-zero_field_count/a3.dbf");
+ try {
+ in = new BufferedInputStream(new FileInputStream(input));
+ dbfReader = new DBFReader(in);
+ int count = dbfReader.getFieldCount();
+ System.out.println("" + dbfReader.toString());
+ Assert.assertEquals(17, count);
+ }
+ finally {
+ DBFUtils.close(in);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/java/com/linuxense/javadbf/bug_dates/BugDatesTest.java b/src/test/java/com/linuxense/javadbf/bug_dates/BugDatesTest.java
new file mode 100644
index 00000000..b2fdfb63
--- /dev/null
+++ b/src/test/java/com/linuxense/javadbf/bug_dates/BugDatesTest.java
@@ -0,0 +1,57 @@
+package com.linuxense.javadbf.bug_dates;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.sql.Timestamp;
+import java.util.GregorianCalendar;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.linuxense.javadbf.DBFDataType;
+import com.linuxense.javadbf.DBFField;
+import com.linuxense.javadbf.DBFReader;
+import com.linuxense.javadbf.DBFWriter;
+
+public class BugDatesTest {
+
+ public BugDatesTest() {
+ super();
+ }
+
+ @Test
+ public void test1() throws Exception {
+ File dbfFile = File.createTempFile("dates", ".dbf");
+ try {
+ DBFWriter dbfWriter = new DBFWriter();
+ DBFField field = new DBFField();
+ field.setName("date"); // give a name to the field
+ field.setType(DBFDataType.DATE); // and set its type
+ dbfWriter.setFields(new DBFField[] {field});
+ GregorianCalendar calendar = new GregorianCalendar(2,1,1);
+ Timestamp date = new Timestamp(calendar.getTime().getTime());
+ dbfWriter.addRecord(new Object[] {date});
+
+ OutputStream os = new FileOutputStream(dbfFile);
+ dbfWriter.write(os);
+ dbfWriter.close();
+ os.close();
+
+
+ InputStream is = new FileInputStream(dbfFile);
+ DBFReader reader = new DBFReader(is);
+ Object[] o = reader.nextRecord();
+ is.close();
+ Object value = o[0];
+ System.out.println(value);
+ Assert.assertEquals(calendar.getTime(), value);
+ }
+ finally {
+ dbfFile.delete();
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/java/com/linuxsense/javadbf/mocks/FailInputStream.java b/src/test/java/com/linuxense/javadbf/mocks/FailInputStream.java
similarity index 84%
rename from src/test/java/com/linuxsense/javadbf/mocks/FailInputStream.java
rename to src/test/java/com/linuxense/javadbf/mocks/FailInputStream.java
index 14a34393..b0cc8998 100644
--- a/src/test/java/com/linuxsense/javadbf/mocks/FailInputStream.java
+++ b/src/test/java/com/linuxense/javadbf/mocks/FailInputStream.java
@@ -1,4 +1,4 @@
-package com.linuxsense.javadbf.mocks;
+package com.linuxense.javadbf.mocks;
import java.io.IOException;
import java.io.InputStream;
diff --git a/src/test/java/com/linuxsense/javadbf/mocks/FailOutputStream.java b/src/test/java/com/linuxense/javadbf/mocks/FailOutputStream.java
similarity index 85%
rename from src/test/java/com/linuxsense/javadbf/mocks/FailOutputStream.java
rename to src/test/java/com/linuxense/javadbf/mocks/FailOutputStream.java
index 85195c91..da0c01e3 100644
--- a/src/test/java/com/linuxsense/javadbf/mocks/FailOutputStream.java
+++ b/src/test/java/com/linuxense/javadbf/mocks/FailOutputStream.java
@@ -1,4 +1,4 @@
-package com.linuxsense.javadbf.mocks;
+package com.linuxense.javadbf.mocks;
import java.io.IOException;
import java.io.OutputStream;
diff --git a/src/test/java/com/linuxsense/javadbf/mocks/NullOutputStream.java b/src/test/java/com/linuxense/javadbf/mocks/NullOutputStream.java
similarity index 96%
rename from src/test/java/com/linuxsense/javadbf/mocks/NullOutputStream.java
rename to src/test/java/com/linuxense/javadbf/mocks/NullOutputStream.java
index 158b107f..ea1d1cca 100644
--- a/src/test/java/com/linuxsense/javadbf/mocks/NullOutputStream.java
+++ b/src/test/java/com/linuxense/javadbf/mocks/NullOutputStream.java
@@ -1,4 +1,4 @@
-package com.linuxsense.javadbf.mocks;
+package com.linuxense.javadbf.mocks;
import java.io.IOException;
import java.io.OutputStream;
diff --git a/src/test/java/com/linuxense/javadbf/testutils/AssertUtils.java b/src/test/java/com/linuxense/javadbf/testutils/AssertUtils.java
new file mode 100644
index 00000000..8aa8c1e8
--- /dev/null
+++ b/src/test/java/com/linuxense/javadbf/testutils/AssertUtils.java
@@ -0,0 +1,38 @@
+/*
+
+(C) Copyright 2017 Alberto Fernández
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 3.0 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library. If not, see .
+
+*/
+
+package com.linuxense.javadbf.testutils;
+
+
+
+import org.junit.Assert;
+
+import com.linuxense.javadbf.DBFDataType;
+import com.linuxense.javadbf.DBFField;
+
+public class AssertUtils {
+
+ public static void assertColumnDefinition(DBFField field, String columnName, DBFDataType type, int length, int decimal) {
+ Assert.assertEquals(columnName, field.getName());
+ Assert.assertEquals(type, field.getType());
+// Assert.assertEquals(length, field.getLength());
+ Assert.assertEquals(decimal, field.getDecimalCount());
+ }
+
+}
diff --git a/src/test/java/com/linuxense/javadbf/testutils/DateUtils.java b/src/test/java/com/linuxense/javadbf/testutils/DateUtils.java
new file mode 100644
index 00000000..fb631a13
--- /dev/null
+++ b/src/test/java/com/linuxense/javadbf/testutils/DateUtils.java
@@ -0,0 +1,37 @@
+/*
+
+(C) Copyright 2017 Alberto Fernández
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 3.0 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library. If not, see .
+
+*/
+package com.linuxense.javadbf.testutils;
+
+import java.util.Calendar;
+import java.util.Date;
+
+public class DateUtils {
+
+ public static Date createDate(int year, int month, int day) {
+ Calendar c = Calendar.getInstance();
+ c.set(Calendar.YEAR, year);
+ c.set(Calendar.MONTH, month - 1);
+ c.set(Calendar.DAY_OF_MONTH, day);
+ c.set(Calendar.HOUR_OF_DAY, 0);
+ c.set(Calendar.MINUTE, 0);
+ c.set(Calendar.SECOND, 0);
+ c.set(Calendar.MILLISECOND, 0);
+ return c.getTime();
+ }
+}
diff --git a/src/test/java/com/linuxense/javadbf/testutils/DbfToTxtTest.java b/src/test/java/com/linuxense/javadbf/testutils/DbfToTxtTest.java
new file mode 100644
index 00000000..11b6aeb6
--- /dev/null
+++ b/src/test/java/com/linuxense/javadbf/testutils/DbfToTxtTest.java
@@ -0,0 +1,109 @@
+/*
+
+(C) Copyright 2017 Alberto Fernández
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 3.0 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library. If not, see .
+
+*/
+package com.linuxense.javadbf.testutils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+
+import com.linuxense.javadbf.DBFField;
+import com.linuxense.javadbf.DBFReader;
+
+public final class DbfToTxtTest {
+
+ private DbfToTxtTest() {
+ throw new AssertionError("no instances");
+ }
+
+ public static void export(DBFReader reader, File file) {
+
+ PrintWriter writer = null;
+ try {
+ writer = new PrintWriter(file, "UTF-8");
+ Object[] row = null;
+
+ while ((row = reader.nextRecord()) != null) {
+ for (Object o : row) {
+ writer.print(o + ";");
+ }
+ writer.println("");
+ }
+ }
+ catch (IOException e) {
+ // nop
+ }
+ finally {
+ if (writer != null) {
+ writer.close();
+ }
+ }
+ }
+
+ public static void writeToConsole(File file) throws Exception {
+ DBFReader reader = null;
+ InputStream is = null;
+ try {
+
+ is = new FileInputStream(file);
+ // create a DBFReader object
+ reader = new DBFReader(is);
+
+ // get the field count if you want for some reasons like the following
+
+ int numberOfFields = reader.getFieldCount();
+
+ // use this count to fetch all field information
+ // if required
+
+ for (int i = 0; i < numberOfFields; i++) {
+
+ DBFField field = reader.getField(i);
+
+ // do something with it if you want
+ // refer the JavaDoc API reference for more details
+ //
+ System.out.println(field.getType() + " " + field.getName());
+ }
+
+ // Now, lets us start reading the rows
+
+ Object[] rowObjects;
+
+ System.out.println("-------------------");
+ while ((rowObjects = reader.nextRecord()) != null) {
+ for (int i = 0; i < rowObjects.length; i++) {
+ System.out.println(rowObjects[i]);
+ }
+ System.out.println("-------------------");
+ }
+
+ // By now, we have iterated through all of the rows
+
+
+ }
+ finally {
+ if(is!=null){
+ is.close();
+ }
+ }
+ }
+}
diff --git a/src/test/java/com/linuxense/javadbf/testutils/FileUtils.java b/src/test/java/com/linuxense/javadbf/testutils/FileUtils.java
new file mode 100644
index 00000000..edfefc37
--- /dev/null
+++ b/src/test/java/com/linuxense/javadbf/testutils/FileUtils.java
@@ -0,0 +1,31 @@
+package com.linuxense.javadbf.testutils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public final class FileUtils {
+
+ private FileUtils() {
+ throw new AssertionError("No instances allowed");
+ }
+ public static void copyFile(File source, File dest) throws IOException {
+ InputStream is = null;
+ OutputStream os = null;
+ try {
+ is = new FileInputStream(source);
+ os = new FileOutputStream(dest);
+ byte[] buffer = new byte[1024];
+ int length;
+ while ((length = is.read(buffer)) > 0) {
+ os.write(buffer, 0, length);
+ }
+ } finally {
+ is.close();
+ os.close();
+ }
+ }
+}
diff --git a/src/test/resources/bug-33-corrupted-file-sync-mode/myfileafter-corrupted.dbf b/src/test/resources/bug-33-corrupted-file-sync-mode/myfileafter-corrupted.dbf
new file mode 100644
index 00000000..4227cbf4
Binary files /dev/null and b/src/test/resources/bug-33-corrupted-file-sync-mode/myfileafter-corrupted.dbf differ
diff --git a/src/test/resources/bug-33-corrupted-file-sync-mode/myfilebefore.dbf b/src/test/resources/bug-33-corrupted-file-sync-mode/myfilebefore.dbf
new file mode 100644
index 00000000..f8fae15b
Binary files /dev/null and b/src/test/resources/bug-33-corrupted-file-sync-mode/myfilebefore.dbf differ
diff --git a/src/test/resources/bug-46-zero_field_count/a3.dbf b/src/test/resources/bug-46-zero_field_count/a3.dbf
new file mode 100644
index 00000000..2cb98cd9
Binary files /dev/null and b/src/test/resources/bug-46-zero_field_count/a3.dbf differ
diff --git a/src/test/resources/fixtures/dbase_7.dbf b/src/test/resources/fixtures/dbase_7.dbf
new file mode 100644
index 00000000..1c05183f
Binary files /dev/null and b/src/test/resources/fixtures/dbase_7.dbf differ