从二进制文件中读取动态大小的字符串
我需要知道如何使用fread()从二进制文件中读取字符串。
根据我的理解,事情是,如果我想将某些字符串的值复制到一个声明如下的新字符串:
char *string;
我需要先使用strlen()计算另一个字符串的长度,使用该值为malloc保留新字符串的内存 ,然后使用strcpy()将另一个字符串的值复制到我的新字符串中
有点像:
newLength = strlen ( otherString ) + 1; string = malloc ( sizeof ( char ) * newLength ); if ( string == NULL ) { return ( FALSE ) }
但是如果我从二进制文件中读取数据会发生什么,并且我试图从所述文件中读取一个字符串,但我事先并不知道它的长度,因此我不能使用malloc为所述字符串保留内存?
这是否有效,即使我还没有为字符串保留内存(我不太相信)?:
fread ( string, sizeof ( char ), strlen ( string ), currentFile );
我现在有点卡住了。 希望你们能给我一些启示并引导我一点。
你的问题有一些混合的内容。 你说’二进制’文件,但你想从它读取字符串数据。 从文件中解析字符串通常意味着该文件本质上是文本的。 然而,在不知道先验 ,你正在读取的字符串的长度,你可以逐字节读取文件,计算字节,直到你到达字符串终止符,之后你分配一致的缓冲区,倒回文件,和读入你的缓冲区。
或者,您可以预先分配一个任意大的缓冲区,而不用担心未使用的数量。 如果需要读取许多不同的数量,通过预先分配最佳分配的内存来读取每个字符串,可能会更节俭,如果耗尽缓冲区,可能使用realloc() 。
fread()不会执行字符串导向读取,例如fscanf() ,它将使用%s格式说明符扫描的字符串为空终止。 fread()与数据无关,如果文件结束,则只是填充指定的缓冲区。 如果’二进制’数据包含空终止符,也许这就是你想要使用的,但在我看来,值得重新思考。
只有在打算使用字符串指针进行动态内存分配时,您的声明才适用。 如果要使用定义为字符串分配存储空间,则必须将其定义为数组类型。
char string[1000];
只要您跟踪实际使用的内存量,就可以分配比您使用的内存更多的内存(在合理的限制范围内 – 您不会为8字节字符串分配64 kB)。
fread
返回读取的元素数量(可能小于请求的项目数),如果您正在读取字符串,则应在分配的字符串中的这么多字节后添加一个0
字节:
// we'll read at most 255 bytes // C strings always need one extra '\0' byte at the end, though char *string = malloc(256); // open file "test.txt" FILE *fp = fopen("test.txt", "r"); // read text from file, and store the number of characters read in len size_t len = fread(string, sizeof(char), 255, fp); // note that you can't use strlen(string) here because string doesn't have any data // so we just tell it to read "as many bytes it can, up to a maximum of 255" // add '\0' byte to the end because all C strings require this, // and fread() doesn't add this for us string[len] = '\0'; // note that string[len] is the (len+1)th character
从文件中读取字符串很棘手,因为许多用户称“文本行”(各种char
后跟'\n
‘)称为“字符串”。 但在C中,“字符串”是各种char
后跟'\0'
。
fgets()
, scanf()
和fread()
无法从文件中读取C字符串。 没有人能够轻易读到'\0'
。
假设您想要读取任意长的“C字符串”:建议使用fgetc()
。
char *ReadString(FILE *inf) { if (inf == NULL) return NULL; size_t size = 1; char *buf = malloc(size); if (buf == NULL) { return Handle_AllocFailure(); } size_t i = 0; int ch; while ((ch = fgetc(inf)) != EOF && ch != '\0') { if (i + 1 >= size) { size_t newsize = (size + 1) * 4 - 1; char *newbuf = realloc(buf, newsize); if (newbuf == NULL) { return Handle_AllocFailure(); } buf = newbuf; size = newsize; } buf[i++] = ch; } buf[i++] = '\0'; // If a final re-size is desired... char *newbuf = realloc(buf, i); if (newbuf == NULL) { return Handle_AllocFailure(); } buf = newbuf; return buf; } FILE *inf; ... char *buf = ReadString(inf); ... free(buf);