关于换行
涉及到的字符有如下两种
* CR - 0x0d, 回车符,在代码里用'\r'表示
* LF - 0x0a,换行符,在代码里用'\n'表示
不同环境下,默认的换行符(字符序列)不同,需要说明的是,这个序是逻辑序,真实的物理序还要考虑大小端的问题
* Win - CRLF,字符序列是'\r\n'
* Linux/Unix - LF,字符序列是'\n'
* Mac - CR, 字符序列是'\r'
* HTTP - CRLF,但实际上,LF被广泛支持了
Linux C
char *gets(char *str);
char *fgets(char *str, int size, FILE *stream);
gets
在新的标准中已经被弃用了fgets
增加了size防止读写过界
这两个函数只识别LF换行符,比较傻瓜。
其中gets
会去除LF:
LF换行: 123LF456LF -> 123, 456
CR换行: 123CR456CR -> 123CR456CR
CRLF换行: 123CRLF456CRLF -> 123CR, 456CR
fgets
不会去除LF:
LF换行: 123LF456LF -> 123LF, 456LF
CR换行: 123CR456CR -> 123CR456CR
CRLF换行: 123CRLF456CRLF -> 123CRLF, 456CRLF
ssize_t getline(char **lineptr, size_t *n, FILE *stream);
ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream);
这两个函数都不是C标准里的,是POSIX标准的
这两个函数会自己管理内存,保证分配足够的内存来放置读取的字符
getline类似于fgets
,只识别LF,不会去除LF
C++
istream& getline (istream& is, string& str, char delim);
istream& getline (istream& is, string& str);
类似于gets
,识别并去除LF
basic_istream::getline
basic_istream& getline(char_type* s, std::streamsize count);
basic_istream& getline(char_type* s, std::streamsize count, char_type delim);
类似于gets
,识别并去除LF
类似于fgets
,防止读写过界
C/C++均无法处理跨平台问题
Python
Python读取文件分为2类,按二进制读取和按文本读取,均使用readline
方法:
二进制读取 - 只识别LF
文本读取 - 识别 CR, LF, CRLF,均被转为 LF
从stdin读取时,貌似类似于二进制读取的状态
Python读取会不会去除CR, LF和CRLF(但可能会将CR, CRLF转为LF)
Java
Java.io.BufferedReader.readline()
类似于python的readline文本读取,可以识别CR, LF, CRLF。
并且会去除掉行尾的换行字符序列。
Go
bufio
func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error)
line 的内存由 ReadLine管理,bool表示是否读取完整。
只能识别并去除 LF, CRLF。
总结
方式 | 支持CR | 支持LF | 支持CRLF | 去除行尾 | 防止越界 |
---|---|---|---|---|---|
c/gets | × | √ | × | √ | × |
c/fgets | × | √ | × | × | 防止读写越界 |
c/getline | × | √ | × | × | 重分配内存 |
c++/::getline | × | √ | × | √ | 不需要 |
c++/istream::getline | × | √ | × | √ | 防止读写越界 |
python/readline | √ | √ | √ | 转为LF | 不需要 |
java/readline | √ | √ | √ | √ | 不需要 |
go/ReadLine | × | √ | √ | √ | 防止读写越界 |
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。