doujing5846 2016-05-13 09:15
浏览 87
已采纳

reader.ReadLine()在scanner.Scan()调用后未前进

The code below reads its values from this file:

2 3

1.0 2.0 3.0

-1.0 -2.0 -3.0

And should print: [ {1 2 3}, {-1 -2 -3} ]

But instead I get this:

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

It seems that the reader.ReadLine() stays at the same location. Is there a simpler way to scan lines, then values inside each line?

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)
}
  • 写回答

1条回答 默认 最新

  • doutuo2829 2016-05-13 09:53
    关注

    When you do this inside the for loop:

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

    The next line gets appended to buffer. That is, before the loop begins, buffer contains 2 3, and then after reading 1.0 2.0 3.0, it gets appended to buffer, so the content becomes 2 31.0 2.0 3.0, which you store in newLine. That's where things start to go sideways.

    You probably want to clear the buffer before reading each new line:

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

    But then you will have further problems still, here:

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

    Since the line contains 1.0 2.0 3.0, the strconf.Atoi is going to fail. I don't understand the purpose of this snippet, perhaps you can delete it (or comment out).

    With the above fixed, you will still have one more problem, on this line:

              attributes = append(attributes, attribute)
    

    Since attributes is never reset, it keeps growing. That is, after the first line, it will contain 1 2 3, and after the second line it will contain 1 2 3 -1 -2 -3. You could correct that by moving the declaration of attributes without the outer loop, like this:

        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))
            }
        }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 javaweb项目无法正常跳转
  • ¥15 VMBox虚拟机无法访问
  • ¥15 skd显示找不到头文件
  • ¥15 机器视觉中图片中长度与真实长度的关系
  • ¥15 fastreport table 怎么只让每页的最下面和最顶部有横线
  • ¥15 R语言卸载之后无法重装,显示电脑存在下载某些较大二进制文件行为,怎么办
  • ¥15 java 的protected权限 ,问题在注释里
  • ¥15 这个是哪里有问题啊?
  • ¥15 关于#vue.js#的问题:修改用户信息功能图片无法回显,数据库中只存了一张图片(相关搜索:字符串)
  • ¥15 texstudio的问题,