forked from LindsayBradford/go-dbf
-
Notifications
You must be signed in to change notification settings - Fork 1
/
dbf.go
95 lines (76 loc) · 1.89 KB
/
dbf.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package dbf
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"golang.org/x/text/encoding"
)
// Open opens a DBF Table from an io.Reader
func Open(r io.Reader) (*Table, error) {
return OpenWithEncoding(r, encoding.Nop)
}
// OpenWithEncoding opens a DBF Table from an io.Reader
// using the specified encoding
func OpenWithEncoding(r io.Reader, enc encoding.Encoding) (*Table, error) {
return createDbfTable(r, enc)
}
// OpenFile opens a DBF Table from file
func OpenFile(filename string) (*Table, error) {
return OpenFileWithEncoding(filename, encoding.Nop)
}
// OpenFileWithEncoding opens a DBF Table from file
// using the specified encoding
func OpenFileWithEncoding(
filename string,
enc encoding.Encoding,
) (*Table, error) {
f, err := os.Open(filename)
if err != nil {
return nil, err
}
defer f.Close() // nolint: errcheck
return OpenWithEncoding(f, enc)
}
func createDbfTable(
ir io.Reader,
enc encoding.Encoding,
) (table *Table, err error) {
// Create and pupulate DbaseTable struct
t := new(Table)
// read complete table
data, err := ioutil.ReadAll(ir)
if err != nil {
return nil, fmt.Errorf("failed to read file: %v", err)
}
// Parse header
header, err := parseHeader(bytes.NewReader(data[:12]))
if err != nil {
return nil, fmt.Errorf("failed to parse header: %v", err)
}
t.Header = header
// Parse columns
fieldCount := (t.Header.HeaderSize() - 1) / 32
columnHeaderSize := fieldCount * 32
columns, err := parseColumns(data[32:columnHeaderSize], 32, enc)
if err != nil {
return nil, err
}
// Parse rows
offset := header.HeaderSize()
rowData := data[offset+1:]
rowLength := columns.RowLength()
var rows []*Row
// Iterate rows
for i := 0; i < len(rowData); i += rowLength + 1 {
row, err := parseRow(rowData[i:i+rowLength+1], columns, enc)
if err != nil {
return nil, err
}
rows = append(rows, row)
}
t.Columns = columns
t.Rows = rows
return t, nil
}