Skip to content

Commit

Permalink
Merge pull request #3 from Valentin-Kaiser/devel-vka
Browse files Browse the repository at this point in the history
[MERGE] devel-vka into main
  • Loading branch information
Valentin-Kaiser authored Sep 27, 2022
2 parents 26cc9c5 + cec71c5 commit ca6a2df
Show file tree
Hide file tree
Showing 12 changed files with 425 additions and 291 deletions.
51 changes: 51 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
run:
timeout: 60s

linters:
# start with everything
enable-all: true

disable:
# deprecated
- golint
- interfacer
- maligned
- scopelint
- deadcode
- varcheck
- structcheck

# too annoying
- cyclop
- exhaustive
- exhaustivestruct
- exhaustruct
- forbidigo
- funlen
- gochecknoglobals
- godot
- goerr113
- gofumpt
- gomnd
- lll
- nakedret
- nestif
- nlreturn
- tagliatelle
- varnamelen
- wsl
- nosnakecase
- ifshort
- gci
- gofmt
- goimports

# disabled because of generics
- rowserrcheck
- sqlclosecheck
- structcheck
- wastedassign

linters-settings:
wsl:
allow-cuddle-declarations: true
53 changes: 29 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ The supported column types with their return Go types are:
| T | DateTime | time.Time |
| Y | Currency | float64 |

