Golang HotFolder文件修改

问题描述 投票:0回答:1

我有以下程序。它基本上查看文件夹并检查是否有任何新文件。如果它找到新文件,则会对该文件进行修改。然而,这样做的方式实际上效率低下并且存在缺陷。它将文件的原始内容复制到内存中,进行修改,删除原始文件,然后使用内存中的内容保存一个新文件。实际上,如果出现任何问题(可能会发生),一旦文件被删除,您就会丢失数据。理想情况下,我可以直接在文件中进行修改,而无需删除原始文件,从而需要保存一个新文件。从代码中可以看出,修改量很小。我不熟悉如何在 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 
}```
string go
1个回答
0
投票

您可以直接修改文件,无需将原始内容复制到内存中或创建新文件。

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/>
将修改后的内容直接写入文件。
    

© www.soinside.com 2019 - 2024. All rights reserved.