我们通常会把应用部署在Linux上,而在使用vi查询应用日志时,可能会发现有一个^M符号,如下所示

[20121121 07:53:19][pool-3-thread-3][AbstractAction]^M
------------------------------------------------------------------------------------------^M
【通信双方】(0x00004AFE: nio socket, server, /192.168.13.3:59565 => /192.168.12.2:80)^M
【收发标识】Receive^M
【报文内容】POST /tra/trade/noCardNoPassword.htm HTTP/1.1^M
Content-Type: application/x-www-form-urlencoded;charset=GB18030^M
Cache-Control: no-cache^M
Pragma: no-cache^M
User-Agent: Java/1.6.0_24^M
Host: 192.168.20.1^M
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2^M
Connection: keep-alive^M
Content-Length: 541^M
^M
cooBankNo=CMBC_CREDIT&signType=MD5&amount=499900&orderValidityNum=15&CVVNo=255^M
------------------------------------------------------------------------------------------
[20121121 16:37:15][pool-3-thread-26][AbstractAction]^M
------------------------------------------------------------------------------------------^M
【通信双方】(0x0000E522: nio socket, server, /58.83.141.39:60796 => /192.168.12.2:80)^M
【收发标识】Receive^M
【报文内容】GET /notify_yeepay?p1_MerId=11&r0_Cmd=Buy&r1_Code=1&r2_TrxId=22 HTTP/1.1^M
Content-Type: application/x-www-form-urlencoded; charset=GBK^M
Cache-Control: no-cache^M
Pragma: no-cache^M
User-Agent: Java/1.5.0_14^M
Host: 123.125.**.248^M
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2^M
Connection: keep-alive^M
^M
^M
------------------------------------------------------------------------------------------



这里就引伸出一个概念:换行符,也就是CR(Carriage Return)和LF(Line Feed)的问题
通常我们在EditPlus——工具——参数设置——文本——新建文件—>>中可以看到PC/UNIX/MAC三种格式
而在UltraEdit——高级——配置——文件处理——新建文件类型——>>中可以看到DOS/UNIX/MAC三种格式
而且UltraEdit在保存文件时也可以指定文件格式:DOS为CRLF,UNIX为LF,MAC为CR
实际上CR(回车符)和LF(换行符)都是用来表示下一行的,只不过各个系统采用的方式不同而已
DOS/Windows系统采用CRLF(即回车+换行)表示下一行
Linux/UNIX系统采用LF表示下一行
MAC系统采用CR表示下一行
注:CR的ASCII是十进制数的13,十六进制的0x0D,LF为10和0x0A


多数的计算机语言中,CR表示为字符或者字符串就是"\r",LF为"\n"
而各语言的printf()函数中的"\n"则代表的是一个逻辑上的意义,即当前操作系统中的下一行
所以在UNIX上它代表的是LF,在Windows上则是CRLF


另外,HTTP/1.1协议的RFC2616规范中明确说到:
HTTP/1.1将CRLF的序列定义为任何协议元素的行尾标志,但这个规定对实体主体(endtity-body)除外
实体主体(entity-body)的行尾标志是由其相应的媒体类型定义的
于是,可以粗略理解为上面贴出来的HTTP报文中的"【报文内容】"部分(即HTTP请求的原始报文)
它的每一行都是以CRLF结尾的(所以在使用Mina2.x编写HTTP服务器时就可以根据0x0D和0x0A来判断了)


最后,回归主题:Linux上的报文尾部出现的^M符号
当使用vi查询日志时,vi内部会认为该日志为Linux格式的,它也只认LF
于是vi就会把遇到的CR干掉,取而代之的就是显示出来一个^M符号


下面再引申出来一个关于CR(回车)和LF(换行)的历史,仅供了解
计算机出现之前,是使用电传打字机(Teletype Model 33)打印字符的,它每秒可以打10个字符
但在打完一行后,准备换行时发现,换行需要用去0.2秒,而这0.2秒又正好可以打印两个字符
而如果在这0.2秒期间,又有新的字符传过来,那么传过来的这个字符将丢失,因为它正在换行
于是,研制人员为了解决此问题,就决定在每行后面添加两个表示结束的字符,即CR(回车)和LF(换行)
CR(回车):告诉打字机把打印头重定位在该行的左边界
LF(换行):告诉打字机把打印头下移一行,即把纸向下移一行
接着,随着计算机的发明,这种处理机制也就被移到了计算机上
但当时存储器很贵,有些人认为在每行结尾加两个字符太浪费了,应该加一个就行了,于是乎分歧出现了
DOS/Windows系统采用CRLF(即回车+换行)表示下一行
Linux/UNIX系统采用LF表示下一行
MAC系统采用CR表示下一行
这种分歧导致的直接后果就是:
Windows中打开Linux/UNIX系统下的文件时,所有的文字都会变成一行(因为Windows只认为CRLF才表示换行)
Linux/UNIX中打开Windows系统下的文件时,在每行的结尾可能会多出一个^M符号
而^M符号是Linux等系统规定的一个特殊标记,它占一个字符的大小,它不是^和M的组合,是打印不出来的
并且^M符号也只是用于显示而已,它不会真正的写入到文件中