我想創建一個10 GB的文件,看起來像:創建測試文件訪問CSV文件較大
prefix:username:timestamp, number
因此,一個例子是這樣的:
login:jbill:2013/3/25, 1
我想創建一個10GB文件,通過創建像上面那樣的隨機行。
我怎麼能在Go中做到這一點?
我可以具有前綴等的數組:
login, logout, register
並且還用戶名的數組:
jbill, dkennedy
我想創建一個10 GB的文件,看起來像:創建測試文件訪問CSV文件較大
prefix:username:timestamp, number
因此,一個例子是這樣的:
login:jbill:2013/3/25, 1
我想創建一個10GB文件,通過創建像上面那樣的隨機行。
我怎麼能在Go中做到這一點?
我可以具有前綴等的數組:
login, logout, register
並且還用戶名的數組:
jbill, dkennedy
例如,
package main
import (
"bufio"
"fmt"
"math/rand"
"os"
"strconv"
"time"
)
func main() {
fileSize := int64(10e9) // 10GB
f, err := os.Create("/tmp/largefile")
if err != nil {
fmt.Println(err)
return
}
w := bufio.NewWriter(f)
prefixes := []string{"login", "logout", "register"}
names := []string{"jbill", "dkennedy"}
timeStart := time.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC)
timeDur := timeStart.AddDate(1, 0, 0).Sub(timeStart)
rand.Seed(time.Now().UnixNano())
size := int64(0)
for size < fileSize {
// prefix:username:timestamp, number
// login:jbill:2012/3/25, 1
prefix := prefixes[int(rand.Int31n(int32(len(prefixes))))]
name := names[int(rand.Int31n(int32(len(names))))]
time := timeStart.Add(time.Duration(rand.Int63n(int64(timeDur)))).Format("2006/1/2")
number := strconv.Itoa(int(rand.Int31n(100) + 1))
line := prefix + ":" + name + ":" + time + ", " + number + "\n"
n, err := w.WriteString(line)
if err != nil {
fmt.Println(n, err)
return
}
size += int64(len(line))
}
err = w.Flush()
if err != nil {
fmt.Println(err)
return
}
err = f.Close()
if err != nil {
fmt.Println(err)
return
}
fmt.Println("Size:", size)
}
輸出:
register:jbill:2012/8/24, 15
login:jbill:2012/10/7, 98
register:dkennedy:2012/8/29, 70
register:jbill:2012/6/1, 89
register:jbill:2012/5/24, 63
login:dkennedy:2012/3/29, 48
logout:jbill:2012/7/8, 93
logout:dkennedy:2012/1/12, 74
login:jbill:2012/4/12, 14
login:jbill:2012/2/5, 83
這是一種簡單方法(1GB):
package main
import (
"fmt"
"log"
"os"
)
func main() {
myfile, err := os.OpenFile("myfile", os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
log.Fatal(err)
}
defer myfile.Close()
var pos int
var line string
// sample: login:jbill:2013/3/25, 1
line = fmt.Sprintf("%s:%s:%s, %d\n", "login", "jbill", "2013/3/25", 1)
for pos < 1024*1024*1024 {
bytes, err := myfile.Write([]byte(line))
if err != nil {
log.Fatal(err)
}
pos = pos + bytes
}
}
這需要永遠(1:16),因爲輸出沒有被緩衝。通過添加BUFIO就可以減少時間大大
package main
import (
"bufio"
"fmt"
"log"
"os"
)
func main() {
myfile, err := os.OpenFile("myfile", os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
log.Fatal(err)
}
defer myfile.Close()
mybufferedfile := bufio.NewWriter(myfile)
var pos int
var line string
// sample: login:jbill:2013/3/25, 1
line = fmt.Sprintf("%s:%s:%s, %d\n", "login", "jbill", "2013/3/25", 1)
for pos < 1024*1024*1024 {
bytes, err := mybufferedfile.WriteString(line)
if err != nil {
log.Fatal(err)
}
pos = pos + bytes
}
err = mybufferedfile.Flush()
if err != nil {
log.Fatal(err)
}
}
不過我的機器上26秒,我想看到一個更快的解決方案。
BTW:你需要做隨機的Fileds,但畢竟是作爲練習留給讀者:)
怎麼樣時間戳和結尾的數字應該保持不變嗎?如果每個條目都改變,這兩個允許的範圍是多少? – topskip 2013-03-25 16:08:08
@ user1361315您的實際問題在哪裏?我看不到它。 – nemo 2013-03-25 16:14:21
@topskip時間戳可以是2012年的任何有效時間。該數字可以是1-100之間的任意隨機數。 – loyalflow 2013-03-25 16:19:38