2016-06-25 44 views
0

我試圖用包含一個鍵,一個空格,一個數字和一個換行符的行來解析一個文件。更好的方法使用掃描儀每行多個標記?

我的代碼有效,但它並不適合我。有沒有更好的方式來使用掃描儀?特別是,我不喜歡在for循環中沒有任何保護的情況下使用Scan()。

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

我不會ScanWords分裂。似乎在換行符上分割會更加習慣,因爲這確保了每次迭代的1個分組。然後在迭代中使用'strings.Split()'。通俗易懂,易於被他人閱讀,並理解邏輯在做什麼。 – eduncan911

回答

3

input你不應該使用\n,始終檢查錯誤。
工作示例代碼:

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) 
    } 
} 

輸出:

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

您也可以使用Fscan,其掃描到所需的類型,像這樣:

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) 
    } 
} 

輸出:

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

謝謝。有趣的是,Scanner比我的系統上的Fscan快5倍-10倍,反覆做100k行文件。 –

+0

@ adapt-dev:如果你正在尋找更快的輸入掃描,請參閱:http://stackoverflow.com/questions/31333353/faster-input-scanning –

1

事實上,它是完全安全的,因爲Scan()驗證輸入並設置了Err()可能會遇到的錯誤。

因此,如果您想檢查Scan()是否失敗,則必須在循環結束時執行此操作,如許多examples中所示。

你的代碼是768,16:

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) 
    } 

}