如何检测来自不同操作系统的文本文件的行结尾?

时间:2011-04-08 22:54:30

标签: c operating-system cross-platform newline line-endings

在C中,我通常一次读取一个字符的文本文件(例如,在FSM的循环中,同时进行标记和解析)。不幸的是,一些操作系统使用不同的方法来标记一行的结尾,例如, Unix("\n"),Mac OS("\r")和DOS / Windows("\r\n")。

因此我的问题是:如何正确检测来自不同操作系统的文本文件中的行结尾?

我目前的做法是将'\r'视为'\n'并忽略空行。不幸的是,只有空行不会改变底层文本的语义,这种方法才有效。

我不想“检测”每个文件的行结束样式,我当然不希望基于#ifdef或其他类型的条件编译的解决方案。是否有任何有效的解决方案?

3 个答案:

答案 0 :(得分:4)

我通常不建议一次读取一个字符的文件,但对于你的情况,我建议你“偷看”一个字符前面使用以下逻辑......

if c == '\r'
    p = peek
    if p == '\n'
        read next c

您无法真正相信所有文件具有一定的亲和力,甚至文件本身遵循相同的约定,因此您应该为所有情况编码。在这种情况下,如果您看到\ r \ n 可能看到\ n,并且您是否使用了下一个字符并继续。

答案 1 :(得分:1)

不幸的是,如果文件已被传递,或者使用允许您指定行结尾的编辑器进行编辑,或者出于任何其他类似原因,则文件可以具有混合行结尾。 确定文件的“<”>行行结束样式可能需要投票 - 以风格 X 结尾的大多数行都会获胜。

我所做的是

  1. \r视为换行符。如果下一个 char \n丢弃它。 (如果 下一个字符不是\n \r 算作换行符)

  2. \n视为一个 换行,除非你扔掉它,因为(1)

答案 2 :(得分:1)

我通常的做法是将'\n'视为行终止符,如果前一个字符是'\r',则将其删除(通常我最终用0覆盖其中一个或另一个)。如果您还想支持旧版Mac文本文件('\r' - 仅限换行符),那么您可以采用单独'\r',孤独'\n'或{{1}对的方法作为换行符。