缓冲读写写入相同的文件

时间:2019-12-24 09:07:33

标签: go

我正在尝试逐行读取非常大的文件,并替换行中的内容,然后写回同一文件。我找不到解决办法。 目前,我已经创建了一个临时文件,并将替换的行保存在临时文件中,最后将临时文件的内容复制到原始文件中。但是我必须做两次读取和两次写入。我想避免这种情况。有任何想法吗。

以下是我尝试过的内容:

file, _ := os.Open("somelargesay1GbFile.txt")
defer file.Close()

outFile, _ := os.OpenFile("temp.txt", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0777)
defer outFile.Close()

reader := bufio.NewReaderSize(file, 10*1024)

for {
    bytesread, isprefix, err := reader.ReadLine()

    if err != nil {
        if err == io.EOF {

            data := changeTheData(string(bytesread))

            outFile.WriteString(data)

            if !isprefix {
                outFile.WriteString("\r\n")
            }
        } else {
            log.Fatal(err)
        }
        break
    }

    data := changeTheData(string(bytesread))
    outFile.WriteString(data)
    if !isprefix {
        outFile.WriteString("\r\n")
    }
}

最后,我删除文件somelargesay1GbFile.txt并将其重命名为temp.txt

1 个答案:

答案 0 :(得分:4)

解决方案是打开文件两次,第一次是读取文件,第二次是覆盖内容。

请参见下面的代码。

请注意,我使用reader.ReadString('\n')而不是ReadLine。还要注意,在测试错误之前,我先写输出。这是因为未以'\ n'结尾的最后一行与ìo.EOF错误一起返回。

func main() {
    inFile, _ := os.Open("file.txt")
    defer inFile.Close()

    outFile, _ := os.OpenFile("file.txt", os.O_RDWR, 0777)
    defer outFile.Close()

    reader := bufio.NewReaderSize(inFile, 10*1024)

    for {
        line, err := reader.ReadString('\n')
        outFile.WriteString(changeData(line))
        if err != nil {
            if err != io.EOF {
                fmt.Println("error:", err)
            }
            break
        }
    }
}

我使用此changeData函数测试了代码,该函数将小写字母更改为大写字母,将大写字母更改为小写字母。然后,我们可以通过重复调用函数来测试更改。

func changeData(data string) string {
    o := make([]rune, 0, len(data))
    for _, r := range data {
        if unicode.IsLetter(r) {
            if unicode.IsUpper(r) {
                o = append(o, unicode.ToLower(r))
            } else {
                o = append(o, unicode.ToUpper(r))
            }
        } else {
            o = append(o, r)
        }
    }
    return string(o)
}

此代码将覆盖文件的每一行。该行是否被修改取决于changeData的操作。

如果要避免覆盖每行,例如,因为大多数行都不需要更改,则必须寻找要覆盖数据的位置。