2013-03-25 84 views
4

我想創建一個10 GB的文件,看起來像:創建測試文件訪問CSV文件較大

prefix:username:timestamp, number 

因此,一個例子是這樣的:

login:jbill:2013/3/25, 1 

我想創建一個10GB文件,通過創建像上面那樣的隨機行。

我怎麼能在Go中做到這一點?

我可以具有前綴等的數組:

login, logout, register 

並且還用戶名的數組:

jbill, dkennedy 
+0

怎麼樣時間戳和結尾的數字應該保持不變嗎?如果每個條目都改變,這兩個允許的範圍是多少? – topskip 2013-03-25 16:08:08

+1

@ user1361315您的實際問題在哪裏?我看不到它。 – nemo 2013-03-25 16:14:21

+0

@topskip時間戳可以是2012年的任何有效時間。該數字可以是1-100之間的任意隨機數。 – loyalflow 2013-03-25 16:19:38

回答

4

例如,

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 
3

這是一種簡單方法(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,但畢竟是作爲練習留給讀者:)

+0

聲明:我是新手,代碼應小心謹慎。這可能不是最好的解決方案。這可能不是一個好的解決方案。 – topskip 2013-03-25 16:52:34

+0

26秒沒那麼差:)所以基本上緩衝的作家包裝原始文件。這是如何添加換行符的? – loyalflow 2013-03-25 17:43:27

+0

查看帶'fmt.Sprintf'的行 - 這會添加一個換行符。真正的應用程序會更慢,因爲必須在每個循環中調用'fmt.Sprintf',包括隨機數生成和數組查找。 – topskip 2013-03-25 17:51:22