最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

哦, 这该死的txt回车符~

IT圈 admin 1浏览 0评论

哦, 这该死的txt回车符~

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

问题描述

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

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

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

  • 遇事先想自己的问题, 不能怀疑语言, 不能怀疑编译器, 这是从百度面试官那里学到的
    我的代码如下
package mainimport ("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即可
  • 然后就能正确打印结果啦

哦, 这该死的txt回车符~

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

问题描述

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

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

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

  • 遇事先想自己的问题, 不能怀疑语言, 不能怀疑编译器, 这是从百度面试官那里学到的
    我的代码如下
package mainimport ("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即可
  • 然后就能正确打印结果啦

与本文相关的文章

发布评论

评论列表 (0)

  1. 暂无评论