【问题标题】:How to read one byte at a time from an array?如何从数组中一次读取一个字节?
【发布时间】:2011-04-18 13:44:10
【问题描述】:

在 C 中,我如何从字节数组中读取一个字节,将其放入文件中,然后一遍又一遍地循环,直到找到我想停止读取的特定字节?

例子:

while  (x = fgetc(file) != EOF )
{
    count++;//Counts the number of bytes
}

chars = (unsigned char*) malloc (sizeof(unsigned char)*count+1);
rewind(file);

FILE* output_file = fopen("Filename.jpg", "rb");

while(chars[i] != specificByte)
{
    fwrite(?,?,?,?); 
}

这不是我使用的确切代码,但我只是想把一些东西放在那里以显示我遇到问题的地方。

直接从文件中读取而不是将字节放入数组中会更好吗?

【问题讨论】:

  • 如果你已经有了字节数组,为什么不直接遍历数组来找到你正在寻找的特定字节呢?
  • 好吧,不用考虑,我可以告诉你,第一个?应该是output_file
  • @T.E.D.下次,试着考虑一下:)fwrite() 中的第一个参数是包含您要写入的字节的缓冲区。 FILE* 位于末尾。另外,我很确定在已打开读取的文件上调用 fwrite() 会失败。
  • @Joey:在x = fgetc(file) != EOF 之后,x 将是01。这可能不是您想要的,尽管它适用于这种特定的 while 案例。
  • @JeremyP - 啊,这有什么好玩的? :-P

标签: c file fwrite


【解决方案1】:

如果我可以提出一个建议,在找到停止字节之前通读数组可能会更有效,然后在单个 I/O 中从头开始写入数组直到停止字节。

【讨论】:

    【解决方案2】:

    这是一个完整的 fread / fwrite 示例。

    但是我不确定将整个文件读入内存然后将其再次写入文件是否有任何意义,而您可以像之前的一些文件一样在读取输入文件的同时写入输出文件示例正在演示。

    我什至不确定这是否比使用 fgetc 和 fputc 更有效,但至少 文件是在一个函数调用中读取和写入

    #include <stdio.h>
    #include <stdlib.h>
    
    /* this function retrieves the size of the input file */
    long get_filesize(FILE *fp)
    {
        long filesize;
    
        fseek(fp, 0, SEEK_END);
        filesize = ftell(fp);
        rewind(fp);
    
        return filesize;
    }
    
    int main(void)
    {
        FILE *fp;
        unsigned char *data;
        long filesize;
        unsigned char specificByte = 10; /* line feed for example */
    
        /* open the input file */
        fp = fopen("input_file", "rb");
        if(fp == NULL) exit(EXIT_FAILURE);
    
        /* get the filesize */
        filesize = get_filesize(fp);
    
        /* allocate space for the file */
        data = malloc(filesize * sizeof(unsigned char));
        if(data == NULL) exit(EXIT_FAILURE);
    
        /* read the file into memory */
        fread(data, filesize, sizeof(unsigned int), fp);
        fclose(fp);
    
        /* open output file */
        fp = fopen("output_file", "wb");
        if(fp == NULL) {
            free(data);
            exit(EXIT_FAILURE);
        }
    
        /* check how many bytes should be written into output file */
        int i;
        for(i = 0; i < filesize && data[i] != specificByte; ++i);
    
        /* write the bytes */
        fwrite(data, i, sizeof(unsigned char), fp);
    
        /* close the file and free the memory */    
        fclose(fp);
        free(data);
    
        return EXIT_SUCCESS;
    }
    

    【讨论】:

      【解决方案3】:

      一个简单但有效的方法是完全避免读入内存,只需执行以下操作:

      while ((input_char = fgetc(input_fp)) != EOF)
      {
          if (input_char != specificByte)
          {
              fputc(input_char, output_fp);
          }
          else
          {
              /* do something with input_char */
          }
      }
      

      这在理论上是低效的,因为您一次从缓冲区读取一个字符,这可能会很昂贵。但是,对于许多应用程序来说,这将运行得很好,尤其是因为文件读取由 C 标准库缓冲。

      如果您确实关心效率并希望最大限度地减少对文件函数的调用,请使用以下内容。

      /* Don't loop through the chars just to find out the file size. Instead, use
       * stat() to find out the file size and allocate that many bytes into array.
       */
      char* array = (char*) malloc(file_size);
      fread(array, sizeof(char), file_size, input_fp);
      
      /* iterate through the file buffer until you find the byte you're looking for */
      for (char* ptr = array; ptr < array + file_size; ptr++);
      {
          if (*ptr == specificByte)
          {
              break;
          }
      }
      
      /* Write everything up to ptr into the output file */
      fwrite(array, sizeof(char), ptr - array, output_fp);
      
      /* ptr now points to the byte you're looking for. Manipulate as desired */
      

      【讨论】:

      • C 标准 I/O 函数的 f*() 系列由标准库缓冲,因此它不应该是每次访问的用户空间内核往返。
      • 我会选择第一个简单的选项,因为 fgetc() 像 unwind 所说的那样被缓冲,而且你也不需要在读取之前弄清楚文件的大小(所以它会也适用于终端和套接字 IO)。
      【解决方案4】:

      这是一种方法:

      int putResult = 0;
      
      for(int i = 0 ; i < BUFFER_SIZE && buffer[i] != specificByte && putResult != EOF ; ++i)
      {
          putResult = fputc(buffer[i]);
      }
      if (putResult == EOF)
      {
          // Deal with the error (in errno)
      }
      

      for 条件退出循环 if

      • i 到达缓冲区的末尾
      • 在缓冲区中找到特定字节
      • fputc() 返回错误。

      【讨论】:

        【解决方案5】:

        如果您不必一次读取整个文件,只需分配一个固定大小的缓冲区并完全避免malloc;如果您没有不得不搞乱动态内存管理,就不要搞乱动态内存管理。

        #define PAGE_SIZE ... // however big a chunk you process at a time
        ...
        unsigned char inbuf[PAGE_SIZE];
        unsigned char outbuf[PAGE_SIZE];
        
        FILE *input_stream = fopen(...);
        FILE *output_stream = fopen(...);
        
        while (fread(inbuf, sizeof inbuf, 1, input_stream))
        {
          unsigned char *r = inbuf, *w = outbuf;
          while (r != inbuf + sizeof inbuf && *r != specificByte)
            *w++ = *r++;
          fwrite(outbuf, (size_t) (w - outbuf), 1, output_stream);
          if (*r == specific_byte)
            break;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-03-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多