Skip to content

Instantly share code, notes, and snippets.

@klingtnet
Last active December 1, 2020 19:22
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save klingtnet/00e77b457cc8d90eaf0bfce955a9047e to your computer and use it in GitHub Desktop.
Save klingtnet/00e77b457cc8d90eaf0bfce955a9047e to your computer and use it in GitHub Desktop.
Read random lines from a file
// inspired by https://github.com/miku/randlines
package main
import (
"errors"
"io"
"log"
"math/rand"
"os"
"strconv"
)
func main() {
if len(os.Args) != 3 {
log.Fatalf("Usage: %s /file #lines\nExample: e.g. %s /some/file 100", os.Args[0], os.Args[0])
}
N, err := strconv.Atoi(os.Args[2])
if err != nil {
log.Fatal(err)
}
if N < 1 {
log.Fatalf("n must be > 0 but was %d", N)
}
path := os.Args[1]
f, err := os.Open(path)
if err != nil {
log.Fatal(err)
}
defer f.Close()
buf := make([]byte, 1<<10)
var cnt int64
var newlines []int64
for {
n, err := f.Read(buf)
if err != nil {
if n == 0 && errors.Is(err, io.EOF) {
break
}
log.Fatal(err)
}
for i := int64(0); i < int64(n); i++ {
if buf[i] == '\n' {
newlines = append(newlines, cnt+i+1)
}
}
cnt += int64(n)
}
for N > 0 {
i := 1 + rand.Intn(len(newlines)-1)
start, end := newlines[i-1], newlines[i]
_, err = f.Seek(start, 0)
if err != nil {
log.Fatal(err)
}
_, err = io.CopyN(os.Stdout, f, end-start)
if err != nil {
log.Fatal(err)
}
N--
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment