Windows/DOS與Unix文件格式之間的相互轉換(/r/n問題)


PS:今天遇到一個文件轉換問題,現在將網上搜索到資料貼出來。。

第一個資料

Windows/DOS與Unix文件格式是不同的,問題一般就是出在/r/n問題上。

回車(CR)和換行(LF)符都是用來表示“下一行”的。而標准沒有規定要使用哪一個。於是產生了三種不同的用法:Dos和windows采用回車+ 換行(CR+LG)表示下一行(亦即所謂的PC格式,誰讓MS最早雄踞PC市場呢,^_^),UNIX采用換行符(LF)表示下一行,MAC機采用回車符(CR)表示下一行。當在不同的系統間傳遞文件,就要涉及格式的轉換。

先搞清楚幾個符號


0D CR ^M 回車


DOS/Windows文本文件中使用CR(回車\r)和 LF(換行\n),
在文件的行尾的情況是是 '\r\n'

UNIX文本只使用換行符,在行的末尾有一個換行(\n),也就是'\n'
所以在windows下編輯的C程序放在unix下編譯會出現"No end of newline"的Warning

兩種文件格式之間的轉化

Unix -> Dos
'\n' -> '\r\n'
   Unix -> Dos
    '\n' -> '\r\n'
    while ( (ch = fgetc(in)) != EOF )
    {
      if ( ch == '\n' )
        putchar('\r');
      putchar(ch);
    }

只要在Unix文件中出現的'\n'的之前加入一個'\r'字符就可以了

Unix <- DOS
'\n' <- '\r\n'

從Dos到Unix的情況復雜點,不能只是把從文件中讀出的'\r'去掉就可以了
因為Dos文件中的文本行的末尾有時會內嵌一個回車符號,這種情況在擊打式打印機中出現。
所以在轉換前要判斷'\r'是否和'\n'同時出現。
如果同時出現,則去掉'\r'
如果沒有同時出現,保留'\n'

//

    cr_flag = 0;  /* No CR encountered yet */
    while ( (ch = fgetc(in)) != EOF )
    {
      if ( cr_flag && ch != '\n' ) {
        /* This CR did not preceed LF */
        putchar('\r');
      }
      if ( !(cr_flag = (ch == '\r')) )
        putchar(ch);
    }

第二個

服務器端
無論在
但這並不是說在服務器端存儲的文件(以 ,v結尾),不能包含字符“0d”。比如二進制文件中很多包含字符0d。文本文件也可能包含0d,但大部分包含0d的文本文件,很有可能是由於不當的跨平台使用cvs造成的。
服務器端的這種處理方法很好的適應了跨平台特性。亦即unix端服務器的repository 可以直接拷貝到windows端的repository中,vice versa。
在將unix維護的服務器端,移植到windows端,我曾經遇到一個百思不得其解的問題。后來發現是由於winzip的一個古怪的缺省設置造成的:“tar file smart cr/lf conversion”!

unix 客戶端
unix上的客戶端文本原樣存儲保存到服務器端,0d作為普通字符隨文件checkin,因為 unix的默認文件換行符為 “0a”。

第三個

Windows & Unix 文件格式之謎

\1. 問題提出:
我們可能會遇到過這樣一些困惑:
(1) 如何查看一個文件或數據流的二進制格式(以十六進制格式顯示)?
(2) 為什么在 windows下編譯的 shell 腳本在 Unix下不能執行?
為什么在 windows下編輯的 C 源文件在有些 gcc 編譯器下不能編譯?
(3) 為什么我在 vi 等編器下打開一個文本文件會包含 ^M, 如何把它去掉?
為什么我在 windows 上用記事本打開 unix上的文件, 文件都不換行?
(4) 如何刪除文件行尾的 空格 或 tab?
如何把文件中的 tab 轉換成 空格, 或者把 空格 轉換成 tab?
如何只轉換行首 tab 轉換成 空格?
...

\2. 分析與方案:

(1) 如何查看一個文件的二進制格式(以十六進制格式顯示)?
查看任意文件或數據流的二進制格式, 我們非常常用.
方法一: 在 UtraEdit 使用 Ctrl + H 切換到十六進制編輯模式.
** 注意 ** :
此方法一有缺陷, 它會將行末的單個"換行符"顯示成 "回車" + "換行" 兩個字符.
這樣會使問題 (2)(3)(4) 無法用此工具正確查看.

方法二: 使用文件或流的二進制查看工具 fbin
fbin 可以運行於 windows 和各種 Unix 平台,
如下例的命令顯示文件的前48字節:

  $ fbin xx.c 0x30
  filename:  'xx.c'
  filelen :  0x68(104), offset: 0x38, max output: 0x30
  00000000:  2369 6E63 6C75 6465 3C73 7464 696F 2E68 #include....intmain()..
  00000020:  7B0D 0A20 2020 2063 6861 7209 2020 2020 {.. char.

  fbin 能准確顯示文件中的每一個字節. (更多詳細實例見后文)

(2) 為什么在 windows下編輯的 shell 腳本在 Unix下不能執行?
為什么在 windows下編輯的 C 源文件在有些 gcc 編譯器下不能編譯?

原因分析:
unix 的 shell 腳本不能識別 "回車符" (即: CR, '\r'),
Windows 文件格式(詳細分析見下文) 換行時, 總是以 "回車" + "換行"
(可以借助上一問介紹的 fbin 工具, 查看文件中是否包含 "回車換行" 對),
導到 unix 下的 shell 無法正常解釋.

解決方法:
就是把 windows 格式的中的 "回車" 符刪除, 刪除.

方法一: 使用 vi 打開源文件, 把 '\r\n' 替換成 '\n'
** 缺點 ** : 不適合大量文件的批量作業.

方法二: 使用 UtraEdit 把 Windows 格式的文件轉換成 Unix 格式.
(菜單)文件-->轉換-->Unix轉DOS
** 缺點 ** : 不適合大量文件的批量作業.

方法三: Unix 下的 dos2unix 命令, 如 $ dos2unix -k xx.c
** 缺點 ** :
此方法有一致命缺陷, 它會改變原來的文件屬性.
如一個可執行 shell 腳本的可執行屬性及其它屬性, 轉換后都將會丟掉
(即使用 -k 也只是能保留住原來的日期.)
** 優點 ** : 適合大量普通文件本文件的批量作業.

方法四: win2unix (windows, unix 均可使用), 功能類似 dos2unix,
如 win2unx xx.c (更多詳細實例見后文)
** 優點** :
克服了 dos2unix 的所有缺點(見上), 它能保留源文件的任何屬性.
還可以返回轉換即 unix2win
適合大量文件的批量作業.

(3) 為什么我在 vi 等編器下打開一個文本文件會包含 ^M, 如何把它去掉? (見結論 4, 5)
為什么我在 windows 上用記事本打開 unix上的文件, 文件都不換行? (見結論 1)

原因分析:
要解決這個問題, 必先弄清 unix 與 windows 文本文件的差異:
1) 磁盤中 Windows 文本文件總是以 "回車" + "換行"的形式進行換行的.
2) 磁盤中 Unix 格式的文本文件, 總是以"換行符"(即: LF, '\n') 換行, 而非 "回車換行符".
(Unix 規定: unix 文本文件保存到磁盤時, 總是自動把 "回車換行符" 轉換成 "回車符" 保存,
輸出到終端時由終端自動將將 "回車符" 轉換成 "回車換行符" 輸出.)

  ** 容易看出 **:
  Windows 格式的文件換行時, 總是比 Unix格式的文件多一個 "回車" ('\r') 符.

  ** 結論 1 **:
  這樣在 windows 的記事本中打開 Unix 格式的文件時, 因為文件中沒有 '\r', 所以無法正常顯示.
  結果就會把所有的內容顯示在同一行中.

  ** 結論 2 **:
  UtraEdit 等工具會自動檢測文件中是否包含 '\r', 當檢查行末缺少 '\r'時, 一般它會提示
  要求進行 Unix 到 Windows 格式的轉換. (相信大家都遇到這個提示信息).

  ** 結論 3 **:
  UtraEdit 和 vi 等工具, 在保存文件時會自動依照文件原來的格式進行保存. 即:
  如打開的如是 windows 格式它會把文件依然按 windows 格式保存 (不進行自動轉換).
  如打開的如是 unix 格式它會把文件依然按 unix 格式保存 (不進行自動轉換).

  ** 結論 4 **:
  向 UtraEdit 打開的 Unix 格式文件中, 通過粘貼板 "粘貼" Windows 格式的若干片斷行時
  (或反之, 即向 Windows 格式文件中, 通過粘貼板 "粘貼" Unix 格式的若干片斷行時),
  代碼片斷中的 "回車換行符" "不會" 自動轉換成單個 "換行" 符(反之亦然).
  這樣, 該文件中就會出現 "回車符" 與 "回車換行符" 互相夾雜.
  即, 文件中既有單獨的 "回車符" 也有 成對的 "回車換行符".

  ** 結論 5 **:
  vi 編輯器等, 既能正確顯示"規則"的 Unix 格式文件, 也能正確顯示"規則"的 Windows 格式文件,
  但, 對包含單獨的 "回車符", 同時成對的 "回車換行符"的不規則文件 (產生原因見結論 4),
  vi 將把回車符以 ^M 的形式顯示.

解決方法:
使用類似問題 2 提供的解決方法即可解決, 不再驁述.
將 unix 轉換成 Windows 格式時, 使用 unix2dos 或 win2unix -r(-r 代表反方向)即可.

(4) 如何刪除文件行尾的 空格 或 tab?
如何把文件中的 tab 轉換成 空格, 或者把 空格 轉換成 tab?
如何只轉換行首 tab 轉換成 空格?

問題分析:
出於各種需要, 特別是編輯 C/C++, Java 等源程序時, 常希望將源文件中的 tab 成空格,
或將空格轉換成 tab, 同時刪除行尾不必要的空格或 tab 等.
如果源程序的正文中字符串中包含"空格"或"tab"時, 則只希望只轉換行首的"空格"或"tab".

