简体   繁体   English

M基于现有文件分配文件缓冲区的大小

[英]Malloc the size of file buffer base on an existing file

On my project, I need to copy the shared file into a directory which called share. 在我的项目中,我需要将共享文件复制到一个名为share的目录中。 My idea is to copy the contains of this file use fgets and fputs: 我的想法是使用fgets和fputs复制此文件的包含内容:

FILE *fp;
int size;
char *fileBuff

fseek(fp,0,SEEK_END );
size=ftell(fp);
printf("Size of %s: %d bytes.\n",path,size); // print correct size 
fileBuff=malloc(size); // mallocate the file buffer
printf("\nsize of file buffer is %d",sizeof(fileBuff)); //always print 4!!
while(!feof(fp)){
    fgets(fileBuff,size,fp); // put into file buffer

}
printf("\nsize of file buffer is %d",sizeof(fileBuff)); // also print 4!!

However, the file buffer cannot be mallocated, the size of this file buffer is always 4. what happen? 但是,不能分配文件缓冲区,该文件缓冲区的大小始终为4.。会发生什么?

update: it seems have some misunderstanding. 更新:似乎有些误会。 the sizeof() if just for my to check whether there is any thing stored in the file buffer. sizeof()是否仅用于检查文件缓冲区中是否存储了任何内容。 I do try strlen(fileBuff), and it gives me 1, always. 我确实尝试了strlen(fileBuff),它总是给我1,

This is wrong: sizeof(fileBuff) . 这是错误的: sizeof(fileBuff) This will be the size of the pointer, which is 4 on your system. 这将是指针的大小,在您的系统上为4。

You cannot use sizeof to "extract" the size of a block of memory returned by malloc() . 您不能使用sizeof来“提取” malloc()返回的malloc()块的大小。 You can't use anything to extract that size, it's simply not possible in (standard) C. You need to use the size value, ie the argument to malloc() . 您不能使用任何东西来提取该大小,在(标准)C语言中根本不可能。您需要使用size值,即malloc()的参数。

Also, ftell() returns long , not int and both malloc() and the various I/O calls can fail, which you need to take into account. 同样, ftell()返回long ,而不是int并且malloc()和各种I / O调用都可能失败,您需要考虑到这一点。

In my opinion, it's not a good idea to use a buffer the size of the file to do a simple copy; 我认为,使用文件大小的缓冲区进行简单复制不是一个好主意。 it's much better to use a "reasonable" buffer (whose exact optimal size depends on a lot of factors) and then do repeated read-write pairs in a loop until you've streamed through the entire file. 最好使用“合理的”缓冲区(其确切的最佳大小取决于很多因素),然后在循环中进行重复的读写对,直到流过整个文件为止。

UPDATE Further points about your code: 更新有关您的代码的其他要点:

  1. You talk about using strlen() but the code shows sizeof after the fread() , too. 您谈论使用strlen()但是代码也在fread()之后显示sizeof
  2. You talk about using sizeof to "check" if there is anything in the buffer, this is not possible; 您谈论使用sizeof来“检查”缓冲区中是否有任何东西,这是不可能的; any expression with sizeof is always evaluated at compile-time 1 , it cannot be used to check dynamic things like that. 任何带有sizeof表达式总是在编译时1进行求值,它不能用于检查像这样的动态事物。 And, again, you cannot use it to compute the size of a block of memory returned by malloc() . 同样,您不能使用它来计算malloc()返回的malloc()块的大小。
  3. Using strlen() on a buffer holding file data only works reliably if the file is binary and contains a '\\0' in its last position, otherwise you will have an unterminated string and strlen() might invoke undefine behavior. 在保存文件数据的缓冲区上使用strlen()仅在文件为二进制文件且最后一个位置包含'\\ 0'时才能可靠地工作,否则,您将拥有一个不终止的字符串,并且strlen()可能会调用未定义的行为。
  4. As I said, you need to check if malloc() returns NULL , which it will do if it fails to allocate the requested block of memory. 如我所说,您需要检查malloc()返回NULL ,如果它未能分配所请求的内存块,它将执行此操作。

1 Except for flexible arrays in C99, but let's ignore that. 1除了C99中的灵活数组外,让我们忽略它。

99 developers will now answer that you are taking the size of a pointer. 现在有99位开发人员将回答您正在使用指针大小。 I don't even have to look at the code. 我什至不必看代码。

The size of a pointer ( char * ) on your (32-bit) platform is always 4. 您的(32位)平台上的指针( char * )的大小始终为4。

You can't use sizeof to determine how much memory has been allocated for a buffer. 您不能使用sizeof来确定为缓冲区分配了多少内存。

To check if the pointer has been allocated, check the return value of malloc() : 要检查指针是否已分配,请检查malloc()的返回值:

fileBuff = malloc(size);

if (fileBuff == 0) {
   fprintf(stderr, "Error allocating %d bytes.\n", size);
   abort();
}

sizeof is evaluated at compile time, since you are asking for sizeof of filebuf which is a char* compiler calculates that it is 4 bytes (Since size of the pointer is 4 bytes ub your platform) and prints it. sizeof是在编译时求值的,因为您要查询filebuf sizeof ,而char*编译器会计算它的大小为4个字节(因为指针的大小为平台的4个字节),然后打印出来。 The malloc you did has nothing to do with sizeof . 您执行的mallocsizeof无关。

Apart the improper use of sizeof() you may consider 2 more thoughts: 除了不正确地使用sizeof()之外,您还可以考虑以下两种想法:

If it's just to copy a file: Don't try to reinvent the wheel and just use the system() function and call the OS program designed for that ( cp on unix, copy on DOS/Windows). 如果只是复制文件:不要尝试重新发明轮子,而只需使用system()函数并调用为此目的设计的OS程序(Unix上为cp ,在DOS / Windows上为复制 )。

If it's for training purposes and you therefore insist to do it by yourself: Don't try to read in the whole file and then write it out again, but read and write chunk by chunk. 如果是出于培训目的,因此您坚持要自己做:不要尝试读入整个文件,然后再次将其写出,而是逐块读取和写入。 Using to big buffer sizes only results in rendering the CPU cache worthless. 使用大缓冲区只会导致CPU缓存变得毫无价值。 Usually matching the file system buffer size or a simple fraction of it is a goot chunk size, so the pseudo code should look like: 通常与文件系统缓冲区大小匹配或仅占其很小一部分的就是goot块大小,因此伪代码应类似于:

open input file for reading
open output file for writing
as long as read from input file BUFSIZE bytes and read bytes > 0
     do write read data to output file
close input file
close output file

(and don't forget to check for I/O errors after each call to an I/O routine!) (并且不要忘记在每次调用I / O例程后检查I / O错误!)

And last note: Don't use fgets() unless you know for sure it's a always a plain text file. 最后一点:不要使用fgets(),除非您确定它始终是纯文本文件。 If you choose to use the fread()/fwrite() you are save, even if it's a binary file (and it's faster, too). 如果您选择使用fread()/ fwrite() ,即使它是二进制文件(而且速度也更快),您将被保存。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM