我正在为我的学校做一个项目,我无法找到如何获得文件的大小。因为我需要读取一个脚本并在我的程序中使用它,所以我需要使用read或fread这个文件的大小。
这是我为获取文件大小所做的,但它似乎不起作用。
int my_size(int filedesc)
{
int size = 1;
int read_output = 1;
char *buffer;
for (size = 1; read_output != 0 ; size++) {
buffer = malloc((size+1)*sizeof(char*));
read_output = read(filedesc, buffer, size);
free(buffer);
}
return(size);
}
并且我不允许使用stat()和fseek()作为此项目的规则,也不允许使用任意大小(如100)的read或fread,因为给出的脚本可能很小或很大。
如果您可以依赖输入作为持久文件(即驻留在存储介质上),并且在程序运行期间没有修改该文件,那么您可以预先读取它以计算其中的字节数,然后倒带。
但是在学术练习之外,禁止通过stat()
,fseek()
等测量大小的通常原因是输入可能不会驻留在存储介质上,因此
那么诀窍不是如何提前确定尺寸,而是如何在不预先测量尺寸的情况下确定尺寸。至少有两个主要策略:
malloc()
space和realloc()
。或者,您可以将内容存储在链接列表中,根据需要分配新的列表节点。至于问题中提出的方法,它有几个问题。它似乎是我第一次描述的尝试 - 将文件读到最后以确定其大小 - 但是
read()
将从文件的开头开始,或者如果read()
无法读取整个文件,那么它可能会失败。情况也不是这样。每个read()
将从文件的当前位置开始,并将文件保留在最后一个字节传输之后。lseek()
重绕。但是,如果lseek()
可以用于此目的(并且请注意我以前关于您无法搜索的文件的评论),那么它将提供一种更清晰的方法来测量文件的大小。ssize_t count_bytes(int fd) {
ssize_t num_bytes = 0;
char buffer[2048];
ssize_t result;
do {
result = read(fd, buffer, sizeof(buffer));
if (result < 0) {
// handle error ...
}
num_bytes += result;
while (result > 0);
return num_bytes;
}
在您的可执行文件中使用gdb
debugger或strace(1),使用所有警告和调试信息编译:gcc -Wall -Wextra -g
和GCC。仔细阅读read(2)的文档,以及你正在使用的每个函数(包括malloc(3),你忘记了test的失败)。
您需要使用read(2)的结果(实际读取字节数)。并且你需要特别处理错误情况(当read
给出-1时)。
有足够长的文件,可能会发生的事情是,在第一个循环中,您正在读取1个字节,在第二个循环上,您正在读取2个字节,在第三个循环上,您已读取3个字节,等等...(和您在这种情况下忘了计算1 + 2 + 3)。
你应该累积和总和所有的read_output
你应该处理read(2)给出少于size
的情况(这应该发生在你的read
最后一次非零)。
我建议使用固定缓冲区(常量或固定大小),并重复执行read(2),但要小心使用返回的字节数(也就是处理错误和EOF条件)。
请注意,system calls(在syscalls(2)中列出)非常昂贵。根据经验,你应该read(2)或write(2)一个几千字节的缓冲区(并仔细处理返回的字节数,也测试它的错误,请参阅errno(3))。每次只对几个字节进行read
的程序是低效的。
此外,malloc
(或realloc
)相当昂贵。将heap allocated大小增加一个是丑陋的(因为你在每个循环上调用malloc
;在你的情况下你甚至不需要使用malloc
)。你最好使用一些几何级数,也许是newsize = 4*oldsize/3 + 10;
(或类似的)。