解決方法:
如果是單個文件, 直接使用一些編輯器自帶的轉換功能轉換.
如果是想批量轉換, 不防試試 tab2sp 進行轉換, 不僅適合批量文件, 還適合數據流.

方法一: 使用 UtraEdit 的轉換功能, 即: (菜單)格式-->轉換 TAB 為空格, ...
** 缺點 **:
不適合大量文件的批量作業.

方法二: tab2sp (適合 windows, 各種 unix 平台),
如 tab2sp -t -w8 xx.c (更多詳細實例見后文)

  ** 優點 **:
  適合大量文件的批量作業.
  適應文件或流的二進制查看工具 fbin

\3. 工具詳解: fbin, win2unix, tab2sp 等對流或文件進行批量查看/轉換
(1) 工具簡介
fbin, win2unix, tab2sp 等工具對流或文件進行批量查看/轉換,
適合 Windows 和 各種 Unix 平台.

(2) fbin - 查看流/文件的二進制格式

在命令行上鍵入下面命令即可查看在線幫助(部分內容未列出)
$ fbin --help
fbin - display file with hex format, version 1.0.4
Copyright(C) eyBuild Group, 2005, 2006. All Rights Reserved.
[url=http://www.eybuild.com/][color=#000000]http://www.eybuild.com[/color][/url], [url=mailto:eybuild@hotmail.com][color=#000000]eybuild@hotmail.com[/color][/url]
Usage: fbin [options] [fname [0x][offset] [maxlen] | [file1] ...]
-h --help - show this help
-w[num] - specify word-width [2/4], default 2
-p - pause for every screen
-v - verbose mode
-l - process file list replace 'fname' ...
fname - file name to display
offset - hex number, '0x' is optional.
offset >= 0 from the begining of input file,
offset for /F %I in ('dir /w /b /s /A:-D eybuild\bin') do fbin -w2 -v -l %I | more

(3) win2unix - Windows 與 Unix 文件格式互轉換工具

在命令行上鍵入下面命令即可查看在線幫助(部分內容未列出)
$ win2unix --help
win2unix - translate file between windows and unix format, version 1.0.5
Usage: win2unix [options] [[src] [dst] | [file1] ...]
-h --help - show this help
-r - translate file from unix format to windows
-v - verbose mode
-l - process file list replace 'src' & 'dst' pair
src - source file or dectory
dst - destination file or dectory

EXAMPLES:
  win2unix foo.txt
convert unix to windows format:
  win2unix -r -b src.txt dst.txt
process file list:
  win2unix -v -l f1 f2 f3 f4 f5 f6

例1. Unix 格式轉換成 Windows 格式:
$ win2unx -r fbin.c

查看二進制結果如下, 與fbin中的"例1"對比容易發現, 第3行中原來的0A0A(兩個"換行符")
被轉換成了 0D0A0D0A (兩對"回車換行符").
$ fbin fbin.c  0  40
00000000:  2F2A 2066 6269 6E2E 6320 2D20 6C69 7374 /* fbin.c - list
00000010:  2066 696C 6520 7769 7468 2062 696E 6E61   file with binna
00000020:  7279 2066 6F72 6D61 7420 2A2F 0D0A 0D0A ry format */....
00000030:  2F2A 2043 6F70 7972 6967 6874 2843 2920 /* Copyright(C)

例2. Windows 格式轉換成 Unix 格式:
$ win2unx fbin.c

查看二進制結果如下, 與 "例1"對比容易發現, 第3行中原來的0D0A0D0A (兩對"回車換行符")
被轉換成了 0A0A(兩個"換行符")
$ fbin fbin.c  0  40
00000000:  2F2A 2066 6269 6E2E 6320 2D20 6C69 7374 /* fbin.c - list
00000010:  2066 696C 6520 7769 7468 2062 696E 6E61   file with binna
00000020:  7279 2066 6F72 6D61 7420 2A2F 0A0A 2F2A ry format */../*
00000030:  2043 6F70 7972 6967 6874 2843 2920 6579   Copyright(C) ey

例3. 批量轉換查找(包含子目錄)到的所有文件:
$ find src -name "*.c" | xargs win2unix -l -v
convert 'win' to 'unix' format ...
src/csp2bin.c
src/tab2sp.c
src/fbin.c
src/win2unix.c
...

Windos 命令如下命令, 會得到相同結果:
E:\> for /F %I in ('dir /w /b /s /A:-D src/*.c') do win2unix -v -l %I

(4) tab2sp - tab 與 空格的互轉換

在命令行上鍵入下面命令即可查看在線幫助(部分內容未列出)
$ win2unix --help
tab2sp - convert tabs to spaces or revert, version 1.0.2
Usage: tab2sp [options] [[src] [dst] | [file1] ...]
-h --help - show this help
-r - convert spaces to tabs
-p - only convert line prefixed spaces or tabs
-t - remove tail tabs and spaces
-w[num] - specify tab width [1-8], default 4
-no - don't do any convert
-v - verbose mode
-l - process file list replace 'src' & 'dst' pair
src - source file
dst - destination file


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM