一尘不染

如何使用Golang自定义扫描器字符串文字并扩展内存以将整个文件加载到内存中?

go

我一直在试图弄清楚如何实现最初认为简单的程序。我有一个引号的文本文件,所有引号均以“ $$”分隔

我希望程序解析报价文件并随机选择3个引号来显示和标准输出。

文件中有1022个引号。

当我尝试分割文件时,出现此错误:缺少“

我似乎无法弄清楚如何为$$分配字符串文字,但我不断得到:
缺少’

这是自定义扫描仪:

onDollarSign := func(data []byte, atEOF bool) (advance int, token []byte, err error) {  
    for i := 0; i < len(data); i++ { 
        //if data[i] == "$$" {              # this is what I did originally
        //if data[i:i+2] == "$$" {    # (mismatched types []byte and string)
        //if data[i:i+2] == `$$` {    # throws (mismatched types []byte and string)
        // below throws syntax error: unexpected $ AND missing '
        if data[1:i+2] == '$$' {   
            return i + 1, data[:i], nil  
        }  
    }

如果我仅使用一个字符串文字,则可以正常工作$

由于某种原因, 仅71个报价被加载到报价切片中。 我不确定如何扩展。允许将所有1022行情存储在内存中。

我一直很难解决这个问题。这就是我现在所拥有的:

package main
import (  
    "bufio"  
    "fmt"  
    "log"  
    "math/rand"  
    "os"  
    "time"  
)

func main() {  
    rand.Seed(time.Now().UnixNano()) // Try changing this number!  
    quote_file, err := os.Open("/Users/bryan/Dropbox/quotes_file.txt")  
    if err != nil {  
        log.Fatal(err)  
    }  
    scanner := bufio.NewScanner(quote_file)  
    // define split function  
    onDollarSign := func(data []byte, atEOF bool) (advance int, token []byte, err error) {  
        for i := 0; i < len(data); i++ {  
            if data[i] == '$$' {  
                return i + 1, data[:i], nil  
            }  
        }  
        fmt.Print(data)  
        return 0, data, bufio.ErrFinalToken  
    }  
    scanner.Split(onDollarSign)  
    var quotes []string

    // I think this will scan the file and append all the parsed quotes into quotes  
    for scanner.Scan() {  
        quotes = append(quotes, scanner.Text())

    }  
    if err := scanner.Err(); err != nil {  
        fmt.Fprintln(os.Stderr, "reading input:", err)  
    }  
    fmt.Print(len(quotes))  
    fmt.Println("quote 1:", quotes[rand.Intn(len(quotes))])  
    fmt.Println("quote 2:", quotes[rand.Intn(len(quotes))])  
    fmt.Println("quote 3:", quotes[rand.Intn(len(quotes))])  
}

阅读 204

收藏
2020-07-02

共1个答案

一尘不染

如果最终还是要读取整个文件,则使用扫描仪会有些麻烦。我将阅读整个文件,然后将其拆分为引号列表:

package main

import (
    "bytes"
    "io/ioutil"
    "log"
    "math/rand"
    "os"
)

func main() {
    // Slurp file.
    contents, err := ioutil.ReadFile("/Users/bryan/Dropbox/quotes_file.txt")
    if err != nil {
            log.Fatal(err)
    }

    // Split the quotes
    separator := []byte("$$") // Convert string to []byte
    quotes := bytes.Split(contents, separator)

    // Select three random quotes and write them to stdout
    for i := 0; i < 3; i++ {
            n := rand.Intn(len(quotes))
            quote := quotes[n]

            os.Stdout.Write(quote)
            os.Stdout.Write([]byte{'\n'}) // new line, if necessary
    }
}

如果 读取文件 之前 选择了三个引号 则使用扫描仪将很有意义。那么您可以在到达最后一个报价后停止阅读。

2020-07-02