在Golang中记录并查找CSV文件位置

时间:2019-04-11 21:58:18

标签: file csv go seek

我需要读取一个CSV文件并将具有某些值的行的位置记录到一个数组中,然后再回去以不特定的顺序并以良好的性能检索这些行,因此可以进行随机访问。

我的程序使用csv.NewReader(file),但是我看不到任何获取或设置它使用的文件偏移量的方法。我尝试使用file.Seek(0,io.SeekCurrent)返回文件位置,但在调用reader.Read()之间并没有改变。我还尝试了fmt.Println(“ + v + v \ n”,reader,file)来查看是否有任何内容存储阅读器的文件位置,但我看不到。如果找到了文件位置,我也不知道最佳的使用方法。

这是我需要做的:

file,_ = os.Open("stuff.csv")
reader = csv.NewReader(file)

//read file and record locations
for {
    line,_ = reader.Read()
    if wantToRememberLocation(line) {
         locations = append(locations, getLocation()) //need this function
    }
}

//then revisit certain lines
for {
    reader.GoToLine(locations[random])  //need this function
    line,_ = reader.Read()
    doStuff(line)
}

是否甚至可以使用csv库执行此操作,还是需要使用更多原始io函数编写自己的函数?

2 个答案:

答案 0 :(得分:0)

这是使用TeeReader的解决方案。此示例仅保存所有位置,然后返回并重新读取其中一些位置。

//set up some vars and readers to record position and length of each line
type Record struct {
    Pos int64
    Len int 
}
records := make([]Record,1)
var buf bytes.Buffer
var pos int64
file,_ := Open("stuff.csv")
tr := io.TeeReader(file, &buf)
cr := csv.NewReader(tr)

//read first row and get things started
data,_ := cr.Read()
dostuff(data)
//length of current row determines position of next
lineBytes,_ := buf.ReadBytes('\n')
length := len(lineBytes)
pos += int64(length)
records[0].Len = length
records = append(records, Record{ Pos: pos })

for i:=1;;i++ {
    //read csv data
    data,err = c.Read()
    if err != nil {break}
    dostuff(data)
    //record length and position
    lineBytes,_ = buf.ReadBytes('\n')
    lenth = len(lineBytes)
    pos += int64(length)
    records[i].Len = length
    records = append(records, Record{ Pos: pos })
}

//prepare individual line reader
line := make([]byte,1000)
lineReader := bytes.NewReader(line)

//read random lines from file
for {
    i := someLineNumber()
    //use original file reader to fill byte slice with line
    file.ReadAt(line[:records[i].Len], records[i].Pos)
    //need new lineParser to start at beginning every time
    lineReader.Seek(0,0)
    lineParser := csv.NewReader(lineReader)
    data,_ = lineParser.Read()
    doStuff(data)
}

答案 1 :(得分:0)

os.Open返回一个文件,该文件实现io.Seeker。

因此,您可以执行以下操作将视频流倒回到开头:

_, err = file.Seek(0, io.SeekStart)

https://golang.org/src/os/file.go