【问题标题】:Is it necessary to write a "portable" if (c == '\n') to process cross-platform files?if (c == '\n') 是否需要写一个“可移植的”来处理跨平台文件?
【发布时间】:2015-09-13 04:03:52
【问题描述】:

这个想法来自于一个实际问题Replacing multiple new lines in a file with just one的讨论。使用在 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;
    }

更新1:

CRT 总是会将行尾转换为 '\n'?

【问题讨论】:

  • CRT 将始终将行尾转换为'\n',因此如果您将文件作为文本读取,它将自动可移植。除非您想从任何平台读取具有任何类型行尾的文件
  • @LưuVĩnhPhúc 谢谢。如果尝试在 Linux 下读取文件(在 windows 上创建),最好的做法是重写if(c=='\n'),或者只是使用命令/工具转换文件?
  • @LưuVĩnhPhúc 错误(一般)。如果文件/流以“ASCII 模式”打开(仅在 microsoft 平台上存在),则行尾仅在 microsoft 平台上翻译
  • @EricTsui portable 意味着相同的代码在不同平台上编译时在该平台上可以正常运行。这并不意味着您可以毫无问题地处理来自其他平台的文件。因此,如果您使用 Windows 中的文件,则需要手动处理它们。 c=='\n' 不起作用,因为 Linux CRT 不知道 Windows 或任何其他系统的行尾并且不会转换它们。先转换文件还是签入代码取决于你
  • 作为用户,当读取文本文件的程序将 ether cr/lf 或 plainlf 视为行结尾时,我几乎总是很感激。写入文本文件时,应使用默认的系统行结尾(写入同一文件或有特定选项覆盖提供和使用的默认值时除外)。

标签: c linux windows macos


【解决方案1】:

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

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

如果您在系统之间传输文件(例如,在 linux 下写入文件,然后将其传输到 windows 系统,程序会尝试读取它),那么您可以选择;

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

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

【讨论】:

  • +1 这些是选项。我会选择完全受控的二进制传输:工作量相同,但涉及的因素更少
  • 也许是这样。但是 OP 没有提供足够的信息来帮助在选项之间进行选择。
  • @Peter 谢谢你的详细分析。真的很有帮助。
猜你喜欢
  • 1970-01-01
  • 2023-03-26
  • 1970-01-01
  • 2016-10-21
  • 1970-01-01
  • 2010-09-12
  • 2012-02-23
  • 2011-01-22
  • 1970-01-01
相关资源
最近更新 更多