猿问

无论我使用什么 dBase (.dbf) 文件,binary.read 都会返回“意外的 EOF”

func main() {

        file, err := os.Open("example.dbf") // For read access.

        if err != nil {

            log.Fatal(err)

        }


        dBaseioReader, err := NewReader(file)

        if err != nil {

            log.Fatal(err)

        }

        return nil

}


type dbHeader struct {

    Version             byte

    LastUpdate          [3]byte

    NumRecords          int32

    NumBytesInHeader    int16

    NumBytesInRecord    int16

    _                   [2]byte //reserved

    IncompatFlag        byte

    EncryptionFlag      byte

    MultiUserProcessing [12]byte

    MDXProductionFlag   byte

    LangDriverId        byte

    _                   [2]byte //reserved

    LangDriverName      [32]byte

    _                   [4]byte //reserved

}



type dbFieldDescriptor struct {

    FieldName         [32]byte

    FieldType         byte

    FieldLen          byte

    FieldDec          byte

    _                 [2]byte

    MDXProductionFlag byte

    _                 [2]byte

    NextAutoIncrement [4]byte

    _                 [4]byte

}



type DBaseReader struct {

    rawInput *bufio.Reader

    Header   *dbHeader

    Fields   []*dbFieldDescriptor


    recordsLeft int

}


func NewReader(input io.Reader) (dbr *DBaseReader, err error) {

    dbr = &DBaseReader{

        rawInput: bufio.NewReaderSize(input, 32*1024),

        Header:   &dbHeader{},

    }


    err = binary.Read(dbr.rawInput, binary.LittleEndian, dbr.Header)

    if err != nil{

        return

    }


    dbr.recordsLeft = int(dbr.Header.NumRecords)


    headerBytesLeft := dbr.Header.NumBytesInHeader

    headerBytesLeft -= dbHeaderSize


    // read field descriptors until 0x0D termination byte

    var term []byte

    for {

        field := &dbFieldDescriptor{}


        err = binary.Read(dbr.rawInput, binary.LittleEndian, field)

        if err != nil{

            //FIRST CRASH HAPPENS HERE.

            return

        }


以上是相关代码。无论我使用什么示例 dbf 文件,程序都会崩溃。我不确定为什么我不断收到“意外的 EOF”错误。在过去的几天里,我一直试图解决这个问题,但不幸的是没有运气。


慕森王
浏览 238回答 1
1回答

小唯快跑啊

您没有提供任何证据证明您的文件格式是正确的。在编写程序之前,您应该确认文件格式正确。文件的前 256 个字节是多少?例如,hex.go:package mainimport (&nbsp; &nbsp; "encoding/hex"&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "io/ioutil"&nbsp; &nbsp; "os"&nbsp; &nbsp; "strconv")func main() {&nbsp; &nbsp; if len(os.Args) <= 1 {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Fprintln(os.Stderr, "usage: hex filename [bytes]")&nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; }&nbsp; &nbsp; data, err := ioutil.ReadFile(os.Args[1])&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Fprintln(os.Stderr, "filename:", err)&nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; }&nbsp; &nbsp; n := len(data)&nbsp; &nbsp; if len(os.Args) > 2 {&nbsp; &nbsp; &nbsp; &nbsp; i, err := strconv.Atoi(os.Args[2])&nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Fprintln(os.Stderr, "bytes:", err)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; if n > i {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; n = i&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Print(hex.Dump(data[:n]))}输出:$ go run hex.go example.dbf 25600000000&nbsp; 03 01 04 18 01 00 00 00&nbsp; 41 07 d0 05 00 00 00 00&nbsp; |........A.......|00000010&nbsp; 00 00 00 00 00 00 00 00&nbsp; 00 00 00 00 00 03 00 00&nbsp; |................|00000020&nbsp; 54 52 41 43 4b 5f 49 44&nbsp; 00 00 00 43 01 00 00 00&nbsp; |TRACK_ID...C....|00000030&nbsp; 0b 00 00 00 00 00 00 00&nbsp; 00 00 00 00 00 00 00 00&nbsp; |................|00000040&nbsp; 4c 4d 55 4c 54 00 00 00&nbsp; 00 00 00 4c 0c 00 00 00&nbsp; |LMULT......L....|00000050&nbsp; 01 00 00 00 00 00 00 00&nbsp; 00 00 00 00 00 00 00 00&nbsp; |................|00000060&nbsp; 4e 54 41 58 59 45 41 52&nbsp; 00 00 00 4e 0d 00 00 00&nbsp; |NTAXYEAR...N....|00000070&nbsp; 04 00 00 00 00 00 00 00&nbsp; 00 00 00 00 00 00 00 00&nbsp; |................|00000080&nbsp; 4e 43 4f 55 4e 54 59 43&nbsp; 4f 44 00 4e 11 00 00 00&nbsp; |NCOUNTYCOD.N....|00000090&nbsp; 02 00 00 00 00 00 00 00&nbsp; 00 00 00 00 00 00 00 00&nbsp; |................|000000a0&nbsp; 43 50 52 4f 50 41 44 44&nbsp; 00 00 00 43 13 00 00 00&nbsp; |CPROPADD...C....|000000b0&nbsp; 3c 00 00 00 00 00 00 00&nbsp; 00 00 00 00 00 00 00 00&nbsp; |<...............|000000c0&nbsp; 4c 43 4f 4d 4d 49 4e 44&nbsp; 00 00 00 4c 4f 00 00 00&nbsp; |LCOMMIND...LO...|000000d0&nbsp; 01 00 00 00 00 00 00 00&nbsp; 00 00 00 00 00 00 00 00&nbsp; |................|000000e0&nbsp; 4c 56 41 43 4c 41 4e 44&nbsp; 00 00 00 4c 50 00 00 00&nbsp; |LVACLAND...LP...|000000f0&nbsp; 01 00 00 00 00 00 00 00&nbsp; 00 00 00 00 00 00 00 00&nbsp; |................|$表级但是一张桌子的水平是多少?级别表示其版本。dBASE 表格式是一种随着时间的推移而发展的标准。当 dBASE 的新版本对该格式进行一些改进时,会给出一个新的格式级别编号,与新的 dBASE 版本相同。例如,我们有级别 3、4、5 和 7,分别对应于 dBASE III、dBASE IV、dBASE 5 和 Visual dBASE 7。没有级别 6,因为没有 Visual dBASE 6。7 级带来了许多改进。字段名称最多可包含 31 个字符(之前最多为 10 个)。出现了一些新的字段类型(例如,AutoIncrement 字段几乎不可能为同一个表中的两个记录提供相同的数字)。如果您的表必须被其他软件使用,您可能必须为了兼容性而牺牲这些优势,因为很少有应用程序可以使用 7 级表。.dbf 文件格式:文件头字节 0,位 0-2 表示版本号:dBASE Level 5 为 3,dBASE Level 7 为 4。
随时随地看视频慕课网APP

相关分类

Go
我要回答