是否有必要编写一个"便携式"if(c =='\n')来处理跨平台文件?

Eri*_*sui 6 c linux windows macos

这个想法来自关于实际问题的讨论只用一个替换文件中的多个新行.使用在Windows 8.1机器上运行的cygwin终端时发生了错误.

由于行尾终结符不同,比如\n,\r或者\r\n,是否有必要编写"可移植" if(c=='\n')以使其在Linux,Windows和OS X上运行良好?或者,最佳做法是使用命令/工具转换文件?

  #include <stdio.h>
    int main ()
    {
      FILE * pFile;
      int c;
      int n = 0;
      pFile=fopen ("myfile.txt","r");
      if (pFile==NULL) perror ("Error opening file");
      else
      {
        do {
          c = fgetc (pFile);
          if (c == '\n') n++; // will it work fine under different platform?
        } while (c != EOF);
        fclose (pFile);
        printf ("The file contains %d lines.\n",n);
      }
      return 0;
    }
Run Code Online (Sandbox Code Playgroud)

UPDATE1:

CRT会一直将行结尾转换为'\n'吗?

Pet*_*ter 4

如果输入文件以二进制模式(模式字符串中的字符“b”)打开,则有必要担心 before 可能'\r'存在'\n'

如果文件不是以二进制模式打开的(并且也不是使用二进制函数读取的,例如fread()),那么就不必担心'\r'before的存在'\n',因为它将在您的代码接收输入之前处理 - 或者由相关的系统函数(例如,从磁盘或从 读取输入的设备驱动stdin程序)或通过实现用于从文件读取输入的函数。

如果您要在系统之间传输文件(例如,在 Linux 下写入文件,然后将其传输到 Windows 系统,其中程序尝试读取该文件),那么您有多种选择;

  • 以非二进制方式写入和读取文件,并在系统之间传输文件时对文件进行相关翻译。如果使用ftp此功能,可以通过使用文本模式而不是二进制模式传输文件来处理。如果文件以二进制模式传输,则需要运行该文件dos2unix(如果将文件传输到unix)或通过unix2dos(反之亦然)。
  • 以二进制模式执行所有 I/O,使用二进制模式在系统之间传输它们,并且切勿以非二进制模式读取它们。除此之外,这使您可以明确控制文件中的数据。
  • 以文本模式写入文件,根据需要传输文件。然后仅以二进制模式读取,当您的读取代码遇到一\r\n对时,删除该'\r'字符。

最后一个可以说是最健壮的 - 写入代码可能包含\r之前的\n字符,也可能不包含,但读取代码只是忽略在字符'\r'之前遇到的任何字符'\n'。如果在读取文件之前手动编辑文件(例如使用文本编辑器 - 可以单独配置为插入或删除\rand ),这样的代码甚至可能可以应付。\n