第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會(huì)有你想問的

如何使用 Scanner 從特定行號(hào)開始讀取文件?

如何使用 Scanner 從特定行號(hào)開始讀取文件?

Go
白衣非少年 2021-12-06 19:42:48
我是 Go 的新手,我正在嘗試編寫一個(gè)簡(jiǎn)單的腳本來逐行讀取文件。我還想在文件系統(tǒng)的某處保存進(jìn)度(即讀取的最后一行號(hào)),以便如果再次將相同的文件作為腳本的輸入,它會(huì)從它停止的行開始讀取文件。以下是我開始的內(nèi)容。package main// Package Importsimport (    "bufio"    "flag"    "fmt"    "log"    "os")// Variable Declarationvar (    ConfigFile = flag.String("configfile", "../config.json", "Path to json configuration file."))// The main function that reads the file and parses the log entriesfunc main() {    flag.Parse()    settings := NewConfig(*ConfigFile)    inputFile, err := os.Open(settings.Source)    if err != nil {        log.Fatal(err)    }    defer inputFile.Close()    scanner := bufio.NewScanner(inputFile)    for scanner.Scan() {        fmt.Println(scanner.Text())    }    if err := scanner.Err(); err != nil {        log.Fatal(err)    }}// Saves the current progressfunc SaveProgress() {}// Get the line count from the progress to make surefunc GetCounter() {}我在掃描儀包中找不到任何處理行號(hào)的方法。我知道我可以聲明一個(gè)整數(shù) saycounter := 0并在每次讀取一行時(shí)增加它c(diǎn)ounter++。但是下次我如何告訴掃描儀從特定行開始?因此,例如,如果我30下次使用相同的輸入文件運(yùn)行腳本時(shí)讀取直到行,我如何讓掃描儀從行開始讀取31?更新我在這里能想到的一種解決方案是使用我上面所說的計(jì)數(shù)器并使用如下所示的 if 條件。    scanner := bufio.NewScanner(inputFile)    for scanner.Scan() {        if counter > progress {            fmt.Println(scanner.Text())        }    }我很確定這樣的事情會(huì)起作用,但它仍然會(huì)遍歷我們已經(jīng)閱讀過的行。請(qǐng)?zhí)岢龈玫姆椒ā?
查看完整描述

3 回答

?
HUX布斯

TA貢獻(xiàn)1876條經(jīng)驗(yàn) 獲得超6個(gè)贊

如果您不想閱讀而只是跳過以前閱讀的行,則需要獲取上次中斷的位置。


不同的解決方案以函數(shù)的形式呈現(xiàn),該函數(shù)獲取要讀取的輸入和開始讀取行的起始位置(字節(jié)位置),例如:


func solution(input io.ReadSeeker, start int64) error

使用了一個(gè)特殊的io.Reader輸入,它也實(shí)現(xiàn)io.Seeker了通用接口,它允許跳過數(shù)據(jù)而不必讀取它們。*os.File實(shí)現(xiàn)了這一點(diǎn),因此您可以將 a 傳遞*File給這些函數(shù)。好的。在“合并”兩者的界面io.Reader和io.Seeker是io.ReadSeeker。


如果你想要一個(gè)干凈的開始(從文件的開頭開始讀?。?,只需通過start = 0. 如果要恢復(fù)先前的處理,請(qǐng)傳遞上次處理停止/中止的字節(jié)位置。這個(gè)位置就是pos下面函數(shù)(解)中局部變量的值。


下面的所有示例及其測(cè)試代碼都可以在Go Playground上找到。


1.與 bufio.Scanner

bufio.Scanner 不保持位置,但是我們可以很容易的擴(kuò)展它來保持位置(讀取的字節(jié)),所以當(dāng)我們下次要重新啟動(dòng)時(shí),我們可以尋找到這個(gè)位置。


為了以最少的努力做到這一點(diǎn),我們可以使用一個(gè)新的拆分函數(shù),將輸入拆分為標(biāo)記(行)。我們可以使用Scanner.Split()來設(shè)置拆分器功能(決定標(biāo)記/行邊界在哪里的邏輯)。默認(rèn)拆分函數(shù)是bufio.ScanLines().


我們來看看split函數(shù)的聲明: bufio.SplitFunc


type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error)

它返回要前進(jìn)的字節(jié)數(shù):advance。正是我們需要保持文件位置。所以我們可以使用 builtin 創(chuàng)建一個(gè)新的 split 函數(shù)bufio.ScanLines(),所以我們甚至不必實(shí)現(xiàn)它的邏輯,只需使用advance返回值來維護(hù)位置:


func withScanner(input io.ReadSeeker, start int64) error {

    fmt.Println("--SCANNER, start:", start)

    if _, err := input.Seek(start, 0); err != nil {

        return err

    }

    scanner := bufio.NewScanner(input)


    pos := start

    scanLines := func(data []byte, atEOF bool) (advance int, token []byte, err error) {

        advance, token, err = bufio.ScanLines(data, atEOF)

        pos += int64(advance)

        return

    }

    scanner.Split(scanLines)


    for scanner.Scan() {

        fmt.Printf("Pos: %d, Scanned: %s\n", pos, scanner.Text())

    }

    return scanner.Err()

}

2.與 bufio.Reader

在這個(gè)解決方案中,我們使用bufio.Reader類型而不是Scanner. 如果我們將字節(jié)作為分隔符傳遞,bufio.Reader已經(jīng)有一個(gè)ReadBytes()與“讀取一行”功能非常相似的方法'\n'。


