Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 复制具有不同大小的读写缓冲区的文件_C_File_Buffer - Fatal编程技术网

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

C 复制具有不同大小的读写缓冲区的文件,c,file,buffer,C,File,Buffer,我一直在为求职面试做一些练习题,但我遇到了一个无法集中精力解决的问题。其思想是创建一个函数,该函数采用两个文件的名称,以及允许从file1读取的缓冲区大小和允许写入file2的缓冲区大小。如果缓冲区大小相同,我知道如何解决这个问题,但是当大小不同时,我在计算如何在缓冲区之间移动数据时遇到了问题。部分限制是,在将写缓冲区写入文件之前,我们必须始终填充写缓冲区。如果file1不是file2的倍数,我们用零填充最后一次缓冲区传输 // input: name of two files made for

我一直在为求职面试做一些练习题,但我遇到了一个无法集中精力解决的问题。其思想是创建一个函数,该函数采用两个文件的名称,以及允许从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;
}
//输入:为复制而创建的两个文件的名称及其有限的缓冲区大小
//输出:复制的字节数
int fileCopy(char*file1、char*file2、int bufferSize1、int bufferSize2){
int bytesttransfered=0;
int字节=o;
字符*buffer1,*buffer2;
文件*fp1,*fp2;
fp1=fopen(文件1,“r”);
如果(fp1==NULL){
printf(“无法打开此文件”);
返回-1;
}
fp2=fopen(文件2,“w”);
如果(fp2==NULL){
printf(“无法打开此文件”);
fclose(fp1);
返回-1;
}
buffer1=(char*)malloc(sizeof(char)*bufferSize1);
if(buffer1==NULL){
printf(“内存错误”);
返回-1;
}
buffer2=(char*)malloc(sizeof(char)*bufferSize2);
if(buffer2==NULL){
printf(“内存错误”);
返回-1;
}
bytesMoved=fread(buffer1,sizeof(buffer1),1,fp1);
//TODO:在buffer1 buffer2时使用最大数量填充buffer2
//如何迭代文件1并确保在写入前始终填充缓冲区2?
bytesttransfered+=fwrite(buffer2,sizeof(buffer2),1,fp2);
fclose(fp1);
fclose(fp2);
通过转移返回;
}
在fwrite之前,如何为缓冲区传输编写while循环?

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

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

对于(i=0;i,正如对您问题的评论所指出的,此解决方案不是将数据从一个文件传输到另一个文件的最佳方式。但是,您的案例有某些限制,这是此解决方案的原因

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

大小\u t fread(void*ptr、大小\u t size、大小\u t nmemb、文件*流)

:从
fread
的手册页中,
nmemb
can=
bufferSize1

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

注意:如果数据大于缓冲区大小,则指向
fread()
fwrite()
中文件流的指针将从其停止的位置开始

伪代码:

/* in while() loop continue reading from file 1 until nothing is left to read */
while (bytesMoved = fread(buffer1, sizeof(buffer1), bufferSize1, fp1))
{

    /* transfer from buffer1 to buffer2 */
    for(i = 0; i < bytesMoved && i < bufferSize2; i++)
        buffer2[i] = buffer1[i];
    buffer2[i] = '\0';

    iterations = 1; /* this is just in case your buffer2 is super tiny and cannot store all from buffer1 */
    /* in while() loop continue writing to file 2 until nothing is left to write 
        to upgrade use strlen(buffer2) instead of bufferSize2 */
    while (bytesTransfered = fwrite(buffer2, sizeof(buffer2), bufferSize2, fp2))
    {    
        /* reset buffer2 & write again from buffer1 to buffer2 */
        for(i = bufferSize2 * iterations, j = 0; i < bytesMoved && j < bufferSize2; i++, j++)
            buffer2[j] = buffer1[i];
        buffer2[j] = '\0';
        iterations++;
    }
    /* mem reset buffer1 to prepare for next data transfer*/
}
/*在while()循环中继续读取文件1,直到没有任何内容可读取为止*/
而(bytesMoved=fread(buffer1,sizeof(buffer1),bufferSize1,fp1))
{
/*从缓冲区1传输到缓冲区2*/
对于(i=0;i
当缓冲区大小不同时,我在计算如何在缓冲区之间移动数据时遇到问题

规划一个计划。对于“面试中的一些实践问题”,一个好的计划和证明它的能力是重要的。编码,虽然重要,但是次要的

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 
现在对其进行编码。一个更健壮的解决方案是使用
struct
文件*、缓冲区、大小、偏移量、长度、活动的
变量进行分组

// 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);
}
  • 使用
    stderr
    查看错误消息

  • 用二进制文件打开文件

  • size\u t
    对于数组/缓冲区大小比
    int
    更健壮

  • sizeof buffer1
    sizeof(buffer1)
    视为
    sizeof对象不需要的参数


  • 这肯定是一个人为的问题,因为如果您使用
    文件*
    进行读写操作,stdio包在读写端都进行自己的缓冲,因此在高级代码中看到的缓冲区大小与实际的读写计数没有关系。这是一个“更好”的答案(虽然可能不是您的讲师想要的)将调用
    setvbuf
    两次,在
    fp1
    fp2
    上设置大小正确的缓冲区,然后编写一个普通的单缓冲区复制循环,根本不必担心重新打包,因为stdio最终会为您执行此操作。请不要强制转换
    malloc
    的返回值,您应该在standard上报告错误错误。当无法打开文件时,应在错误消息中指定文件名。应以换行符结束错误消息。应
     // buffer1 = (char*) malloc (sizeof(char)*bufferSize1);
     buffer1 = malloc (sizeof *buffer1 * bufferSize1);