windows下操作文件换行符的问题

 为什么写这篇文章?

    因为在工作过程中, 经常会切换Linux 和Windows, 操作文档时有两次遇到莫名的问题, 怎么查程序都查不出来, 因为逻辑都没问题,但是数据就是出错了。查了N天,发现是不同操作系统换行符的问题,搞得血都吐了一堆。而网上很多文章感觉都没有讲的很清晰。

 为了不让大家重蹈覆辙,参考了其他网站的文章,特地总结了一下, 希望能在一篇文章里把问题讲解清楚。

    当然,如果其中理解有误的地方,请各位提出来。本来想分析一下源码,但是没有找到相关windows下转换的源码,就暂时不剖析了。如果各们有找到源码的同学,也可以分享一下,谢谢。

回车换行符的历史背景:

     早期的计算机输出设备不是显示器,而是电传打字机,结构与普通的打字机差不多。有一个打印头在纸上打字,同时有一个电动机控制纸张的进出。当打印头到达行尾的时候,需要两个动作才能够到达下一行的行首:

1: 首先执行回车动作,将打印头移动到本行的行首;

2: 然后进行换行动作,电动机将纸张向上移动一行,这样打印头就处于下一行的行首,可以继续进行打印。

 

    回车和换行对应的控制字符分别是\r和\n,这就是windows中换行符为\r\n的由来。

    后来由于经常连续执行,所以在打印机中将这两个控制字符简化为一个控制字符,这就是linux/unix中的换行符\n的由来。

不同操作系统换行符的区别:

Unix 系统中:   每行结尾只有 "<换行>",即 "\n";

          对应十六进制0x0A

Windows 系统中: 每行结尾是 "<回车><换行>",即 "\r\n";

          对应十六进制0x0D 0x0A

Mac 系统中:   每行结尾是 "<回车>",即 "\r"。

          对应十六进制0x0D

 

由于换行符不同, 导致的结果是:

  Unix/Mac系统下的文件在Windows里打开的话,所有文字会变成一行;

  而Windows里的文件在Unix/Mac下打开的话,在每行的结尾可能会多出一个^M符号.

 

而在 windows下操作文件fopen使用”r”和”rb”打开文件,  结果是不一样的(Linux下没有区别):

  如果 fopen是”r”文本方式打开, 读文件时会自动转换换物符\r\n为 \n。

  如果 fopen是”r”文本方式打开, 写文件时会自动转换换物符\n为 \r\n。

  如果 fopen是”rb”是以二进制方式打开,不会自动转换。

环境实验:windows fopen r rb的区别

 在windows环境和Linux环境下,分别建立一个文本,内容相同:

  Hello World!

  5AA555AA

windows下创建的文件,命名为windows.txt

Linux下创建的文件,命名为Linux.txt

写个程序将使用fopen( path, “rb” ) 文本里面的内容读出来:


#include <stdio.h>

 

int main( int argc, char ** argv ){


  FILE *fp;

  char buf[255] = { 0 };

  size_t num = 0;

  int i = 0;

 

  if( argc != 2 ){

  printf( "You need to input the file to read!" );
  return -1;
}

 if((fp = fopen( argv[1], "rb" )) == NULL )
   printf( "file open failed!" );

  while( (num = fread(buf, sizeof(char), 10, fp )) > 0 ){

    for( i = 0; i < num; ++i ){

      printf( "%02X", buf[i] );

    }

  }

  fclose( fp );

  return 0;

}

fopen( path, rb ) 输出结果为:

 

结果如下:

  windows下创建的文本换行符仍然是 0D0A(即\r\n), 

  Linux下创建的文件为 0A(\n)

 

将上述代码改为 fopen( path, r )

结果如下:

 

如上, 换行符统一被转换为0A(即\n

 

注意: 

如果Linux创建的文本,在windows下有编辑过,文件里面的0A会被转换为0D0A

比如我复制一份Linux.txt 为Linux1.txt, 在windows下用记事板打开文件,显示文件为:

 

 按CTRL+S保存后, 0A被转换为0D0A:

 

文件格式转换:

    那如果我们有文件需要在不同的操作系统中来回切换操作, 怎么处理文档内的换行符呢?

方法1NotePad++ 转换

    设置行尾符格式:编辑 ->  档案格式转换 ->(可选 Windows、Unix 和 Mac中的一种)(如果是英文版的 Notepad++,则应该是 Edit -> EOL Conversion -> Windows Format、Unix/OSX Format、Old Mac Format。)

方法2:  使用UNIX命令转换:

  unix2dos -k xxx_file

  dos2unix -k xxx_file

 

参考文章: 1: https://blog.csdn.net/wzb56_earl/article/details/6860358

      2:https://www.cnblogs.com/cnjavahome/p/8893813.html

posted @ 2020-07-28 15:16  coolboycool  阅读(5485)  评论(0编辑  收藏  举报