我有以下程序。它基本上查看文件夹并检查是否有任何新文件。如果它找到新文件,则会对该文件进行修改。然而,这样做的方式实际上效率低下并且存在缺陷。它将文件的原始内容复制到内存中,进行修改,删除原始文件,然后使用内存中的内容保存一个新文件。实际上,如果出现任何问题(可能会发生),一旦文件被删除,您就会丢失数据。理想情况下,我可以直接在文件中进行修改,而无需删除原始文件,从而需要保存一个新文件。从代码中可以看出,修改量很小。我不熟悉如何在 GO 中执行此操作。
package main
import (
"time"
"fmt"
"io/ioutil"
"os"
"bytes"
"strings"
)
const dir = "dir00003"
func main() {
fmt.Println("Running...")
//Go into a loop forever
for {
//Wait 60 seconds before taking any action.
time.Sleep(60 * time.Second)
//Read all of the file data for all files in the directory:
files, err := ioutil.ReadDir(dir)
if err != nil {fmt.Println("Failed to read transfer folder. There must be a folder named `dir00003`!"); continue}
for _, v := range files {
//if this is an index file, skip over it as we don't care:
if strings.Contains(v.Name(), "pmi") {continue}
//if the file was created within the last 2 minutes, we should check if we need to modify it
if time.Now().Sub(v.ModTime()) < (time.Minute * 2) {
//open the file
f, err := os.Open(fmt.Sprintf("%s/%s", dir, v.Name()))
if err != nil {fmt.Printf("\tCouldn't open file: %s\n", v.Name()); continue}
defer f.Close()
//read all of the bytes of the file
bs, err := ioutil.ReadAll(f)
if err != nil {fmt.Printf("\tCouldn't read bytes from %s\n", v.Name()); continue}
//see if the <program_parameters/> tag is in the file
b := bytes.Contains(bs, []byte("<program_parameters/>"))
//if the tag is in the file, we should replace it, otherwise we move on to the next file
if b {
//replace the tag with nothing. Only look for the first instance and then abort the process of replacing.
rbs := bytes.Replace(bs, []byte("<program_parameters/>"), []byte(""), 1)
//close the file so we can delete it.
f.Close()
//delete the exisint file.
os.Remove(fmt.Sprintf("%s/%s", dir, v.Name()))
//create a new file with the same original name:
nf, err := os.Create(fmt.Sprintf("%s/%s", dir, v.Name()))
if err != nil {fmt.Printf("\tFailed to create new file for %s\n", v.Name()); continue}
//write all of the bytes that we have in memory to our new file.
_, err = nf.Write(rbs)
if err != nil {fmt.Println("Failed to write to new file %s\n", v.Name()); continue}
//close our new file
nf.Close()
fmt.Printf("Modified new file: %s", v.Name())
} else {
continue
}
}
}
fmt.Printf("\nDone with round\n")
}
fmt.Println("PROGRAM STOPPED RUNNING!!")
return
}```
您可以直接修改文件,无需将原始内容复制到内存中或创建新文件。
os.File
、os.Seek
和os.WriteAt
函数可用于查找文件中需要修改的位置。下面是一个更有效的示例,直接在文件中进行修改:
// Open the file
f, err := os.OpenFile(fmt.Sprintf("%s/%s", dir, v.Name()), os.O_RDWR, 0644)
if err != nil {
fmt.Printf("Couldn't open file: %s\n", v.Name())
continue
}
defer f.Close()
// Create a buffer to read the contents of the file
var buffer bytes.Buffer
_, err = buffer.ReadFrom(f)
if err != nil {
fmt.Printf("Couldn't read bytes from %s\n", v.Name())
continue
}
if strings.Contains(buffer.String(), "<program_parameters/>") {
// Find the position of the tag in the buffer
index := strings.Index(buffer.String(), "<program_parameters/>")
// Seek to the position in the file where the modification should be made
_, err := f.Seek(int64(index), 0)
if err != nil {
fmt.Printf("Couldn't seek to the position in %s\n", v.Name())
continue
}
// Write the modified content directly to the file
_, err = f.WriteAt([]byte(""), int64(index))
if err != nil {
fmt.Printf("Couldn't write to %s\n", v.Name())
continue
}
fmt.Printf("Modified file in place: %s\n", v.Name())
}
在此方法中,我们使用
os.OpenFile
打开文件以允许读取和写入。然后,我们将文件内容读入缓冲区,检查是否存在 os.O_RDWR
,寻找正确的位置,并使用 <program_parameters/>
将修改后的内容直接写入文件。