如何在golang中创建一个充满"000000 ..."数据的10MB文件?

har*_*ass 1 file fsync go sparse-file

我打算在log或diskqueue这样的系统中使用fdatasync.第一件事是在文件系统中创建一个带有"000000 ..."的10MB文件,如ext4.但我不知道如何正确地做到这一点.

zzz*_*zzz 7

jnml@fsc-r630:~/src/tmp/SO/16797380$ ls -l
celkem 4
-rw-rw-r-- 1 jnml jnml 186 kv? 29 07:54 main.go
jnml@fsc-r630:~/src/tmp/SO/16797380$ cat main.go 
package main

import (
        "log"
        "os"
)

func main() {
        f, err := os.Create("foo.bar")
        if err != nil {
                log.Fatal(err)
        }

        if err := f.Truncate(1e7); err != nil {
                log.Fatal(err)
        }
}
jnml@fsc-r630:~/src/tmp/SO/16797380$ go run main.go 
jnml@fsc-r630:~/src/tmp/SO/16797380$ ls -l
celkem 4
-rw-rw-r-- 1 jnml jnml 10000000 kv? 29 07:55 foo.bar
-rw-rw-r-- 1 jnml jnml      186 kv? 29 07:54 main.go
jnml@fsc-r630:~/src/tmp/SO/16797380$ 
Run Code Online (Sandbox Code Playgroud)


Nic*_*ood 5

如果您使用的是unix,那么您可以非常快速地创建稀疏文件。稀疏文件用零 (ascii NUL) 填充,并且在写入之前实际上不会占用磁盘空间,但可以正确读取。

package main

import (
    "log"
    "os"
)

func main() {
    size := int64(10 * 1024 * 1024)
    fd, err := os.Create("output")
    if err != nil {
        log.Fatal("Failed to create output")
    }
    _, err = fd.Seek(size-1, 0)
    if err != nil {
        log.Fatal("Failed to seek")
    }
    _, err = fd.Write([]byte{0})
    if err != nil {
        log.Fatal("Write failed")
    }
    err = fd.Close()
    if err != nil {
        log.Fatal("Failed to close file")
    }
}
Run Code Online (Sandbox Code Playgroud)

它会生成一个 10MB 的文件,名为output.

$ ls -l output 
-rw-r--r-- 1 user user 10485760 May 28 18:58 output
$ du -hs output 
4.0K    output
Run Code Online (Sandbox Code Playgroud)

更新晚了

我在 rclone 中解决了这个问题。即预分配文件而不写入数据,或创建稀疏文件。你不能直接从标准库中做到这一点,而且它不是跨平台的,但使用带有标志的Fallocate系统调用FALLOC_FL_KEEP_SIZE是 Linux 中的方法。您也可以在 Windows 中执行此操作。

这里是windowslinux下相关代码的链接,这里是linux代码:

package main

import (
    "log"
    "os"
)

func main() {
    size := int64(10 * 1024 * 1024)
    fd, err := os.Create("output")
    if err != nil {
        log.Fatal("Failed to create output")
    }
    _, err = fd.Seek(size-1, 0)
    if err != nil {
        log.Fatal("Failed to seek")
    }
    _, err = fd.Write([]byte{0})
    if err != nil {
        log.Fatal("Write failed")
    }
    err = fd.Close()
    if err != nil {
        log.Fatal("Failed to close file")
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 相关手册页 [fdatasync](http://linux.die.net/man/2/fdatasync) 和 [stat](http://linux.die.net/man/2/stat)。写入文件的稀疏部分可能会更改**blkcnt_t**,因此它可能会更新元数据。无论如何,如果您追求终极性能,那么不要写入稀疏文件,因为写入时会产生更多开销。如果您想立即创建 1 GB 的备份文件,请使用稀疏文件! (2认同)