【问题标题】:How does read(2) interact with carriage returns?read(2) 如何与回车交互?
【发布时间】:2023-03-29 14:37:01
【问题描述】:

我正在编写一个简单的程序来翻转文件中的所有位,但现在它只处理前 1000 个字节,直到我得到那么多工作。为什么我对 read() 的调用会忽略 \r 字符?当我在仅包含 \r\n\r\n 的文件上运行此代码时,读取调用返回 2 并且缓冲区包含 \n\n。 \r 字符被完全忽略。我在 Windows 上运行它(这在 Linux 机器上甚至都不是问题)

为什么 read(2) 在找到 \r 字符时会跳过它?或者这就是正在发生的事情?

编辑:结论是 Windows 默认以“文本”模式打开文件,而不是“二进制”模式。因此,在调用 open 时,我们必须指定 O_BINARY 作为模式。

谢谢,代码如下。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>

void invertBytes(size_t amount, char* buffer);

int main(int argv, char** argc)
{
   int fileCount = 1;
   char* fileName;
   int fd = 0;
   size_t bufSize = 1000;
   size_t amountRead = 0;
   char* text;
   int offset = 0;

   if(argv <= 1)
   {
      printf("Usages: encode [filenames...]\n");
      return 0;
   }

   text = (char *)malloc(sizeof(char) * bufSize);

   for(fileCount = 1; fileCount < argv; fileCount++)
   {
      fileName = argc[fileCount];
      fd = open(fileName, O_RDWR);
      printf("fd: %d\n", fd);
      amountRead = read(fd, (void *)text, bufSize);
      printf("Amount read: %d\n", amountRead);
      invertBytes(amountRead, text);
      offset = (int)lseek(fd, 0, SEEK_SET);
      printf("Lseek to %d\n", offset);
      offset = write(fd, text, amountRead);
      printf("write returned %d\n", offset);
      close(fd);
   }

   return 0;
}

void invertBytes(size_t amount, char* buffer)
{
   int byteCount = 0;
   printf("amount: %d\n", amount);
   for(byteCount = 0; byteCount < amount; byteCount++)
   {
      printf("%x, ", buffer[byteCount]);
      buffer[byteCount] = ~buffer[byteCount];
      printf("%x\r\n", buffer[byteCount]);
   }
   printf("byteCount: %d\n", byteCount);
}

【问题讨论】:

  • 你使用的是什么环境? openread 不是 Windows 原生的。
  • 这一切现在都是在 windows xp 上完成的。我从命令行编译它。
  • 是的,但是您使用的是哪个开发环境?
  • 哦,哈哈,我不是。我正在使用记事本++。
  • 您确定使用的是编译器和一个或多个运行时库吗?

标签: c windows file io


【解决方案1】:
fd = open(fileName, O_RDWR);

应该是

fd = open(fileName, O_RDWR | O_BINARY);

详情请见read() only reads a few bytes from file

【讨论】:

  • 哇,你是对的。我改变了那一行,现在它正在正确处理 \r 字符。如果我在 Linux 机器上编译它,我需​​要指定 O_BINARY 模式吗?我知道 unix 文件通常不包含 \r.
  • 不,在Linux上二进制模式和文本(?)模式之间没有区别。但是当然为了可移植性,最好还是使用 O_BINARY。
  • 我总是对二进制文件使用 O_BINARY,这只是礼貌的做法,并促进了与 cygwin 交叉编译的可移植性。
  • @Akron 这根本与 \r 无关:Windows 使用不同的模式将文件读取为文本或二进制文件,AFAIK 这个概念在 Linux 中不存在。所以:是的,你是对的,你在 Linux 上不需要 O_BINARY,但是不,这不是因为 Linux 文本文件使用 \n 作为行分隔符,而是因为 Linux 没有使用这种(恕我直言)方式来处理文件。
【解决方案2】:

尝试使用 O_BINARY 打开以使用二进制模式,文本模式可能是默认模式,可能会忽略 \r。

打开(文件名,O_RDWR|O_BINARY);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-14
    • 2010-10-17
    • 2017-04-25
    • 2011-02-15
    • 2015-09-22
    • 2016-11-15
    • 1970-01-01
    相关资源
    最近更新 更多