B4J Code Snippet [DBF] Read/Write DBF file using jDBF

The example above works but the characters are not displaying correctly. With some trial-and-error, I finally get it works like the Test.java

TestRead:
'Non-UI application (console / server application)
#Region Project Attributes
    #CommandLineArgs:
    #MergeLibraries: True
    #AdditionalJar: jdbf-1.2.jar
#End Region

Sub Process_Globals

End Sub

Sub AppStart (Args() As String)
    ' Set charset to GBK
    Dim CSet As JavaObject
    CSet.InitializeStatic("java.nio.charset.Charset")
    Dim cs As Object = CSet.RunMethod("forName", Array As String("GBK"))
 
    ' Initialize DBF Reader
    Dim dbfReader As JavaObject
    dbfReader.InitializeNewInstance ("com.hexiong.jdbf.DBFReader", Array As Object ("book2.dbf")) ' D:\Development\B4J\DBF\Objects\

    ' Get field name
    Dim FieldsName As String
    Dim FieldsCount As Object = dbfReader.RunMethod("getFieldCount", Null)
    For i = 0 To FieldsCount - 1
        Dim Fld As JavaObject = dbfReader.RunMethod("getField", Array As Object(i))
        Dim Nam As String = Fld.RunMethod("getName", Null)
        FieldsName = FieldsName & $"${Nam}  |  "$
    Next
    Log(FieldsName)
 
    ' Read fields
    Do While dbfReader.RunMethod("hasNextRecord", Null)
        Dim res() As Object = dbfReader.RunMethod("nextRecord", Array As Object(cs))
        Dim row As String
        For Each Field In res
            row = row & $"${Field}  |  "$
        Next
        Log(row & CRLF)
    Loop
 
    ' Close the dbf file
    dbfReader.RunMethod ("close", Null)
End Sub

TestWrite:
'Non-UI application (console / server application)
#Region Project Attributes
    #CommandLineArgs:
    #MergeLibraries: True
    #AdditionalJar: jdbf-1.2.jar
#End Region

Sub Process_Globals

End Sub

Sub AppStart (Args() As String)
    TestWrite
End Sub

Sub TestRead
    ' Initialize DBF Reader
    Dim dbfReader As JavaObject
    dbfReader.InitializeNewInstance("com.hexiong.jdbf.DBFReader", Array As Object ("testwrite.dbf"))

    ' Get field name
    Dim FieldsName As String
    Dim FieldsCount As Object = dbfReader.RunMethod("getFieldCount", Null)
    For i = 0 To FieldsCount - 1
        Dim Fld As JavaObject = dbfReader.RunMethod("getField", Array As Object(i))
        Dim Nam As String = Fld.RunMethod("getName", Null)
        FieldsName = FieldsName & $"${Nam}  |  "$
    Next
    Log(FieldsName)
 
    ' Read fields
    i = 0
    Do While dbfReader.RunMethod("hasNextRecord", Null)
        Dim res() As Object = dbfReader.RunMethod("nextRecord", Null)
        Dim row As String
        For Each Field In res
            row = row & $"${Field}  |  "$
        Next
        Log(row & CRLF)
        i = i + 1
    Loop
    Log("Total Count: " & i)
 
    ' Close the dbf file
    dbfReader.RunMethod("close", Null)
End Sub

Sub TestWrite
    ' Initialize JDB Fields
    Dim t1 As Char = "C"
    Dim t2 As Char = "N"
    Dim t3 As Char = "F"
    Dim t4 As Char = "D"
 
    Dim JDBField As JavaObject
    Dim col1 As JavaObject = JDBField.InitializeNewInstance("com.hexiong.jdbf.JDBField", Array("ID", t1, 8, 0))
    Dim JDBField As JavaObject
    Dim col2 As JavaObject = JDBField.InitializeNewInstance("com.hexiong.jdbf.JDBField", Array("Name", t1, 254, 0))
    Dim JDBField As JavaObject
    Dim col3 As JavaObject = JDBField.InitializeNewInstance("com.hexiong.jdbf.JDBField", Array("TestN", t2, 20, 0))
    Dim JDBField As JavaObject
    Dim col4 As JavaObject = JDBField.InitializeNewInstance("com.hexiong.jdbf.JDBField", Array("TestF", t3, 20, 6))
    Dim JDBField As JavaObject
    Dim col5 As JavaObject = JDBField.InitializeNewInstance("com.hexiong.jdbf.JDBField", Array("TestD", t4, 8, 0))
 
    Dim JDBFields As JavaObject
    Dim fields() As Object = JDBFields.InitializeArray("com.hexiong.jdbf.JDBField", Array(col1, col2, col3, col4, col5))
 
    ' Initialize DBF Writer
    Dim dbfWriter As JavaObject
    dbfWriter.InitializeNewInstance("com.hexiong.jdbf.DBFWriter", Array As Object ("testwrite.dbf", fields))

    Dim row1 As Object = Array("1", "hexiong ", 500, 500.123, CurrentDate)
    Dim row2 As Object = Array("2", " hefang ", 600, 600.234, CurrentDate)
    Dim row3 As Object = Array("3", "hexi01234567890123456789012345678901234567890123456789" & _
    "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" & _
    "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789", 600, 600.234, CurrentDate)
    Dim row4 As Object = Array("4", "heqiang", 700, 700.456, CurrentDate)

    Dim records() As Object
    records = Array As Object(row1, row2, row3, row4)
    For i = 0 To records.Length - 1
        dbfWriter.RunMethod("addRecord", Array(records(i)))
    Next
 
    ' Close the dbf file
    dbfWriter.RunMethod("close", Null)
 
    Log("testwrite.dbf write finished.......")
    TestRead
