mirror of
https://github.com/nxshock/mssqlbulkloader.git
synced 2024-11-27 00:11:02 +05:00
125 lines
2.2 KiB
Go
125 lines
2.2 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"fmt"
|
||
|
"io"
|
||
|
"time"
|
||
|
|
||
|
dbf "github.com/SebastiaanKlippert/go-foxpro-dbf"
|
||
|
)
|
||
|
|
||
|
func init() {
|
||
|
dbf.SetValidFileVersionFunc(func(version byte) error {
|
||
|
return nil
|
||
|
})
|
||
|
}
|
||
|
|
||
|
type DbfReader struct {
|
||
|
reader *dbf.DBF
|
||
|
header []string
|
||
|
options *Options
|
||
|
}
|
||
|
|
||
|
func NewDbfReader(r io.Reader, options *Options) (*DbfReader, error) {
|
||
|
return newDbfReader(r, options)
|
||
|
}
|
||
|
|
||
|
func newDbfReader(r io.Reader, options *Options) (*DbfReader, error) {
|
||
|
b, err := io.ReadAll(r)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
br := bytes.NewReader(b)
|
||
|
|
||
|
re, err := dbf.OpenStream(br, nil, &dbf.UTF8Decoder{})
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
dbfReader := &DbfReader{
|
||
|
reader: re,
|
||
|
options: options}
|
||
|
|
||
|
fullHeader := re.FieldNames()
|
||
|
var header []string
|
||
|
for i, v := range options.fieldsTypes {
|
||
|
if v == ' ' {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
s, err := charsets.DecodeString(options.encoding, fullHeader[i])
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
header = append(header, s)
|
||
|
}
|
||
|
|
||
|
dbfReader.header = header
|
||
|
|
||
|
return dbfReader, nil
|
||
|
}
|
||
|
|
||
|
func (r *DbfReader) GetHeader() []string {
|
||
|
return r.header
|
||
|
}
|
||
|
|
||
|
func (r *DbfReader) Options() *Options {
|
||
|
return r.options
|
||
|
}
|
||
|
|
||
|
func (r *DbfReader) GetRow(asStrings bool) ([]any, error) {
|
||
|
if r.reader.EOF() {
|
||
|
return nil, io.EOF
|
||
|
}
|
||
|
|
||
|
record, err := r.reader.Record()
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("read record: %v", err)
|
||
|
}
|
||
|
|
||
|
r.reader.Skip(1)
|
||
|
|
||
|
var args []any
|
||
|
|
||
|
for i, v := range record.FieldSlice() {
|
||
|
var fieldType FieldType
|
||
|
err = fieldType.UnmarshalText([]byte{r.options.fieldsTypes[i]})
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("get record type: %v", err)
|
||
|
}
|
||
|
|
||
|
if fieldType == Skip {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
decV, err := charsets.DecodeString(r.options.encoding, fmt.Sprint(v))
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
parsedValue, err := fieldType.ParseValue(r, decV)
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("parse value: %v", err)
|
||
|
}
|
||
|
|
||
|
args = append(args, parsedValue)
|
||
|
}
|
||
|
|
||
|
return args, nil
|
||
|
}
|
||
|
|
||
|
func (r *DbfReader) Close() error {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (r *DbfReader) ParseDate(rawValue string) (time.Time, error) {
|
||
|
return time.ParseInLocation("02.01.2006", rawValue, r.options.timezone)
|
||
|
}
|
||
|
|
||
|
func (r *DbfReader) ParseDateTime(rawValue string) (time.Time, error) {
|
||
|
return time.ParseInLocation("02.01.2006 15:04:05", rawValue, r.options.timezone)
|
||
|
}
|