這個(gè)解決方案類似于 JimB 的,增加了處理所有有效的行終止符序列,并將它們從讀取行中剝離(很少需要它們);在正則表達(dá)式中,它是\r?\n。


func withReader(input io.ReadSeeker, start int64) error {

    fmt.Println("--READER, start:", start)

    if _, err := input.Seek(start, 0); err != nil {

        return err

    }


    r := bufio.NewReader(input)

    pos := start

    for {

        data, err := r.ReadBytes('\n')

        pos += int64(len(data))

        if err == nil || err == io.EOF {

            if len(data) > 0 && data[len(data)-1] == '\n' {

                data = data[:len(data)-1]

            }

            if len(data) > 0 && data[len(data)-1] == '\r' {

                data = data[:len(data)-1]

            }

            fmt.Printf("Pos: %d, Read: %s\n", pos, data)

        }

        if err != nil {

            if err != io.EOF {

                return err

            }

            break

        }

    }

    return nil

}

注意:如果內(nèi)容以空行結(jié)尾(行終止符),本方案將處理空行。如果你不想要這個(gè),你可以簡(jiǎn)單地像這樣檢查它:


if len(data) != 0 {

    fmt.Printf("Pos: %d, Read: %s\n", pos, data)

} else {

    // Last line is empty, omit it

}

測(cè)試解決方案:

測(cè)試代碼將簡(jiǎn)單地使用"first\r\nsecond\nthird\nfourth"包含多行不同行終止的內(nèi)容。我們將使用strings.NewReader()來獲取io.ReadSeeker其來源為 a 的string。


測(cè)試代碼首先調(diào)用withScanner()并withReader()傳遞0start position: a clean start。在下一輪中,我們將傳遞一個(gè)起始位置,start = 14它的位置是 3. 行的位置,因此我們不會(huì)看到前 2 行已處理(打?。夯謴?fù)模擬。


func main() {

    const content = "first\r\nsecond\nthird\nfourth"


    if err := withScanner(strings.NewReader(content), 0); err != nil {

        fmt.Println("Scanner error:", err)

    }

    if err := withReader(strings.NewReader(content), 0); err != nil {

        fmt.Println("Reader error:", err)

    }


    if err := withScanner(strings.NewReader(content), 14); err != nil {

        fmt.Println("Scanner error:", err)

    }

    if err := withReader(strings.NewReader(content), 14); err != nil {

        fmt.Println("Reader error:", err)

    }

}

輸出:


--SCANNER, start: 0

Pos: 7, Scanned: first

Pos: 14, Scanned: second

Pos: 20, Scanned: third

Pos: 26, Scanned: fourth

--READER, start: 0

Pos: 7, Read: first

Pos: 14, Read: second

Pos: 20, Read: third

Pos: 26, Read: fourth

--SCANNER, start: 14

Pos: 20, Scanned: third

Pos: 26, Scanned: fourth

--READER, start: 14

Pos: 20, Read: third

Pos: 26, Read: fourth


查看完整回答
反對(duì) 回復(fù) 2021-12-06
?
呼喚遠(yuǎn)方

TA貢獻(xiàn)1856條經(jīng)驗(yàn) 獲得超11個(gè)贊

而不是使用 a Scanner,使用 a bufio.Reader,特別是ReadBytesorReadString方法。通過這種方式,您可以讀取每個(gè)行終止,并且仍然收到帶有行結(jié)尾的完整行。


r := bufio.NewReader(inputFile)


var line []byte

fPos := 0 // or saved position


for i := 1; ; i++ {

    line, err = r.ReadBytes('\n')

    fmt.Printf("[line:%d pos:%d] %q\n", i, fPos, line)


    if err != nil {

        break

    }

    fPos += len(line)

}


if err != io.EOF {

    log.Fatal(err)

}

您可以選擇任意存儲(chǔ)文件位置和行號(hào)的組合,下次開始時(shí),您可以使用inputFile.Seek(fPos, os.SEEK_SET)移動(dòng)到上次中斷的位置。


查看完整回答
反對(duì) 回復(fù) 2021-12-06
?
繁花不似錦

TA貢獻(xiàn)1851條經(jīng)驗(yàn) 獲得超4個(gè)贊

如果您想使用 Scanner,您必須通過文件的請(qǐng)求,直到找到GetCounter()行尾符號(hào)。


scanner := bufio.NewScanner(inputFile)

// context line above


// skip first GetCounter() lines

for i := 0; i < GetCounter(); i++ {

    scanner.Scan()

}


// context line below

for scanner.Scan() {

    fmt.Println(scanner.Text())

}

或者,您可以在計(jì)數(shù)器中存儲(chǔ)偏移量而不是行號(hào),但請(qǐng)記住,使用 Scanner 時(shí)終止標(biāo)記被剝離,對(duì)于新行,標(biāo)記是\r?\n(正則表達(dá)式符號(hào)),因此不清楚是否應(yīng)該將 1 或 2 添加到文本長度:


// Not clear how to store offset unless custom SplitFunc provided

inputFile.Seek(GetCounter(), 0)

scanner := bufio.NewScanner(inputFile)

因此最好使用以前的解決方案或根本不使用 Scanner。


查看完整回答
反對(duì) 回復(fù) 2021-12-06
  • 3 回答
  • 0 關(guān)注
  • 396 瀏覽

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)