【问题标题】:read system call doesn't detect end of file读取系统调用未检测到文件结尾
【发布时间】:2017-01-13 18:53:28
【问题描述】:

我正在尝试创建一个函数,该函数使用可以随时更改的特定读取大小读取整个文件,但是读取系统调用不会将字符正确存储在缓冲区中,到目前为止我只是想像这样打印到文件末尾:

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

# define READ_SIZE (42)

int main(int argc, char **argv)
 {
   int fd;
   int rd;
   char *buffer;

   buffer = malloc(READ_SIZE);
   fd = open(argv[1], O_RDONLY);
   while ((rd = read(fd, buffer, READ_SIZE)) > 0)
    {
       printf("%s", buffer);
    }
    return (0);
 }

这是我要读取的文件:

test1234
test123
test1
test2
test3
test4
test

这是我的程序的输出:

test123
test12
test1
test2
test3
test4
testest123
test12
test1
test2
test3
test4
tes

我只能用malloc和read来处理这个,open只是为了测试,我不明白为什么会这样,通常read返回该文件中读取的字节数,如果是0到达文件末尾,所以看到这个有点奇怪。

【问题讨论】:

  • 由于while() 语句中的括号不平衡,您的程序无效且无法编译。缺少括号的位置会影响代码的含义。
  • 在使用printf之前忘记NULL终止缓冲区
  • @user161151 NULL空指针常量。当然,您的意思是 null 字符'\0'
  • @chux 我当然愿意。
  • @James 如果您的新代码有与此相同的问题(使用%s 打印缺少空字符的字符数组),那么新代码也会被捕获在 未定义行为 i> (UB) 陷阱。它可能今天有效,明天失败。

标签: c string posix c-strings


【解决方案1】:

字符数组的打印缺少空字符。这是 "%s" 的 UB。

printf("%s", buffer);  // bad

要限制打印缺少空字符的字符数组,请使用精度修饰符。这将打印字符数组,最多可以有这么多字符或空字符 - 哪个是第一个。

// printf("%s", buffer);
printf("%.*s", rd, buffer);

调试提示:打印带有标记的文本以清楚地指示每次打印的结果。

printf("<%.*s>\n", rd, buffer);

【讨论】:

  • 它可以正确打印字符是的,但是我如何在将字符存储在另一个缓冲区中来实现这一点,以包含文件中的所有字符。
  • @James 这个答案是针对当前问题的,它的“到目前为止,我只是想打印到像这样的文件结尾”和“我不明白为什么会这样”。您的comment 提出了一个更适合作为新帖子的新问题。一次一个问题。
  • "调试提示:打印带有标记的文本" 是的,是的,我的演讲自古以来! :-) +++1
  • 还不错^_^感谢您的帮助,我会搜索更多,如果我没有任何进展,我会再次发布
【解决方案2】:

除了chux's answer 提供的非常优雅的解决方案之外,您还可以在打印之前显式终止缓冲区(并且仅将其设为 C-“字符串”):

while ((rd = read(fd, buffer, READ_SIZE-1)) > 0) /* read one less, to have a spare 
                                                    char available for the `0`-terminator. */
{
  buffer[rd] = '\0';
  printf("'%s'", buffer);
}

【讨论】:

  • 推荐这个fine advice它来自可靠的来源。
  • @chux:改编! :))
  • 结果比原来好,但我明白它是如何工作的,我会看看如何解决它,谢谢大家^_^
  • 顺便说一句,使用调试器(主要)有助于识别“奇怪”行为的根本原因...... ;-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-13
  • 2016-10-14
  • 1970-01-01
  • 1970-01-01
  • 2019-05-10
  • 2013-07-14
相关资源
最近更新 更多