If you need more information about dbase data types take a look here: [Microsoft Visual Studio Foxpro](https://learn.microsoft.com/en-us/previous-versions/visualstudio/foxpro/74zkxe2k(v=vs.80))

# Installation
```
go get github.com/Valentin-Kaiser/go-dbase/dbase
Expand All @@ -70,7 +72,7 @@ type Test struct {
Date time.Time `json:"DATUM"`
TIJD string `json:"TIJD"`
SOORT float64 `json:"SOORT"`
ID_NR int32 `json:"ID_NR"`
IDNR int32 `json:"ID_NR"`
UserNR int32 `json:"USERNR"`
CompanyName string `json:"COMP_NAME"`
CompanyOS string `json:"COMP_OS"`
Expand All @@ -81,99 +83,102 @@ type Test struct {
}

func main() {
// Open file
// Open the example database file.
dbf, err := dbase.Open("./test_data/TEST.DBF", new(dbase.Win1250Converter))
if err != nil {
panic(err)
}
defer dbf.Close()

// Print all database column infos
// Print all database column infos.
for _, column := range dbf.Columns() {
fmt.Println(column.Name(), column.Type(), column.Decimals)
fmt.Printf("Name: %v - Type: %v \n", column.Name(), column.Type())
}

// Read the complete first row
// Read the complete first row.
row, err := dbf.Row()
if err != nil {
panic(err)
}

// Print all the columns in their Go values as slice
fmt.Println(row.Values())
// Print all the columns in their Go values as slice.
fmt.Printf("%+v", row.Values())

// Go back to start
err = dbf.Skip(0)
if err != nil {
panic(err)
}
// Go back to start.
dbf.Skip(0)

// Loop through all rows using rowPointer in DBF struct
// Reads the complete row
// Loop through all rows using rowPointer in DBF struct.
for !dbf.EOF() {
// This reads the complete row
fmt.Printf("EOF: %v - Pointer: %v \n", dbf.EOF(), dbf.Pointer())

// This reads the complete row.
row, err := dbf.Row()
if err != nil {
panic(err)
}

// Increase the pointer.
dbf.Skip(1)
// skip deleted rows

// Skip deleted rows.
if row.Deleted {
continue
}

// get value by position
// Get value by column position
_, err = row.Value(0)
if err != nil {
panic(err)
}

// get value by name
// Get value by column name
_, err = row.Value(dbf.ColumnPos("COMP_NAME"))
if err != nil {
panic(err)
}

// Set space trimming per default
// Enable space trimming per default
dbf.SetTrimspacesDefault(true)
// Disable space trimming for the company name
dbf.SetColumnModification(dbf.ColumnPos("COMP_NAME"), false, "", nil)
// add a column modification to switch the names of "NUMBER" and "Float" to match the data types
// Add a column modification to switch the names of "NUMBER" and "Float" to match the data types
dbf.SetColumnModification(dbf.ColumnPos("NUMBER"), true, "FLOAT", nil)
dbf.SetColumnModification(dbf.ColumnPos("FLOAT"), true, "NUMBER", nil)

// Read the row into a struct.
t := &Test{}
err = row.ToStruct(t)
if err != nil {
panic(err)
}
fmt.Printf("%+v \n", t)

fmt.Printf("Company: %v", t.CompanyName)
}

// Read only the third column of rows 1, 2 and 3
rownumbers := []uint32{1, 2, 3}
for _, row := range rownumbers {
for _, row := range []uint32{1, 2, 3} {
err := dbf.GoTo(row)
if err != nil {
panic(err)
}

// Check if the row is deleted
deleted, err := dbf.Deleted()
if err != nil {
panic(err)
}

if deleted {
fmt.Printf("Row %v deleted \n", row)
continue
}

// Read the entire row
r, err := dbf.Row()
if err != nil {
panic(err)
}

// Read the seventh column
column, err := r.Value(7)
if err != nil {
panic(err)
Expand Down
58 changes: 26 additions & 32 deletions dbase/constants.go
Original file line number Diff line number Diff line change
@@ -1,42 +1,36 @@
package dbase

import "fmt"

type DBaseError string
type Error string

const (
// returned when the end of a dBase database file is reached
ERROR_EOF DBaseError = "EOF"
// returned when the row pointer is attempted to be moved before the first row
ERROR_BOF DBaseError = "BOF"
// returned when the read of a row or column did not finish
ERROR_INCOMPLETE DBaseError = "INCOMPLETE"
// returned when an invalid column position is used (x<1 or x>number of columns)
ERROR_INVALID DBaseError = "INVALID"
// returned when a file operation is attempted on a non existent file
ERROR_NO_DBF_FILE DBaseError = "FPT_FILE_NOT_FOUND"
ERROR_NO_FPT_FILE DBaseError = "DBF_FILE_NOT_FOUND"
ERROR_INVALID_ENCODING DBaseError = "INVALID_ENCODING"
// Returned when the end of a dBase database file is reached
EOF Error = "EOF"
// Returned when the row pointer is attempted to be moved before the first row
BOF Error = "BOF"
// Returned when the read of a row or column did not finish
Incomplete Error = "INCOMPLETE"
// Returned when a file operation is attempted on a non existent file
NoFPT Error = "FPT_FILE_NOT_FOUND"
NoDBF Error = "DBF_FILE_NOT_FOUND"
// Returned when an invalid column position is used (x<1 or x>number of columns)
InvalidPosition Error = "INVALID_Position"
InvalidEncoding Error = "INVALID_ENCODING"

// Supported file types
FOXPRO byte = 0x30
FOXPRO_AUTOINCREMENT byte = 0x31
FoxPro byte = 0x30
FoxProAutoincrement byte = 0x31

// Relevant byte marker
NULL byte = 0x00
BLANK byte = 0x20
END_OF_COLUMN byte = 0x0D
ACTIVE = BLANK
DELETED = 0x2A
EOF_MARKER byte = 0x1A
Null byte = 0x00
Blank byte = 0x20
ColumnEnd byte = 0x0D
Active = Blank
Deleted = 0x2A
EOFMarker byte = 0x1A

// dBase Table flags
STRUCTURAL byte = 0x01
MEMO byte = 0x02
STRUCTURAL_MEMO byte = 0x03
DATABASE byte = 0x04
// DBase Table flags
Structural byte = 0x01
Memo byte = 0x02
StructuralMemo byte = 0x03
Database byte = 0x04
)

func (re DBaseError) AsError() error {
return fmt.Errorf(string(re))
}
Loading

0 comments on commit ca6a2df

Please sign in to comment.