文件内容覆盖出现问题

huangapple go评论77阅读模式
英文:

Trouble overwriting file content

问题

我遇到了一个问题,无法用零覆盖文件的内容。问题是即使我超过文件大小100个字节,原始文件的最后一个字节仍然存在。有人知道我漏掉了什么吗?

func (h PostKey) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    f, err := os.Create("received.dat")
    if err != nil {
        w.WriteHeader(http.StatusInternalServerError)
        return
    }
    defer f.Close()

    _, err = io.Copy(f, r.Body)
    if err != nil {
        w.WriteHeader(http.StatusInternalServerError)
        return
    }

    // 获取文件大小
    size, _ := f.Seek(0, 1)
    zeroFilled := make([]byte, size + 100)
    n, err := f.WriteAt(zeroFilled, 0)
    if err != nil {
        return
    }

    fmt.Printf("Size: %d\n", size) // 输出 13
    fmt.Printf("Bytes written: %d\n", n) // 输出 113
}

以上是你提供的代码。

英文:

I've got trouble overwriting a files content with zeros. The problem is that the very last byte of the original file remains, even when I exceed its size by 100 bytes. Someone got an idea what I'm missing?

func (h PostKey) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	f, err := os.Create("received.dat")
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	defer f.Close()

	_, err = io.Copy(f, r.Body)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

    // Retrieve filesize
    size, _ := f.Seek(0, 1)
    zeroFilled := make([]byte, size + 100)
    n, err := f.WriteAt(zeroFilled, 0)
    if err != nil {
        return
    }

    fmt.Printf("Size: %d\n", size) // prints 13
    fmt.Printf("Bytes written: %d\n", n) // prints 113
}

答案1

得分: 1

问题可能是因为数据被写入同一个文件(共享资源)中的http处理程序,并且处理程序本身可能会并发执行。在数据序列化(覆盖过程)期间,您需要锁定对文件的访问。快速解决方案如下:

import (
   "sync"
   //... 其他包
)

var muFile sync.Mutex

func (h PostKey) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    muFile.Lock()
    defer muFile.Unlock()

    f, err := os.Create("received.dat")
    //其他语句
    //...
}

如果您的服务器负载较低,上述解决方案将是可行的。但是,如果您的服务器需要同时处理大量请求,您需要使用不同的方法(尽管规则相同,即锁定对任何共享资源的访问)。

英文:

The problem may occurred because the data is written into a same file (shared resource) inside an http handler, and the handler itself may be executed concurrently. You need to lock access to the file during data serialization (overwriting process). Quick solution will be:

import (
   "sync"
   //... other packages
)

var muFile sync.Mutex

func (h PostKey) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    muFile.Lock()
    defer muFile.Unlock()

    f, err := os.Create("received.dat")
    //other statements
    //...
}

If your server load is low, the above solution will be fine. But if your server needs to handle a lot of requests concurrently, you need to use different approach (although the rule is the same, lock access to any shared resource).

答案2

得分: 0

我正在写入文件并尝试在同一上下文中进行覆盖,因此第一次写入操作的部分仍然在内存中,尚未写入磁盘。通过在复制正文内容后使用f.Sync()来刷新所有内容,我成功解决了这个问题。

英文:

I was writing to the file and trying to overwrite it in the same context, and so parts of the first write operation were still in memory and not yet written to the disk. By using f.Sync() to flush everything after copying the bodys content I was able to fix the issue.

huangapple
  • 本文由 发表于 2017年4月24日 00:44:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/43573849.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定