2013-03-25 2 views
4

Я хочу создать 10 ГБ файл, который выглядит следующим образом:Создание большого файла CSV для тестирования доступа файла

prefix:username:timestamp, number 

Так пример, как:

login:jbill:2013/3/25, 1 

Я хочу создать 10GB файл, создав случайные строки, подобные приведенным выше.

Как я могу это сделать в Go?

я могу иметь массив префиксы:

login, logout, register 

А также массив имен пользователей:

jbill, dkennedy 
+0

насчет отметка времени и номер в конце, должны ли они оставаться неизменными? Каков допустимый диапазон этих двух, если они должны измениться на каждой записи? – topskip

+1

@ user1361315 Где моя проблема? Я не вижу этого. – nemo

+0

@topskip timestamp может быть любым допустимым временем в 2012 году. Номер может быть любым случайным числом между 1-100. – loyalflow

ответ

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

Это наивный подход (1 Гб):

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 сек на моей машине, я хотел бы видеть более быстрое решение.

КСТАТИ: вам нужно сделать случайных полей, рабочих, но что остается в качестве упражнения для читателя :)

+0

Отказ от ответственности: Я новичок, и код должен быть принят с осторожностью. Это может быть не лучшее решение. Это может даже не быть хорошим решением. – topskip

+0

26 секунд не так уж плохо :), так что в основном буферизованный писатель обертывает исходный файл. Как это добавляет новые строки? – loyalflow

+0

См. Строку с 'fmt.Sprintf' - это добавляет новую строку. Реальное приложение будет медленнее, так как 'fmt.Sprintf' нужно вызывать в каждом цикле, включая генерацию случайных чисел и поиск массива. – topskip