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

您所在的位置:网站首页 beginner为什么双写n 彻底解读剪不断理还乱的\r\n和\n, 以Windows和Linux为例

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

2024-07-13 05:17:23| 来源: 网络整理| 查看: 265

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

        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 #include 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 #include 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的问题基本算是清楚了, 以后再也不用纠结了。

 

 

 

 



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