WindowsDOS与Unix⽂件格式之间的相互转换(rn问题)
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 #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 - 查看流/⽂件的⼆进制格式
(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:
convert unix to windows format:
win2unix -r -
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

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。