Skip to content

Commit b70c218

Browse files
committed
1.12 version commit. Added ability for cloning DBF file.
1 parent 47b5251 commit b70c218

File tree

7 files changed

+121
-2
lines changed

7 files changed

+121
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ Version history
33

44
|Date | Ver | Author | Description |
55
|----------|-----|-----------------------------|--------------------|
6+
|2021-04-25| 1.12| galisha. | Added ability for cloning DBF file. |
67
|2020-08-31| 1.11| galisha. | Added ability of append records to existed DBF file. |
78
|2020-01-08| 1.10| frankvdh, galisha. | Fixed two issues: 1) Column names not upper case 2) Buffer reads are not stream-safe |
89
|2019-07-10| 1.09| galisha. | Added handling for such bad numeric as: 1219,.0000 |

README.md

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# DbfEngine Java API
22

3-
DbfEngine - a Java API to read, write and append xBase(DBASE, Foxpro dbf files). Also API allows read memory files (.mem) of Foxpro.
3+
DbfEngine - a Java API to read, write, append and clone xBase(DBASE, Foxpro dbf files). Also API allows read memory files (.mem) of Foxpro.
44
Samples for both operations you can see at [DbfEngine javadoc](https://smart-flex.ru/htm/de_api/index.html)
55

66
This API is pure lightweight library without memory consumption and any third party libraries (there are no java loggers and etc.)
@@ -81,7 +81,60 @@ public class Fp26Writer {
8181
Fp26Writer.testWrite();
8282
}
8383
}
84+
85+
public class DbfClonePerformance {
86+
87+
private static void cloneDBF(String srcFile, String cloneFile) {
88+
File room64File = new File(srcFile);
89+
System.out.println("Length src file (bytes): " + room64File.length() + " (megabytes): " + room64File.length()/(1024*1024));
90+
DbfHeader header = DbfEngine.getHeader(room64File, "Cp866");
91+
System.out.println(header.toString());
92+
DbfIterator dbfIterator = header.getDbfIterator();
93+
94+
File cloneDbf = new File(cloneFile);
95+
if (cloneDbf.exists()) {
96+
cloneDbf.delete();
97+
}
98+
DbfAppender dbfAppender = DbfEngine.getWriter(cloneDbf,
99+
DbfCodePages.Cp866);
100+
dbfAppender.defineColumns(header);
101+
102+
while (dbfIterator.hasMoreRecords()) {
103+
DbfRecord dbfRecord = dbfIterator.nextRecord();
104+
105+
// here can be your filtering code ....
106+
107+
DbfStatement statement = dbfAppender.getStatement();
108+
statement.fillStatement(dbfRecord);
109+
statement.insertStatement();
110+
}
111+
112+
dbfAppender.writeDbfAndClose();
113+
header.closeDbfHeader();
114+
}
115+
116+
public static void main(String[] args) {
117+
118+
long start = System.currentTimeMillis();
119+
120+
cloneDBF("F:\\fias_dbf\\ROOM64.DBF",
121+
"F:\\fias_dbf\\ROOM64_CLONE.DBF");
122+
123+
long finish = System.currentTimeMillis();
124+
125+
System.out.println("Clone finished for: " + (finish - start)/1000 + " sec");
126+
}
127+
}
84128
```
129+
#### Performance
130+
131+
The result of performance are (below is the work log of DbfClonePerformance class):
132+
133+
* Length src file (bytes): 600606501 (megabytes): 572
134+
* DbfHeader [firstRecordPosition=641, countRecords=1078287, countColumns=19, lengthRecord=557, codePage=Cp866, typeDbf={3,FoxBASE_dBASE_III_PLUS_without_memo}]
135+
* Clone finished for: 52 sec
136+
137+
This java code is worked under jdk1.6/32; Intel Core i3; Windows 10. And there is no one messages such as: java.lang.OutOfMemoryError: Java heap space
85138

86139
#### Licensing
87140

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>ru.smartflex.tools.dbf</groupId>
88
<artifactId>DbfEngine</artifactId>
9-
<version>1.11</version>
9+
<version>1.12</version>
1010
<name>DbfEngine - a small Java library to read, write, append xBase(DBASE, Foxpro dbf/mem files)</name>
1111

1212
<properties>

src/main/java/ru/smartflex/tools/dbf/DbfAppender.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,25 @@ public void defineColumns(DbfColumn... dbfColumns) {
100100
}
101101
}
102102

103+
/**
104+
* Defines columns for dbf file based on source header of dbf file.
105+
* @param header source header of dbf file
106+
* @since 1.12
107+
*/
108+
public void defineColumns(DbfHeader header) {
109+
if (flagAppendExistedFile) {
110+
throw new DbfEngineException(DbfConstants.EXCP_DEF_COLS_NOT_ALLOWED);
111+
}
112+
if (header.getOrderedColumnList().size() == 0) {
113+
throw new DbfEngineException(DbfConstants.EXCP_COLUMN_ADD);
114+
}
115+
dbfHeader = new DbfHeader();
116+
117+
for (DbfColumn dc : header.getOrderedColumnList()) {
118+
dbfHeader.addColumn(dc);
119+
}
120+
}
121+
103122
/**
104123
* Writes records into dbf file and then closes it.
105124
*

src/main/java/ru/smartflex/tools/dbf/DbfRecord.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,4 +346,13 @@ public String getAsString(DbfColumn column) {
346346
public int getCurrentRecord() {
347347
return currentRecord;
348348
}
349+
350+
/**
351+
* Return record
352+
* @return current record as byte array
353+
* @since 1.12
354+
*/
355+
byte[] getRecord() {
356+
return record;
357+
}
349358
}

src/main/java/ru/smartflex/tools/dbf/DbfStatement.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,4 +247,8 @@ private DbfColumnPosition definePosition(String colName, DbfColumnTypes dct) {
247247
return dbfColumnPos;
248248
}
249249

250+
public void fillStatement(DbfRecord dbfRecord) {
251+
System.arraycopy(dbfRecord.getRecord(), 0, rec, 0, rec.length);
252+
}
253+
250254
}

src/test/java/ru/smartflex/tools/dbf/DbfWriterTest.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import java.io.File;
88
import java.math.BigDecimal;
99
import java.util.Date;
10+
import java.util.Iterator;
1011

1112
import static org.junit.Assert.assertEquals;
1213

@@ -89,6 +90,38 @@ public void testAppendDbf() {
8990
writeDbf.delete();
9091
}
9192

93+
@Test
94+
public void testDbfCloning() {
95+
96+
DbfHeader dbfHeader = DbfEngine.getHeader(
97+
TestHelper.getFile("FP_26_SAMPLE.DBF"), null);
98+
DbfIterator dbfIterator = dbfHeader.getDbfIterator();
99+
System.out.println("DBF header info: " + dbfHeader.toString());
100+
101+
Iterator<DbfColumn> iter = dbfHeader.getColumnIterator();
102+
while (iter.hasNext()) {
103+
DbfColumn column = iter.next();
104+
System.out.println(column.getColumnName() + " " + column.getDbfColumnType() + " " + column.getDbfColumnPosition().getColumnLength());
105+
}
106+
107+
File cloneDbf = new File("FP_26_SAMPLE_CLONE.DBF");
108+
if (cloneDbf.exists()) {
109+
cloneDbf.delete();
110+
}
111+
DbfAppender dbfAppender = DbfEngine.getWriter(cloneDbf, DbfCodePages.Cp866);
112+
dbfAppender.defineColumns(dbfHeader);
113+
114+
while (dbfIterator.hasMoreRecords()) {
115+
DbfRecord dbfRecord = dbfIterator.nextRecord();
116+
DbfStatement statement = dbfAppender.getStatement();
117+
statement.fillStatement(dbfRecord);
118+
statement.insertStatement();
119+
}
120+
121+
dbfAppender.writeDbfAndClose();
122+
dbfHeader.closeDbfHeader();
123+
}
124+
92125
private void writeTwoRecordsToDbf(File writeDbf) {
93126

94127
DbfAppender dbfAppender = DbfEngine.getWriter(writeDbf, DbfCodePages.Cp866);

0 commit comments

Comments
 (0)