哦, 这该死的txt回车符~

  • 今天的golang学习被txt中的回车符困扰了半个小时, 最后才傻傻的发现, mark一下

问题描述

我想从两个文件 test1.txttest2.txt中分别按行读取字符串, 然后统计字符串的出现次数.
两文件内容分别如下, 是我手动键入的:

test1
test2
test2
test1
  • 按照逻辑来说, 最终统计结果是, test1test2都分别出现两次,
  • 但是结果却并不如我所想, map中有四个字符串, 打印出来是
test1
test1
test2
test2

明明它们都一样, 怎么统计的呀, 难道是golang的map有问题???

  • 遇事先想自己的问题, 不能怀疑语言, 不能怀疑编译器, 这是从百度面试官那里学到的
    我的代码如下
package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"strings"
)

func main()  {
    
    
	//fmt.Println("dup3,test filename")
	counts := make(map[string]int)
	filenames := []string{
    
    "data\\test1.txt","data\\test2.txt"}
	for _,fileName := range filenames{
    
    
		data, err := ioutil.ReadFile(fileName) // 返回字节数组, 以及错误类型
		//fmt.Println(data)
		if err != nil{
    
    
			fmt.Fprintf(os.Stderr, "dup3: %v\n", err)
			continue
		}
		for _,str := range strings.Split(string(data),"\n"){
    
    
			counts[str]++
		}
	}

	for line,cnt := range counts{
    
    
		if cnt >1 {
    
    
			fmt.Printf("%d\t%s\n",cnt,line)
		}
	}
}

问题分析与解决

  • 为什么test1test1不同呢, 它们明明是同一个字符串
  • 经过思考, 我猜到了答案, 回车符, 然后就是验证
  • 原因在于, readFile是读入的字节切片, 而不是按行读入
  • 我们将readFile读取到的字节切片直接打印, 可以得到如下结果
[116 101 115 116 49 13 10 116 101 115 116 50]
[116 101 115 116 50 13 10 116 101 115 116 49]
  • 这是因为我在敲txt的时候, 习惯性敲了回车键, ascll码13对应的就是\r, 即回车, 而10对应的就是换行
  • 所以原因是因为我手敲的文件内容, 其中为了换行, 用了回车符, 而换行本身又是\n, 所以在上面我们用/n来进行split会产生长度为6和长度为5的字符串, 分别是test1\rtest1,test2\rtest2, 自然又不一样了, 然后打印出来, 因为经过了系统函数的格式化, 删除了回车符, 所以看起来都一样, 于是搞不清是哪出了问题
  • 这个问题只是因为我们手敲导致, 如果是代码写入txt, 那么一般都不会使用回车符+换行符, 而是直接使用换行符, 则没有本文的问题出现
  • 解决方法为, 将splitsep换成\r\n即可
  • 然后就能正确打印结果啦
    在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_34687559/article/details/120121621