多数程序员都会在不经意间遇到下面这两个问题:

1.  linux上用vim写的文件test.txt拷贝到windows上, 结果所有的内容都显示在一行中。(当然, 如果你Windows上的编辑显示器够智能, 那就是另外一回事了)

2. Windows上建立的test.txt拷贝到linux上, 结果linux程序运行异常。(当然, 如果你的linux程序足够健壮, 那就没有问题了)

ps. 当你在Windows上写好linux shell script, 拷贝到linux下运行, 就会出问题。

为什么会出现上面的问题呢? 这就需要我们了解\r\n和\n了。

我们先以Windows为例来说明。 我们来新建一个dos.txt文件, 然后在第一行敲一下enter键, 然后保存文件。 此时, 我们查一下这个文件的大小, 结果发现是2个字节(而不是1个), 用UltraEdit查阅一下, 就知道文件中的两个字节是0x0d和0x0a, 也就是\r和\n.  但是, 如果用C程序来读取dos.txt文件, 发现又根本没有读取到\r, 这是怎么回事呢? 原来: 在Windows上的dos.txt文件中, 按一下enter键, 实际上就相当于C程序写\n字符,而由于历史原因, 写文件的时候, Windows系统会自动在\n前面加上\r, 这样, dos.txt文件中就有了\r\n了, 在读取的时候, Windows系统会自动去掉\r, 所以你的C程序根本读不读\r, 还是\n.

实话实说, 我发现很多地方讲\r\n和\n, 都说得不太清楚, 下面我来说一下, 希望是更清楚, 而不是更模糊

Windows系统中有如下等价关系:

用enter换行 <====> 程序写\n  <====> 真正朝文件中写\r\n(0x0d0x0a) <====>程序真正读取的是\n

linux系统中的等价关系:

  用enter换行 <====> 程序写\n  <====> 真正朝文件中写\n(0x0a)  <====> 程序真正读取的是\n

现在, 我们看看本文开头部分的问题。 假设有一个linux下的unix.txt文件,  那么, 它在文件中的换行标志是:\n, 现在把unix.txt拷贝靠Windows上, 那好啊, Windows那双犀利的眼神仿佛是在对unix.txt文件说: 别跟我整什么\n, 我只认识文件中的\r\n, 如果你这个unix.txt文件里面有\r\n, 那我就认为是换行符, 否则, 我不认你。 如此一来, Windows压根就找不到unix.txt中的\r\n, 所以, 对于Windows而言, 压根就没有发现unix.txt有任何换行, 所以, 我们从Windows上看到的unix.txt文件显示在一行里面。

同理, 假设Windows上有一个dos.txt文件, 那么, 它在文件中的换行标志是\r\n, 现在拷贝到linux下, 那好啊, 正如linus一样, linux这个倔强的家伙貌似在说: 别的我不管, 我遇到文件中的\n, 我就认为是换行, 至于其他的, 我只认为是正常的字符。 如此一来, \r就被当成了文件的正常部分, 也就是说, linux下的C程序不仅仅会读取到\n, 也会读取到它前面的\r.

实际上Windows上的文件是dos格式的, 而linux上的文件是unix格式的, 我们可以通过linux上的dos2unix和unix2dos来实现转化, 当然, 有的linux环境下, 需要用busybox dos2unix和busybox unix2dos.

下面, 我们用程序来简要验证一下上面的部分叙述。 现在Windows上创建一个dos.txt文件, 第一行写入12, 然后按enter, 然后在第二行写入3, 不按enter, 然后保存。 我们先来看看Windows上的程序:

// VC++6.0#include <stdio.h>
#include <string.h>int main()
{char szTest[100] = {0};int len = 0;FILE *fp = fopen("dos.txt", "r");if(NULL == fp){printf("failed to open dos.txt\n");return 1;}fgets(szTest, sizeof(szTest) - 1, fp);len = strlen(szTest);if('\n' == szTest[len - 1]){printf("yes1\n");}if('\r' == szTest[len - 2]){printf("yes2\n");}memset(szTest, 0, sizeof(szTest));fgets(szTest, sizeof(szTest) - 1, fp);len = strlen(szTest);if('\n' == szTest[len - 1]){printf("yes3\n");}if('\r' == szTest[len - 2]){printf("yes4\n");}fclose(fp);return 0;
}

程序结果为:

yes1

我们看到, 读取的时候\r确实被去掉了。

好, 我们把dos.txt拷贝到linux下, 然后运行下面相同的程序:

// gcc#include <stdio.h>
#include <string.h>int main()
{char szTest[100] = {0};int len = 0;FILE *fp = fopen("dos.txt", "r");if(NULL == fp){printf("failed to open dos.txt\n");return 1;}fgets(szTest, sizeof(szTest) - 1, fp);len = strlen(szTest);if('\n' == szTest[len - 1]){printf("yes1\n");}if('\r' == szTest[len - 2]){printf("yes2\n");}memset(szTest, 0, sizeof(szTest));fgets(szTest, sizeof(szTest) - 1, fp);len = strlen(szTest);if('\n' == szTest[len - 1]){printf("yes3\n");}if('\r' == szTest[len - 2]){printf("yes4\n");}fclose(fp);return 0;
}

