golang: read text file line by line of int strings

huangapple go评论85阅读模式
英文:

golang: read text file line by line of int strings

问题

我正在处理一个包含整数列表的输入文件,它以字符串形式存在。

我选择使用ReadString('\n')方法逐行读取它。

以下是代码示例:

line, error := inputReader.ReadString('\n')
lineStr := string(line)

控制台输出(长度和值):

lineStr %v 4
lineStr %v 10

lineStr 的长度为"4",可能是由于 rune 编码的原因。

然后,我尝试了几种方法将其转换为简单的整数,但都没有成功。

示例1

num, _ := strconv.ParseUint(lineStr, 0, 64)

输出的 num 为 0(应该是 10)。

示例2

num, _ := strconv.Atoi(lineStr)

输出的 num 为 0(应该是 10)。

示例3

num, _ := strconv.Atoi("10")

输出的 num 为 10(正确)。

示例4

num, _ := strconv.ParseUint("10", 0, 64)

输出的 num 为 10(正确)。

字符串字面量是可以正常工作的,但是从文件中读取的字符串却无法正常工作,这是什么问题?

提前感谢您的帮助!

英文:

I am dealing with an input file containing a list of integers as a string

10
..

I have choosen to read it line by line with ReadString('\n') method

The following code

line, error := inputReader.ReadString('\n')
lineStr := string(line)

console output (length and value)

lineStr %v 4
lineStr %v 10

lineStr as a length of "4", maybe because of rune encoding.

Then I have tried several way to convert it to simple integer but with no success.

Ex1

num, _ := strconv.ParseUint(lineStr, 0, 64)

ouputs a num of 0 (should be 10)

Ex2

num, _ := strconv.Atoi(lineStr)

ouputs a num of 0 (should be 10)

Ex3

num, _ := strconv.Atoi("10")

ouputs a num of 10 (ok)

Ex4

num, _ := strconv.ParseUint("10", 0, 64)

ouputs a num of 10 (ok)

string in literal are ok but string from file do not work, what is wrong ?

thanks in advance

答案1

得分: 4

从文档中可以看到:"ReadString 会读取输入直到第一个分隔符出现为止,并返回包含分隔符在内的数据的字符串。"

因此,我建议您使用一个扫描器(scanner),它可以像您期望的那样处理这种情况:

scanner := bufio.NewScanner(file)
for scanner.Scan() {
    lineStr := scanner.Text()
    num, _ := strconv.Atoi(lineStr)
    fmt.Println(lineStr, num)
}
英文:

From the documentation: "ReadString reads until the first occurrence of delim in the input, returning a string containing the data up to and including the delimiter."

Because of this, i suggest you use a scanner, which handles this case like you would expect:

scanner := bufio.NewScanner(file)
for scanner.Scan() {
	lineStr := scanner.Text()
	num, _ := strconv.Atoi(lineStr)
	fmt.Println(lineStr, num)
}

答案2

得分: 1

如果你查看ReadString的文档,你会注意到返回的string将包括分隔符(在你的情况下是\n)。

ReadString会读取输入直到第一个分隔符出现,返回一个包含数据和分隔符的字符串。

由于读取10后行的长度为4,我会假设行是由\r\n分隔的。最简单的方法是使用其中一个Trim函数(比如TrimSpace)来移除它。

英文:

If you look at the documentation of ReadString you will notice that the string returned will include the delimiter (in your case \n).

> ReadString reads until the first occurrence of delim in the input,
> returning a string containing the data up to and including the
> delimiter.

And because the length of the line after reading 10 is 4 I would assume that the lines are delimited by \r\n. The easiest way to remove it is using one of the Trim functions (like TrimSpace).

答案3

得分: 1

引用bufio.Reader.ReadString的文档(重点在于):

ReadString会读取输入直到第一个分隔符出现为止,返回一个包含数据的字符串,包括分隔符在内

现在,引用strconv.ParseInt的文档:

ParseInt返回的错误具有具体类型*NumError,并包括err.Num = s。如果s为空或包含无效的数字,err.Err = ErrSyntax,并且返回值为0

你的问题是ReadString方法还会返回终止行的\n字符,而这是ParseInt函数无效的字符。

你可以使用以下代码片段来检查真正的错误:

i, err := strconv.ParseInt(line, 10, 64)
if err != nil {
    switch err.(*strconv.NumError).Err {
        case strconv.ErrSyntax:
            fmt.Println("语法错误")
        case strconv.ErrRange:
            fmt.Println("超出范围的值")
    }
}

建议:使用strings.TrimSpace来清理你的输入。

英文:

Citing the documentation of bufio.Reader.ReadString (emphasis mine):

> ReadString reads until the first occurrence of delim in the input, returning a string containing the data up to and including the delimiter.

Now, the documentation of strconv.ParseInt

> The errors that ParseInt returns have concrete type *NumError and include err.Num = s. If s is empty or contains invalid digits, err.Err = ErrSyntax and the returned value is 0

Your problem is that the ReadString method return also the \n that terminate the line, which is an invalid character for the ParseInt function.

You can check the real error with the following snippet

i, err := strconv.ParseInt(line, 10, 64)
if err != nil {
    switch err.(*strconv.NumError).Err {
        case strconv.ErrSyntax:
            fmt.Println("syntax error")
        case strconv.ErrRange:
            fmt.Println("out of range value")
    }
}

Advice: use strings.TrimSpace to clean your input.

huangapple
  • 本文由 发表于 2015年3月11日 18:16:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/28983831.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定