我需要读取一个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函数编写自己的函数?
答案 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)