2016-05-13 5 views
2

Der folgende Code liest seine Werte aus dieser Datei:reader.ReadLine() nicht vorab nach einer scanner.Scan() aufrufen

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

und gedruckt werden soll: [ {1 2 3}, {-1 -2 -3} ]

Aber anstatt ich erhalten diese:

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

Es scheint, dass die reader.ReadLine() bleibt an der gleichen Stelle. Gibt es eine einfachere Methode zum Scannen von Linien und dann Werte innerhalb jeder Linie?

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

Antwort

3

Wenn Sie dies tun in der for Schleife:

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

Die nächste Zeile wird auf buffer angehängt. Das heißt, bevor die Schleife beginnt, buffer enthält 2 3, und dann nach 1.0 2.0 3.0 Lesen, es zu puffern angehängt wird, so dass der Inhalt 2 31.0 2.0 3.0 wird, , die Sie in newLine speichern. Da beginnen die Dinge seitwärts zu gehen.

Sie wollen wahrscheinlich die buffer löschen, bevor eine neue Zeile zu lesen:

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

Aber dann werden Sie weitere Probleme nach wie vor haben, hier:

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

Da die Leitung 1.0 2.0 3.0 enthält, die strconf.Atoi wird scheitern. Ich verstehe nicht den Zweck dieses Snippets, vielleicht können Sie es löschen (oder auskommentieren).

Mit dem oben fixiert, werden Sie noch ein weiteres Problem, auf dieser Linie:

  attributes = append(attributes, attribute) 

Da attributes nie zurückgesetzt, es wächst. Das heißt, nach der ersten Zeile wird es 1 2 3, enthalten und nach der zweiten Zeile wird es enthalten. Sie können das korrigieren, indem Sie die Deklaration attributes ohne die äußere Schleife wie folgt verschieben:

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