将2个大型排序的CSV文件组合到一个文件中
问题描述:
我有一个大小约为50GB的存档文件。将2个大型排序的CSV文件组合到一个文件中
每个星期,我都需要一个CSV文件,并将其与非常大的50GB CSV文件合并。
我是Go的新手,希望Go有一个不错的解决方案。
这些文件看起来像:
"a:123", 101010
"b:123", 101010
"some-key-here:123", 101010
"some-key-here:234", 101010
答
虽然我没有编译它自己来检查,这应该做你想做的,一旦你实现compare()
功能。它本质上是Mergesort算法的“合并”步骤。由于您已经按照排序顺序得到了这两个文件,因此您只需要合并步骤,这可以通过流式处理完成。
package main
import (
"encoding/csv"
"io"
"log"
"os"
)
const outFile = "your/output/file/path.ext"
func main() {
// make sure there are only 2 args
if len(os.Args) != 3 {
log.Panic("\nUsage: command file1 file2")
}
// open the first file
f1, e := os.Open(os.Args[1])
if e != nil {
log.Panic("\nUnable to open first file: ", e)
}
defer f1.Close()
// open second file
f2, e := os.Open(os.Args[2])
if e != nil {
log.Panic("\nUnable to open second file: ", e)
}
defer f2.Close()
// create a file writer
w, e := os.Create(outFile)
if e != nil {
log.Panic("\nUnable to create new file: ", e)
}
defer w.Close()
// wrap the file readers with CSV readers
cr1 := csv.NewReader(f1)
cr2 := csv.NewReader(f2)
// wrap the out file writer with a CSV writer
cw := csv.NewWriter(w)
// initialize the lines
line1, b := readline(cr1)
if !b {
log.Panic("\nNo CSV lines in file 1.")
}
line2, b := readline(cr2)
if !b {
log.Panic("\nNo CSV lines in file 2.")
}
// copy the files according to similar rules of the merge step in Mergesort
for {
if compare(line1, line2) {
writeline(line1)
if line1, b = readline(cr1); !b {
copy(cr2, w)
break
}
} else {
writeline(line2)
if line2, b = readline(cr2); !b {
copy(cr1, w)
break
}
}
}
// note the files will be closed here, since we defered it above
}
func readline(r csv.Reader) ([]string, bool) {
line, e := r.Read()
if e != nil {
if e == io.EOF {
return nil, false
}
log.Panic("\nError reading file: ", e)
}
return line, true
}
func writeline(w csv.Writer, line []string) {
e := w.Write(line)
if e != nil {
log.Panic("\nError writing file: ", e)
}
}
func copy(r csv.Reader, w csv.Writer) {
for line, b := readline(r); !b; r, b = readline(r) {
writeline(w, line)
}
}
func compare(line1, line2 string) bool {
/* here, determine if line1 and line2 are in the correct order (line1 first)
if so, return true, otherwise false
*/
}
注:这个答案已经被大量编辑,包括内联代码,而不是链接。此外,自第一稿以来,代码已经有了很大的改进,但由于这里没有任何活动,我只是吹走旧版本并重写我的答案。
答
如果两个文件分别排序,则可以使用合并排序的合并函数将它们合并到排序后的数组中。
通过数组,我的意思是我们可以使用另一个CSV文件即时写入排序数据。
+0
问题的标题显示它已排序。由于文件很大,流式传输比读入数组更好(它可能不适合内存)。 – burfl 2013-04-09 17:50:38
如果你在Unix/Linux/OS X上,你应该考虑使用'sort'命令。艰苦的工作已经为你完成。 – Daniel 2013-03-27 21:08:16