我打算在日志或磁盘队列等系统中使用 fdatasync。首先是在像 ext4 这样的文件系统中创建一个 10MB 的文件,其中包含“000000...”。但我不知道如何正确地做到这一点。
问问题
7695 次
4 回答
15
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$
于 2013-05-29T05:56:44.513 回答
4
如果您使用的是 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")
}
}
这会产生一个 10MB 的文件,名为output
.
$ ls -l output
-rw-r--r-- 1 user user 10485760 May 28 18:58 output
$ du -hs output
4.0K output
很久以后更新
我在 rclone 中解决了这个问题。即在不写入数据的情况下预分配文件,或创建稀疏文件。您不能直接从标准库中执行此操作,并且它不是跨平台的,但是使用带有标志的fallocate系统调用FALLOC_FL_KEEP_SIZE
是在 linux 中的方式。您也可以在 Windows 中执行此操作。
以下是windows和linux中相关代码的链接,这里是 linux 代码:
var (
fallocFlags = [...]uint32{
unix.FALLOC_FL_KEEP_SIZE, // Default
unix.FALLOC_FL_KEEP_SIZE | unix.FALLOC_FL_PUNCH_HOLE, // for ZFS #3066
}
fallocFlagsIndex int32
)
// preAllocate the file for performance reasons
func preAllocate(size int64, out *os.File) error {
if size <= 0 {
return nil
}
index := atomic.LoadInt32(&fallocFlagsIndex)
again:
if index >= int32(len(fallocFlags)) {
return nil // Fallocate is disabled
}
flags := fallocFlags[index]
err := unix.Fallocate(int(out.Fd()), flags, 0, size)
if err == unix.ENOTSUP {
// Try the next flags combination
index++
atomic.StoreInt32(&fallocFlagsIndex, index)
fs.Debugf(nil, "preAllocate: got error on fallocate, trying combination %d/%d: %v", index, len(fallocFlags), err)
goto again
}
// FIXME could be doing something here
// if err == unix.ENOSPC {
// log.Printf("No space")
// }
return err
}
于 2013-05-28T18:03:24.810 回答
1
尝试这个:
package foo
import "io"
func WriteBytes(w io.Writer, c byte, n uint) {
buf := make([]byte,0x1000)
for i := 0 ; i < len(buf) ; i++ {
buf[i] = c
}
for i := 0 ; i < n >> 24 ; i++ {
w.Write(buf)
}
w.Write(buf[:n & 0xfff])
}
于 2013-05-28T17:16:34.913 回答
-2
这将在当前目录中创建一个 10000000 字节的文件,名为testfile
.
package main
import (
"fmt"
"os"
)
func main() {
data := make([]byte, int(1e7), int(1e7)) // Initialize an empty byte slice
f, err := os.Create("testfile")
if err != nil {
fmt.Printf("Error: %s", err)
}
defer f.Close()
size, err := f.Write(data) // Write it to the file
if err != nil {
fmt.Printf("Error: %s", err)
}
fmt.Printf("%d bytes written", size)
}
希望有帮助。
于 2013-05-29T10:23:08.000 回答