2016-05-13 24 views
2

下面的代碼從這個文件中讀取它的值:reader.ReadLine()一scanner.Scan後不進()調用

2 3\n 
1.0 2.0 3.0\n 
-1.0 -2.0 -3.0\n 

而且應該打印: [ {1 2 3}, {-1 -2 -3} ]

而是我得到這樣的:

[{2 [31 2 3]} {0 []}] strconv.ParseFloat: parsing "3.0-1.0": invalid syntax

看來,reader.ReadLine()停留在相同的位置。有沒有更簡單的方法來掃描線,然後每行內的值?

package main 

import (
    "bufio" 
    "bytes" 
    "fmt" 
    "os" 
    "strconv" 
    "strings" 
) 

type Example struct { 
    classLabel int 
    attributes []float64 
} 

func NewExample(classLabel int, attributes []float64) *Example { 
    return &Example{classLabel, attributes} 
} 

func readFile(path string) ([]Example, error) { 

    var (
     result  []Example 
     err   error 
     file   *os.File 
     part   []byte 
     size   int 
     attributeNum int 
    ) 

    if file, err = os.Open(path); err != nil { 
     return result, err 
    } 
    defer file.Close() 

    reader := bufio.NewReader(file) 
    buffer := bytes.NewBuffer(make([]byte, 0)) 

    if part, _, err = reader.ReadLine(); err != nil { 
     return result, err 
    } 
    buffer.Write(part) 
    newLine := buffer.String() 
    fmt.Println("newLine=" + newLine) 

    r := strings.NewReader(newLine) 
    scanner := bufio.NewScanner(r) 
    scanner.Split(bufio.ScanWords) 

    if scanner.Scan() { 
     size, err = strconv.Atoi(scanner.Text()) 
     if err != nil { 
      return result, err 
     } 
    } 
    fmt.Println("size=" + strconv.Itoa(size)) 

    if scanner.Scan() { 
     attributeNum, err = strconv.Atoi(scanner.Text()) 
     if err != nil { 
      return result, err 
     } 
    } 
    fmt.Println("attributeNum=" + strconv.Itoa(attributeNum)) 

    result = make([]Example, size) 

    var classLabel int 
    var attributes []float64 

    for k := 0; k < size; k++ { 
     if part, _, err = reader.ReadLine(); err != nil { 
      return result, err 
     } 
     buffer.Write(part) 
     newLine := buffer.String() 
     fmt.Println("newLine=" + newLine) 

     r := strings.NewReader(newLine) 
     scanner := bufio.NewScanner(r) 
     scanner.Split(bufio.ScanWords) 

     if scanner.Scan() { 
      classLabel, err = strconv.Atoi(scanner.Text()) 
      if err != nil { 
       return result, err 
      } 
     } 
     fmt.Println("classLabel=" + strconv.Itoa(classLabel)) 

     for i := 0; i < attributeNum; i++ { 
      var attribute float64 
      if scanner.Scan() { 
       attribute, err = strconv.ParseFloat(scanner.Text(), 64) 
       if err != nil { 
        return result, err 
       } 
       attributes = append(attributes, attribute) 
       fmt.Println("attribute=" + strconv.FormatFloat(attribute, 'f', -1, 64)) 
      } 
     } 
     result[k] = *NewExample(classLabel, attributes) 
    } 

    return result, scanner.Err() 
} 

func main() { 
    example, err := readFile("test.txt") 
    fmt.Println(example, err) 
} 

回答

3

當你這樣做for循環中:

buffer.Write(part) 
newLine := buffer.String() 
fmt.Println("newLine=" + newLine) 

下一行被追加到buffer。在循環開始 也就是說, 之前,buffer包含2 3, 然後閱讀1.0 2.0 3.0, 它被附加到緩衝區, 後使內容變得2 31.0 2.0 3.0, 您在newLine存儲。 這是事情開始橫向的地方。

你可能想讀每個新行之前清除buffer

buffer.Reset() 
buffer.Write(part) 
newLine := buffer.String() 
fmt.Println("newLine=" + newLine) 

但隨後你將有進一步的問題是,在這裏:

if scanner.Scan() { 
     classLabel, err = strconv.Atoi(scanner.Text()) 
     if err != nil { 
      return result, err 
     } 
    } 

由於行包含1.0 2.0 3.0strconf.Atoi將會失敗。 我不明白這段代碼的目的, 也許你可以刪除它(或註釋掉)。

有了固定的上面,你仍然會有更多的一個問題,在這條線:

  attributes = append(attributes, attribute) 

由於attributes永遠不會重置,規模還在不斷擴大。 也就是說,在第一行之後,它將包含1 2 3, ,在第二行之後它將包含1 2 3 -1 -2 -3。 您可以通過移動不帶外環的attributes聲明來糾正該問題,如下所示:

var attributes []float64 
    for i := 0; i < attributeNum; i++ { 
     var attribute float64 
     if scanner.Scan() { 
      attribute, err = strconv.ParseFloat(scanner.Text(), 64) 
      if err != nil { 
       return result, err 
      } 
      attributes = append(attributes, attribute) 
      fmt.Println("attribute=" + strconv.FormatFloat(attribute, 'f', -1, 64)) 
     } 
    } 
相關問題