我正在使用此代码来读取文件:
char* fs_read_line(FILE* file)
{
if (file == NULL) {
return "CFILEIO: Error while reading the file: Invalid File";
}
long threshold = ftell(file);
fseek(file, 0, SEEK_END);
uint8_t* buffer = calloc(ftell(file)-threshold, sizeof(uint8_t));
if(buffer == NULL)
return;
int8_t _;
fseek(file, threshold, SEEK_SET);
uint32_t ct = 0;
while ((_ = (char)(fgetc(file))) != '\n'
&& _ != '\0' && _ != '\r' && _ != EOF) {
buffer[ct++] = _;
}
buffer = realloc(buffer, sizeof *buffer * (ct + 1));
buffer[ct] = '\0';
return buffer;
}
如果文件太大,我会得到(堆)溢出错误,可能是因为我最初使用它包含的字符总数来分配文件。
我尝试这样做的另一种方法是在每次迭代后通过realloc
缓冲区,但那不是我想要的方法。
有没有办法动态地改变数组的大小,具体取决于当前的迭代而不总是uisng realloc
?或者有没有办法通过ftell
和fseek
来确定当前行的持续时间?
答案 0 :(得分:0)
如果您的文件无法适合内存,则无法在内存中使用。您正在预先分配内存缓冲区,但是您犯了两个错误,导致您分配的内容超出了您的需要。
ftell(file) - threshold
个字节。sizeof(uint8_t *)
应该是sizeof(uint8_t)
。你分配的内存比应该多4或8倍。除此之外,在完成写入之后重新分配缓冲区的重点是什么?内存溢出已经发生。你应该在写之前分配(在while循环中)。但是,我根本没有看到重新分配的重点,因为你开始分配的内存超过了。
答案 1 :(得分:0)
代码不会返回指向字符串的指针。
返回的buffer
中没有空字符,因此调用代码无法知道已分配内存的长度。这肯定会导致调用代码出错。
重新分配时,添加1。
// buffer = realloc(buffer, ct * sizeof(uint8_t*));
// v--- no star
buffer = realloc(buffer, ct * sizeof(uint8_t ) + 1);
buffer[ct] = '\0';
// or better
size_t ct = 0;
...
buffer = realloc(buffer, sizeof *buffer * (ct + 1));
buffer[ct] = '\0';
有没有办法动态改变
数组分配的内存的大小,具体取决于当前的迭代而不总是使用realloc
?
数组大小无法更改。要动态更改已分配内存的大小,需要realloc()
。注意:可以在内存分配调用之前确定所需的内存量。
或者有没有办法使用
ftell
和fseek
确定当前行的时长?
与此代码一样,您已找到当前行长度的上限。 ftell
和fseek
找不到行尾。
代码可以使用fscanf(file, "%*[^\n]");
“追踪”到fgetc(file)
或1以后的行尾。
答案 2 :(得分:0)
以下代码:
char*
而不是uint8_t*
fseek()
时返回的值,并且无法检查每次调用ftell()
时的返回值,它应该这样做以确保操作那是成功的。我没有在我的回答中添加错误检查,以免混乱代码,但应该执行它。现在,代码:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
char* fs_read_line(FILE* file);
char* fs_read_line(FILE* file)
{
if ( !file )
{
return "CFILEIO: Error while reading the file: Invalid File";
}
// implied else, valid parameter
long threshold = ftell(file);
fseek(file, 0, SEEK_END);
char* buffer = calloc( (size_t)(ftell(file) - threshold) *2 +1, sizeof(char));
if(buffer == NULL)
return NULL;
// implied else, calloc successful
int ch;
fseek(file, threshold, SEEK_SET);
size_t ct;
while ( (ch = fgetc(file)) != '\n'
&& ch != '\0'
&& ch != '\r'
&& ch != EOF)
{
buffer[ct++] = (char)ch;
}
return buffer;
} // end function: fs_read_line