為什么寫這篇文章?
因為在工作過程中, 經常會切換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:
文件格式轉換:
那如果我們有文件需要在不同的操作系統中來回切換操作, 怎么處理文檔內的換行符呢?
方法1: NotePad++ 轉換
設置行尾符格式:編輯 -> 檔案格式轉換 ->(可選 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