2016-06-25 4 views
0

Ich versuche, eine Datei mit Zeilen zu analysieren, die aus einem Schlüssel, einem Leerzeichen, einer Zahl und dann einem Zeilenumbruch bestehen.eine bessere Möglichkeit, Scanner für mehrere Token pro Zeile zu verwenden?

Mein Code funktioniert, aber es riecht nicht richtig zu mir. Gibt es eine bessere Möglichkeit, den Scanner zu verwenden? Insbesondere mag ich es nicht, den Scan() innerhalb der for-Schleife ohne Schutz zu haben.

func TestScanner(t *testing.T) { 
    const input = `key1 62128128\n 
key2 8337182720\n 
key3 7834959872\n 
key4 18001920\n 
key5 593104896\n` 
    scanner := bufio.NewScanner(strings.NewReader(input)) 
    scanner.Split(bufio.ScanWords) 
    for scanner.Scan() { 
     key := scanner.Text() 
     scanner.Scan() 
     value := scanner.Text(); 
     fmt.Printf("k: %v, v: %v\n", key, value) 
    } 
} 
+1

ich nicht auf scanwords aufgeteilt würde. scheint es idiomatischer zu sein, sich auf Zeilenumbrüche aufzuteilen, da dies eine Gruppierung pro Iteration sicherstellt. Dann innerhalb der Iteration mit 'strings.Split()'. idiomatisch wie in einfacher zu lesen von anderen und zu verstehen, was die Logik tut. – eduncan911

Antwort

3

sollten Sie nicht \n in input, verwenden und immer auf Fehler überprüfen.
Arbeitsbeispielcode:

package main 

import (
    "bufio" 
    "fmt" 
    "strings" 
) 

func main() { 
    const input = `key1 62128128 
key2 8337182720 
key3 7834959872 
key4 18001920 
key5 593104896` 
    scanner := bufio.NewScanner(strings.NewReader(input)) 
    scanner.Split(bufio.ScanWords) 
    for scanner.Scan() { 
     key := scanner.Text() 
     if !scanner.Scan() { 
      break 
     } 
     value := scanner.Text() 
     fmt.Printf("k: %v, v: %v\n", key, value) 
    } 
} 

Ausgang:

k: key1, v: 62128128 
k: key2, v: 8337182720 
k: key3, v: 7834959872 
k: key4, v: 18001920 
k: key5, v: 593104896 

Auch Sie können Fscan verwenden, die auf die gewünschte Art durchsucht, wie folgt aus:

package main 

import "fmt" 
import "strings" 

func main() { 
    const input = `key1 62128128 
key2 8337182720 
key3 7834959872 
key4 18001920 
key5 593104896` 
    rdr := strings.NewReader(input) 
    for { 
     k, v := "", 0 
     n, _ := fmt.Fscan(rdr, &k, &v) 
     if n != 2 { 
      //fmt.Println(err) 
      break 
     } 
     fmt.Printf("%T: %[1]v, %T: %[2]v\n", k, v) 
    } 
} 

Ausgang:

string: key1, int: 62128128 
string: key2, int: 8337182720 
string: key3, int: 7834959872 
string: key4, int: 18001920 
string: key5, int: 593104896 
+0

Danke. Interessanterweise ist der Scanner etwa 5x-10x schneller als Fscan auf meinem System und wiederholt immer 100k Liniendateien. –

+0

@ adapt-dev: Wenn Sie nach schneller Eingabe Scannen suchen, siehe: http://StackOverflow.com/Questions/31333353/Faster-Input-Scanning –

1

Eigentlich ist das vollkommen sicher, da Scan() die Eingabe validiert und einen Fehler setzt, den man mit Err() bekommen kann.

Wenn Sie also überprüfen möchten, ob Scan() fehlschlägt, müssen Sie es am Ende der Schleife tun, wie in vielen examples gezeigt.

Ihr Code shoud sein:

func TestScanner(t *testing.T) { 
    const input = `key1 62128128 
key2 8337182720 
key3 7834959872 
key4 18001920 
key5 593104896` 
    scanner := bufio.NewScanner(strings.NewReader(input)) 
    scanner.Split(bufio.ScanWords) 
    for scanner.Scan() { 
     key := scanner.Text() 
     scanner.Scan() 
     value := scanner.Text(); 
     fmt.Printf("k: %v, v: %v\n", key, value) 
    } 

    if err := scanner.Err(); err != nil { 
     fmt.Printf("Invalid input: %s", err) 
    } 

} 
Verwandte Themen