如何在使用 getc 和 putc 时添加缓冲

Posted

技术标签:

【中文标题】如何在使用 getc 和 putc 时添加缓冲【英文标题】:How to add buffering while using getc and putc 【发布时间】:2020-10-22 11:43:41 【问题描述】:

我想使用 c FILE 进行复制/粘贴,但我也需要添加读/写缓冲区,但我不知道如何添加它。有没有类似普通读/写的功能。代码如下。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[]) 
    FILE* fsource, * fdestination;

    printf("enter the name of source file:\n");
    char sourceName[20], destinationName[20];
    strcpy(sourceName, argv[1]);
    strcpy(destinationName, argv[2]);


    fsource = fopen(sourceName, "r");
    if (fsource == NULL)
        printf("read file did not open\n");
    else
        printf("read file opened sucessfully!\n");
    fdestination = fopen(destinationName, "w");
    if (fdestination == NULL)
        printf("write file did not open\n");
    else
        printf("write file opened sucessfully!\n");

    char pen = fgets(fsource);
    while (pen != EOF)
    
        fputc(pen, fdestination);
        pen = fgets(fsource);
    


    fclose(fsource);
    fclose(fdestination);
    return 0;

【问题讨论】:

您可能正在寻找freadfwrite 我把 fgets 改成了 fgetc j 正确的错误消息被写入标准错误并包含失败的原因:if( fsource == NULL ) perror(sourceName); exit(EXIT_FAILURE; 你的问题对我来说毫无意义。 fgetsfgetc 是缓冲读取。你想做什么? 不要复制 argv。如果您想要一个比argv[1] 更具可读性的名称(这是一件非常合理的事情),则无需复制数据。相反,只需执行 const char *sourceName = argv[1]; 通过将 sourceName 设置为大小为 20 的数组,然后使用未经检查的 strcpy,您会暴露一个简单的缓冲区溢出。 【参考方案1】:

这是对您的代码进行的改造(没有一些错误处理),它以 256 字节的增量进行读写:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[]) 
  char *sourceName = argv[0];
  char destName[256];
  snprintf(destName, 256, "%s.copy", sourceName);
  printf("Copying %s -> %s\n", sourceName, destName);
  FILE *fsource = fopen(sourceName, "rb");
  FILE *fdest = fopen(destName, "w");
  char buffer[256];
  for (;;) 
    size_t bytesRead = fread(buffer, 1, 256, fsource);
    if (bytesRead == 0) 
      break;
    
    if (fwrite(buffer, 1, bytesRead, fdest) != bytesRead) 
      printf("Failed to write all bytes!");
      break;
    
    printf("Wrote %ld bytes, position now %ld\n", bytesRead, ftell(fdest));
  
  fclose(fsource);
  fclose(fdest);
  return 0;

输出例如

$ ./so64481514
Copying ./so64481514 -> ./so64481514.copy
Wrote 256 bytes, position now 256
Wrote 256 bytes, position now 512
Wrote 256 bytes, position now 768
Wrote 256 bytes, position now 1024
[...]
Wrote 168 bytes, position now 12968

【讨论】:

你为什么要延续复制 argv 的讽刺意味? @WilliamPursell 在不提示用户输入文件名的情况下使其独立。 但不是使用strncpy,而是演示char *destName = argv[i]似乎更干净 这需要边界检查 re argc 和程序的使用说明。我的意思是你可以运行这个程序,它会复制自己。

以上是关于如何在使用 getc 和 putc 时添加缓冲的主要内容,如果未能解决你的问题,请参考以下文章

C 语言文件操作 ( getc 和 putc 函数 )

getc_unlocked,putc_unlocked,getchar_unlocked,putchar_unlocked

调用 get(fgetc) 和 putc(fputc) 函数进行输入输出

C 语言文件操作 ( C 语言中的文件操作函数 | 磁盘与内存缓冲区 | 缓冲区工作机制 )

I/O 函数总结

fwite/putc 如何写入磁盘?