End Sub

Sub CurrentDate As Object
    Dim jo As JavaObject
    jo.InitializeNewInstance("java.util.Date", Null)
    'Log(jo)
    Return jo
End Sub

jDBF is available for free download here: https://code.google.com/archive/p/jdbf/downloads

Updates:
Reupload to GitHub as version 1.3 https://github.com/pyhoon/jdbf
version: 1.4
- Fix trim of String field
- Fix logical value with blank space as False
version: 1.5
- Fix error when not trim on number field
version: 1.6
- Fix error when not trim on date field

Modified source code attached jdbf.zip (IntelliJ IDEA project)
 

Attachments

  • DBF.zip
    1.8 KB · Views: 274
  • book2.zip
    3.9 KB · Views: 268
  • jdbf-1.3.jar
    13.6 KB · Views: 260
Last edited:

aeric

Expert
Licensed User
Longtime User
Awesome and thanks, just curious if it possible to have a CRUD example, something I was pondering about some time ago and didnt / dont have time yet to look at.
As my knowledge in Java and JavaObject is quite limited, I will try my best to also make the Writer work. :)
If anyone can help then it is great.
@rwblinn , can you help? The link in your previous post is broken.
 

AnandGupta

Expert
Licensed User
Longtime User
Thanks @aeric for the DBF read write codes.
I work with DBF in my office project with XBase++ , so this may come handy to me :)
 

Johan Hormaza

Well-Known Member
Licensed User
Longtime User
1639242540136.png
 

AnandGupta

Expert
Licensed User
Longtime User
I have tried the code snippets itself and both are working fine.
Maybe Johan Hormaza is missing something
 

aeric

Expert
Licensed User
Longtime User
If we look at the source, we can see there are only 4 files which I think it is quite straight forward. I think it is possible to rewrite the Java code into pure B4X. Is it worth it?
 

aeric

Expert
Licensed User
Longtime User
If you are interested, please check:
 

AnandGupta

Expert
Licensed User
Longtime User
One of my dbf file (renamed as book2.dbf) throws error on display,

B4X:
B  |  O  |  06  |  CURRENT ASSETS, LOANS & ADVANCES  |  04  |  Other Current Assets  |  03  |  05  |    |    |  false  |    |  
21
B  |  O  |  06  |  CURRENT ASSETS, LOANS & ADVANCES  |  05  |  Loans & Advances  |  03  |  06  |    |    |  false  |    |  
22
B  |  O  |  07  |  MISCELLANEOUS EXPENDITURE  |    |    |  04  |    |    |    |  false  |    |  
main._appstart (java line: 87)
java.lang.reflect.InvocationTargetException
    at sun.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at anywheresoftware.b4j.object.JavaObject.RunMethod(JavaObject.java:132)
    at b4j.example.main._appstart(main.java:87)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:109)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:96)
    at b4j.example.main.main(main.java:28)
Caused by: com.hexiong.jdbf.JDBFException: Unrecognized value for logical field: 
    at com.hexiong.jdbf.JDBField.parse(JDBField.java:253)
    at com.hexiong.jdbf.DBFReader.nextRecord(DBFReader.java:254)
    ... 12 more

I understand may be due to code for font
B4X:
Dim cs As Object = CSet.RunMethod("forName", Array As String("GBK"))
As my dbf are normal US English, how to change this code ?

I have attached the dbf file, if you need to check it.
 

Attachments

  • book2.zip
    854 bytes · Views: 182

AnandGupta

Expert
Licensed User
Longtime User
I use the jar I modified a few days ago and able to open your file without error.
Thanks a lot 🙏

Now no error shown.
I will make changes to open all my dbf files of my program folder and check. This will ensure that all my dbf are Ok to read.
 

AnandGupta

Expert
Licensed User
Longtime User
I found this library easier to use and code than the VFoxPro one, so I am using it and read data response are fast on internet ip.
My dbf files are of Clipper format so extra FPro field type are not required.

I have below query for this library.

All data are of US English so how to change the GBK below ? (It is for Chinese I see)
Got it, use cp1252
B4X:
    ' Set charset to GBK
    Dim CSet As JavaObject
    CSet.InitializeStatic("java.nio.charset.Charset")
    Dim cs As Object = CSet.RunMethod("forName", Array As String("GBK"))

Initializing the dbf makes it exclusive opened, but I want it to be shared opened. How to achieve it ?
Working shared on next checking. Let me check it with other dbf s.
B4X:
    Dim dbfReader As JavaObject
'    dbfReader.InitializeNewInstance ("com.hexiong.jdbf.DBFReader", Array As Object ("smast.dbf")) ' D:\Development\B4J\DBF\Objects\
    dbfReader.InitializeNewInstance ("com.hexiong.jdbf.DBFReader", Array As Object (req.GetParameter("path") & "SMAST.dbf")) ' D:\Development\B4J\DBF\Objects\

Thanks in advance for your guidance.
 
Last edited:
Top