如何在Golang中写入文件

28

我正在尝试向文件写入内容。我已经读取了文件的全部内容,现在希望根据从该文件中获取的某些单词更改文件的内容。但是当我检查文件的内容时,它仍然与原来的一样,并没有发生变化。这是我使用的代码:

if strings.Contains(string(read), sam) {
    fmt.Println("this file contain that word")
    temp := strings.ToUpper(sam)
    fmt.Println(temp)
    err := ioutil.WriteFile(fi.Name(), []byte(temp), 0644)
} else {
    fmt.Println(" the word is not in the file")
}

你有检查 err 的值吗?我认为这会告诉你出了什么问题... - julienc
我只是想将temp的内容写回文件中,但是当我检查我的文件时,内容并没有改变。 - user3841581
2
我理解你想做什么。我只是要求你检查 err 是否为 nil 或者是否有其他值。如果有的话,那么这个值是什么。 - julienc
代码不完整,我使用了这个函数check(e error) { 如果e不为nil { panic(e) } },在我的代码片段后面我有check(err)。如果它是nil,那么就有问题。 - user3841581
3
如果您提供尽可能小的完全可运行的代码,这将对您和我们都有帮助。通过剥离不必要的代码,您可能会自己找到问题所在。如果没有,我们更有机会找到错误。 - topskip
如果匹配{ read,err:= ioutil.ReadFile(path) //fmt.Println(string(read)) fmt.Println(“这是文件名”,fi.Name()) 如果 strings.Contains(string(read),sam) { fmt.Println(“此文件包含该单词”) value:=strings.ToUpper(sam) fmt.Println(value) err=ioutil.WriteFile(fi.Name(),[]byte(value),0644) } else { fmt.Println(“该单词不在文件中”) } check(err) - user3841581
2个回答

26

考虑到您对ioutil.WriteFile()的调用与"通过示例编写文件"中使用的内容一致,这应该可以工作。

但是,在Go by example文章中,它在写入调用后立即检查了err。

您在测试范围之外检查了err:

    if matched {
        read, err := ioutil.ReadFile(path)
        //fmt.Println(string(read))
        fmt.Println(" This is the name of the file", fi.Name())
        if strings.Contains(string(read), sam) {
            fmt.Println("this file contain that word")
            Value := strings.ToUpper(sam)
            fmt.Println(Value)
            err = ioutil.WriteFile(fi.Name(), []byte(Value), 0644)
        } else {
            fmt.Println(" the word is not in the file")
        }
        check(err)   <===== too late
    }

你正在测试的错误是在读取文件时 (ioutil.ReadFile) 产生的,这是由于区块和作用域引起的。

你需要在写入调用后立即检查错误。

            err = ioutil.WriteFile(fi.Name(), []byte(Value), 0644)
            check(err)   <===== too late

由于 WriteFile 会覆盖整个文件,你可以使用 strings.Replace() 将单词替换为其大写形式:

r := string(read)
r = strings.Replace(r, sam, strings.ToUpper(sam), -1)
err := ioutil.WriteFile(fi.Name(), []byte(r), 0644)
为了进行不区分大小写的替换,请像在"如何在Go中使用不区分大小写的正则表达式?"中那样使用正则表达式。然后,使用func (*Regexp) ReplaceAllString:
re := regexp.MustCompile("(?i)\\b"+sam+"\\b")
r = re.ReplaceAllString(r, strings.ToUpper(sam))
err := ioutil.WriteFile(fi.Name(), []byte(r), 0644)
请注意\b:使用单词边界来查找任何以sam内容开头和结尾的单词(而不是查找包含sam内容的子字符串)
如果您想替换子字符串,只需省略\b
re := regexp.MustCompile("(?i)"+sam)

我同意。你可以在写入后检查错误,看看是否有异常吗? - VonC
我刚刚执行了,但是没有抛出任何异常。其他代码都正常工作,但是当我检查文件时,内容是相同的。 - user3841581
@user3841581,你能否将fi.Name()替换为文件的完整路径,仅供测试之用?ioutil.WriteFile("/full/path/of/the/file", []byte(Value), 0644) - VonC
它能够工作,但覆盖了整个文件并将其更改为该值。这里可能出了什么问题? - user3841581
问题在于它替换了用于测试的字符串,但是它必须被写入文件。在这种情况下,它会覆盖整个文件。 - user3841581
显示剩余12条评论

2

不太清楚你想做什么。我最好的猜测是这样的:

package main

import (
    "bytes"
    "errors"
    "fmt"
    "io/ioutil"
    "os"
)

func UpdateWord(filename string, data, word []byte) (int, error) {
    n := 0
    f, err := os.OpenFile(filename, os.O_WRONLY, 0644)
    if err != nil {
        return n, err
    }
    uWord := bytes.ToUpper(word)
    if len(word) < len(uWord) {
        err := errors.New("Upper case longer than lower case:" + string(word))
        return n, err
    }
    if len(word) > len(uWord) {
        uWord = append(uWord, bytes.Repeat([]byte{' '}, len(word))...)[:len(word)]
    }
    off := int64(0)
    for {
        i := bytes.Index(data[off:], word)
        if i < 0 {
            break
        }
        off += int64(i)
        _, err = f.WriteAt(uWord, off)
        if err != nil {
            return n, err
        }
        n++
        off += int64(len(word))
    }
    f.Close()
    if err != nil {
        return n, err
    }
    return n, nil
}

func main() {
    // Test file
    filename := `ltoucase.txt`

    // Create test file
    lcase := []byte(`update a bc def ghij update klmno pqrstu update vwxyz update`)
    perm := os.FileMode(0644)
    err := ioutil.WriteFile(filename, lcase, perm)
    if err != nil {
        fmt.Println(err)
        return
    }

    // Read test file
    data, err := ioutil.ReadFile(filename)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(string(data))

    // Update word in test file
    word := []byte("update")
    n, err := UpdateWord(filename, data, word)
    if err != nil {
        fmt.Println(n, err)
        return
    }
    fmt.Println(filename, string(word), n)
    data, err = ioutil.ReadFile(filename)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(string(data))
}

输出:

update a bc def ghij update klmno pqrstu update vwxyz update
ltoucase.txt update 4
UPDATE a bc def ghij UPDATE klmno pqrstu UPDATE vwxyz UPDATE

它确实可以工作,但是它区分大小写,那么如果我发送UpDate,该单词将无法在文件中找到。有没有办法使它不区分大小写? - user3841581
有没有办法将正则表达式函数包含到您的函数中,以便它不区分大小写? - user3841581

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接