一、走近CRLF和LF
CRLF和LF是控制字符,是换行字符的两种符号表示。CRLF是"carriage return"和"line feed"的缩写,表示回车和换行。LF是"line feed"的缩写,表示换行。
在Windows操作系统下,回车和换行使用的是CRLF,而在Unix/Linux和Mac OS X操作系统下,回车和换行使用的是LF。CRLF和LF主要在文本文件中使用,例如代码文件、配置文件等。
下面我们通过一个简单的示例来理解它们的区别:
<html>
<head>
<title>欢迎</title>
</head>
<body>
</body>
</html>
这是一个简单的HTML文档,该文档以Windows操作系统下的记事本编辑并保存。我们可以使用文本编辑器或hexdump等工具查看文档的二进制表示:
00000000: 3C68 746D 6C3E 0D0A 3C68 6561 643E 0D0A <html>..<head>..
00000010: 3C74 6974 6C65 3E0D 0A20 20 20 20 20 20 20 20 <title>..
00000020: E68A 8AFE E5 91 98 3C2F 7469 746C 653E 0D0A ...</title>..
00000030: 3C2F 6865 6164 3E0D 0A3C 626F 6479 3E0D 0A </head>..<body>..
00000040: 3C2F 626F 6479 3E0D 0A3C 2F68 746D 6C3E 0D0A </body>..</html>..
我们可以看到,Windows使用的是CRLF,而Unix/Linux或Mac OS X使用的是LF。在文本文件中使用LF比使用CRLF的好处是更加节省空间。例如,在一个100M大小的文本文件中,使用LF相比CRLF格式可以节省几十M的空间。
二、不同场景下的使用
CRLF和LF在不同的场景下有不同的使用方式:
1. 网络传输
在网络传输中,特别是在高速网络中,使用LF比使用CRLF更加高效,因为LF只占用一个字符。在编写网络服务器或客户端程序时,为了更好地支持LF和CRLF,一般会加入兼容性处理。
例如,以下是一个支持CRLF和LF的简单的echo服务器程序:
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netdb.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#define SERVER_PORT 12345
#define MAX_LINE 256
int main(int argc, char* argv[])
{
struct sockaddr_in sin;
char buf[MAX_LINE];
int len;
int s, new_s;
bzero(&sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(SERVER_PORT);
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("simplex-talk: socket");
exit(1);
}
if ((bind(s, (struct sockaddr*)&sin, sizeof(sin))) < 0) {
perror("simplex-talk: bind");
exit(1);
}
if ((listen(s, 2)) < 0) {
perror("simplex-talk: listen");
exit(1);
}
while (1) {
if ((new_s = accept(s, (struct sockaddr*)&sin, &len)) < 0) {
perror("simplex-talk: accept");
exit(1);
}
while ((len = recv(new_s, buf, sizeof(buf), 0))) {
if (len <= 0) break;
buf[len] = '\0';
if (buf[len - 1] == '\n') {
buf[len - 1] = '\0';
}
printf("Client:%s\n", buf);
send(new_s, buf, strlen(buf), 0);
}
close(new_s);
}
return 0;
}
使用telnet工具连接该服务器,可以看到服务器返回的内容是CRLF格式。
2. 编程风格
在不同编程语言中,换行使用的方式也有不同。在C语言中,回车和换行使用的是CRLF("\r\n"),而在Python中则使用LF("\n"),在Java程序中默认使用LF。即使在同一编程语言中,使用LF或CRLF的风格也各不相同。
下面是一个Python程序,它将一个字符串写入到文件中:
s = 'Hello world'
with open('file.txt', 'w') as f:
f.write(s + '\n')
该程序使用的是LF换行符。而下面的C程序使用的是CRLF:
#include<stdio.h>
int main()
{
printf("Hello world!\r\n");
return 0;
}
三、CRLF和LF的转换
在不同操作系统和编码风格中,文件的换行符可能会不同。因此,我们需要在不同系统之间进行转换:
1. Windows到Unix/Linux的转换
有些应用程序或服务是在Unix/Linux平台下运行的,因此我们需要将Windows下的文本文件转换为Unix/Linux下的格式。常用的工具是dos2unix和tr命令:
#dos2unix
$ dos2unix filename
# tr
$ tr -d '\r' <filename> >newfilename
2. Unix/Linux到Windows的转换
同样地,有些应用程序或服务是在Windows平台下运行的,因此我们需要将Unix/Linux下的文本文件转换为Windows下的格式。常用的工具是unix2dos和sed命令:
#unix2dos
$ unix2dos filename
# sed
$ sed -e "s/$/`echo -e \\\r`/" <filename> >newfilename
以上仅是简单的命令行工具,还有更多的文本编辑器和IDE可以提供转换功能。
四、结语
CRLF和LF的区别主要在于使用方式的差异。在网络传输中,使用LF比使用CRLF更加高效;在编程风格中,使用的风格也各有不同;在不同操作系统和编码风格中,需要进行转换。因此,熟练掌握CRLF和LF之间的差异,可以更好地编写和处理文本文件。