【问题标题】:How to write to a file in golanggolang如何写入文件
【发布时间】:2014-07-19 11:20:32
【问题描述】:

我正在尝试写入文件。我阅读了文件的全部内容,现在我想根据我从文件中得到的一些单词来更改文件的内容。但是当我检查文件的内容时,它仍然是相同的并且没有改变。这是我用的

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的值吗?我想这会告诉你出了什么问题......
  • 我只是想把 temp 的内容写回文件,但是当我检查我的文件时,内容并没有改变
  • 我明白你想做什么。我只是要求您检查err 是否为nil 或者它是否具有其他值。在这种情况下,价值是什么。
  • 代码不完整,我使用了这个 func check(e error) { if e != nil { panic(e) } 并且在我的狙击手之后我有 check(err)。如果是 nil 则有问题
  • 我认为,如果您提供尽可能小的完整工作代码,这将对您和我们都有帮助。通过删除不需要的代码,您可能会自己发现问题。如果没有,我们就有更好的机会找到错误。

标签: go


【解决方案1】:

考虑到您对ioutil.WriteFile() 的调用与“Go by Example: Writing Files”中使用的一致,这应该可行。

但是那篇 Go by example 文章会在 write 调用之后检查错误。

您在测试范围之外检查错误:

    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),因为 blocks and scope

您需要在 Write 调用后立即检查错误

            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)

对于不区分大小写的替换,请使用“How do I do a case insensitive regular expression in 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)

注意\bword boundary 以查找以sam 开头和结尾的任何单词内容(而不是查找子字符串包含 em> sam 内容)。
如果要替换子字符串,只需删除 \b:

re := regexp.MustCompile("(?i)"+sam)

【讨论】:

  • 在初始文件中它没有改变。它是小写的,也就是说它仍然是我读取的相同值
  • 我同意。能不能在 Write 之后检查一下 err,看看有没有异常?
  • 我刚刚做了,但它没有给我任何异常。其他代码工作正常,但是当我检查文件时,内容是一样的
  • @user3841581 你能打印fi.Name() 并确保它是正确的文件路径吗?或者您是否看到由您的程序创建的另一个同名文件?
  • @user3841581 你能用文件的完整路径替换fi.Name(),只是为了测试? ioutil.WriteFile("/full/path/of/the/file", []byte(Value), 0644)
【解决方案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 会发生什么,在文件中找不到该词。有没有办法让它仍然不区分大小写?
  • 有没有办法将正则表达式函数包含到您的函数中,使其不区分大小写?
猜你喜欢
  • 2014-05-12
  • 1970-01-01
  • 2022-01-28
  • 1970-01-01
  • 2018-01-01
  • 1970-01-01
  • 2016-05-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多