结果:

[taoge@localhost learn_c]$ xxd dos.txt 
0000000: 3132 0d0a 33                             12..3
[taoge@localhost learn_c]$ gcc test.c 
[taoge@localhost learn_c]$ ./a.out 
yes1
yes2
[taoge@localhost learn_c]$ 

我们看到, 读取的时候, \r还在。

OK, 至此, \r\n和\n的问题基本算是清楚了, 以后再也不用纠结了。

彻底解读剪不断理还乱的\r\n和\n, 以Windows和Linux为例相关推荐

  1. 简要介绍一下Dos/Windows格式文件和Unix/Linux格式文件(剪不断理还乱的\r\n和\n)

    DOS文件(windows格式文件)中,按一下ENTER就是输入了\r\n,这就是回车换行 MAC文件里,用\r换行 UNIX文件里,用\n换行 自己尝试了一些\r \n的组合,归纳了下规律: win ...

  2. r语言和metawin_如何创建R的HelloWorld包(Windows或Linux环境下)

    1.Windows环境下 1.2安装完后,配置系统的path 1.2.1假定R的安装路径在:D:\Program Files\R\R-2.5.0\bin:Rtools的安装路径在:c:\Rtools\ ...

  3. ML与Information:机器学习与Information信息论之间那些七七八八、乱七八糟、剪不断理还乱的关系攻略

    ML与Information:机器学习与Information信息论之间那些七七八八.乱七八糟.剪不断理还乱的关系攻略 目录 ML与信息论 ML与熵 1.熵的基础知识 2.熵与分布的关系 3.最大熵模 ...

  4. 剪不断理还乱的前端和交互

    前端工程师和交互设计师之间理所当然的存在着一些联系.从另一个角度看前端工作,前端人员既能定义为设计师,更重要的是应该对用户心理有完整的了解和研究.有一句话可以充分的证明这两者之间剪不断理还乱的关系,& ...

  5. 菜鸟学数据库——大话 char、varchar、 nchar、nvarchar之间剪不断理还乱的关系

    char.varchar.nchar.nvarchar这四个家伙不光长得很像,它们所具有的属性也十分的相似,以至于让人感觉有种"剪不断理还乱"的感觉.其实如果了解了它们各自的特点之 ...

  6. 分布式CAP中情侣的纠缠故事,真是剪不断 理还乱!

    -     CAP的前世今生     - 1.1 起源 CAP理论,被戏称为"帽子理论",CAP是Eric Brewer在2000年ACM研讨会上出了一个想法:"一致性. ...

  7. 玄姐出品:想和兄弟、集美们聊聊“分布式CAP”中情侣的纠缠故事,真是剪不断 理还乱!...

    孙玄 读完需要 5 分钟 速读仅需 2 分钟 1 CAP 的前世今生 1.1 起源 CAP 理论,被戏称为"帽子理论",CAP 是 Eric Brewer 在 2000 年 ACM ...

  8. 关于浮点数的剪不断理还乱

    文章出自个人博客https://knightyun.github.io/2020/03/21/programme-float-point,转载请申明 二进制小数 谈浮点数前,先了解一些基础知识:对于整 ...

  9. 简要分析unity3d中剪不断理还乱的yield

    在学习unity3d的时候很容易看到下面这个例子: 1 void Start () { 2 StartCoroutine(Destroy()); 3 } 4 5 IEnumerator Destroy ...

最新文章

  1. Windows2003使用命令行设置共享权限与安全权限心得
  2. adb logcat 查看日志
  3. ViewPager循环
  4. java匿名类和匿名对象及this的其他用法
  5. SpringBoot默认日志logback配置解析
  6. 使用Linux curl命令获取本机公网IP地址
  7. Java Web项目漏洞:检测到目标URL存在http host头攻击漏洞解决办法
  8. 腾讯C++程序员面试题
  9. 信道、频段带宽等术语简介
  10. 利用SPSS对数据转置和数据整理
  11. linux下code-server离线远程web浏览器调试C++代码
  12. 【JavaScript】DOM和事件简介和文档加载流程以及DOM查询(上)案例(附源码)
  13. Java语音SDK接口开发经验及具体开发实现
  14. 华为HCSP认证值得一考吗?
  15. 食品药品监督管理局:支持推动药品流通企业转型升级
  16. 最新软件开发企业网站Pbootcms模板源码
  17. 2节点弹性梁的稳定性分析(弹性基础)(python,有限元)
  18. WordPress安装部署
  19. 酷我音乐盒2014 v7.6.0.0 官方免费版
  20. 客快物流大数据项目(八十三):Kudu的优化

热门文章

  1. 世界上最顶尖的技术都在哪些国家?
  2. 2018个人面试记录
  3. 边云协同的优点_云边协同的现实意义
  4. 羊毛出在狗身上让猪来买单 - 智能音箱背后的平台经济
  5. 路由器与交换机配置测试题及答案
  6. 我们为什么要坚持写博客?
  7. 这5个PHP编程中的不良习惯,一定要改掉!
  8. 训练神经网络gpu占用率低,外接gpu 训练神经网络
  9. Elasticsearch Ingest Pipeline
  10. 批处理——读写文件、字符串替换