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”)文本里面的內容讀出來:
1 #include <stdio.h> 2 3 4 5 int main( int argc, char ** argv ){ 6 7 FILE *fp; 8 9 char buf[255] = { 0 }; 10 11 size_t num = 0; 12 13 int i = 0; 14 15 16 17 if( argc != 2 ){ 18 19 printf( "You need to input the file to read!" ); 20 21 return -1; 22 23 } 24 25 26 27 if((fp = fopen( argv[1], "rb" )) == NULL ) 28 29 printf( "file open failed!" ); 30 31 32 33 while( (num = fread(buf, sizeof(char), 10, fp )) > 0 ){ 34 35 for( i = 0; i < num; ++i ){ 36 37 printf( "%02X", buf[i] ); 38 39 } 40 41 } 42 43 44 45 fclose( fp ); 46 47 return 0; 48 49 50 51 }
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