2013-03-25 82 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