复制具有不同大小的缓冲区的文件以进行读写

时间:2017-08-03 05:11:51

标签: c file buffer

我一直在为求职面试做一些练习问题,而且我遇到了一个我无法解决如何解决问题的功能。我们的想法是创建一个函数,该函数采用两个文件的名称,允许的缓冲区大小从file1读取,允许的缓冲区大小用于写入file2。如果缓冲区大小相同,我知道如何解决这个问题,但是当我确定如何在大小不同时在缓冲区之间移动数据时遇到问题。部分约束是我们必须在将写缓冲区写入文件之前始终填充写缓冲区。如果file1不是file2的倍数,我们用零填充最后一次缓冲区传输。

// input: name of two files made for copy, and their limited buffer sizes
// output: number of bytes copied
int fileCopy(char* file1,char* file2, int bufferSize1, int bufferSize2){
int bytesTransfered=0;
int bytesMoved=o;
char* buffer1, *buffer2;
FILE *fp1, *fp2;

fp1 = fopen(file1, "r");
if (fp1 == NULL) { 
    printf ("Not able to open this file"); 
    return -1;
}

fp2 = fopen(file2, "w");
if (fp2 == NULL) {
    printf ("Not able to open this file"); 
    fclose(fp1); 
    return -1;
}

buffer1 = (char*) malloc (sizeof(char)*bufferSize1);
if (buffer1 == NULL) {
    printf ("Memory error");
    return -1;
}

buffer2 = (char*) malloc (sizeof(char)*bufferSize2);
if (buffer2 == NULL) {
    printf ("Memory error"); 
    return -1;
}

bytesMoved=fread(buffer1, sizeof(buffer1),1,fp1);

//TODO: Fill buffer2 with maximum amount, either when buffer1 <= buffer2 or buffer1 > buffer2
//How do I iterate trough file1 and ensuring to always fill buffer 2 before writing?

bytesTransfered+=fwrite(buffer2, sizeof(buffer2),1,fp2);

fclose(fp1);
fclose(fp2);

return bytesTransfered;
}

如何在fwrites之前为缓冲区传输编写while循环?

3 个答案:

答案 0 :(得分:1)

  

我在确定如何在大小不同的情况下在缓冲区之间移动数据时遇到问题

制定计划。对于“求职面试的一些实践问题”,一个好的计划和能力来证明这一点很重要。编码虽然很重要,但却是次要的。

given valid: 2 FILE *, 2 buffers and their sizes
while  write active && read active
  while write buffer not full && reading active
    if read buffer empty
      read
      update read active
    append min(read buffer length, write buffer available space) of read to write buffer
  if write buffer not empty
    pad write buffer
    write 
    update write active
return file status 

现在编码吧。更强大的解决方案是使用structFILE*, buffer, size, offset, length, active变量进行分组。

// Return true on problem
static bool rw(FILE *in_s, void *in_buf, size_t in_sz, FILE *out_s,
    void *out_buf, size_t out_sz) {
  size_t in_offset = 0;
  size_t in_length = 0;
  bool in_active = true;
  size_t out_length = 0;
  bool out_active = true;

  while (in_active && out_active) {
    // While room for more data
    while (out_length < out_sz && in_active) {
      if (in_length == 0) {
        in_offset = 0;
        in_length = fread(in_buf, in_sz, 1, in_s);
        in_active = in_length > 0;
      }
      // Append a portion of `in` to `out`
      size_t chunk = min(in_length, out_sz - out_length);
      memcpy((char*) out_buf + out_length, (char*) in_buf + in_offset, chunk);
      out_length += chunk;
      in_length -= chunk;
      in_offset += chunk;
    }

    if (out_length > 0) {
      // Padding only occurs, maybe, on last write
      memset((char*) out_buf + out_length, 0, out_sz - out_length);
      out_active = fwrite(out_buf, out_sz, 1, out_s) == out_sz;
      out_length = 0;
    }
  }
  return ferror(in_s) || ferror(out_s);
}

其他说明;

  1. 不需要投射malloc()个结果。 @Gerhardh

     // buffer1 = (char*) malloc (sizeof(char)*bufferSize1);
     buffer1 = malloc (sizeof *buffer1 * bufferSize1);
    
  2. 使用stderr获取错误消息。 @Jonathan Leffler

  3. 以二进制文件打开文件。

  4. size_t对于数组/缓冲区大小比int更强大。

  5. sizeof buffer1sizeof (buffer1)视为sizeof object

  6. 不需要的问题

答案 1 :(得分:0)

while(bytesMoved > 0) {
    for(i=0; i<bytesMoved && i<bufferSize2; i++) 
        buffer2[i]=buffer1[i];

    bytesTransfered+=fwrite(buffer2, i,1,fp2);
    bytesMoved-=i;
}

如果bufferSize1小于filesize,则需要外部循环。

答案 2 :(得分:0)

正如您的问题的评论所示,此解决方案不是将数据从1个文件传输到另一个文件的最佳方式。但是,您的案例有一些限制,此解决方案可以解决这个问题。

(1)由于您使用的是缓冲区,因此您不需要一次读取和写入1个字符,而是可以尽可能少地调用这些函数

  

size_t fread(void * ptr,size_t size,size_t nmemb,FILE * stream);

:在fread的手册页中,nmemb可以= bufferSize1

(2)您需要检查fread()的回报(即bytesMoved)并将其与bufferSize 1和2进行比较。如果(a) bytesMoved(即从fread()返回)等于bufferSize1(b) {{1} }小于bufferSize2或从bufferSize1返回,那么您就知道仍有数据需要读取(或写入)。因此,您应该开始下一次数据传输,当完成后返回上一步时,您就停止了。

注意:如果数据大于bufferSizes,则fread()fread()中指向文件流的指针将从停止的位置开始。

<强>伪代码:

fwrite()