Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.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
如何获取文件';在不使用fseek或stat的情况下,以C表示的s大小?_C_File_Size - Fatal编程技术网

如何获取文件';在不使用fseek或stat的情况下,以C表示的s大小?

如何获取文件';在不使用fseek或stat的情况下,以C表示的s大小?,c,file,size,C,File,Size,我正在为我的学校做一个项目,但我不知道如何获得文件的大小。因为我需要读取脚本并在程序中使用它,所以我需要文件的大小来使用read或fread 下面是我为获得文件大小所做的工作,但它似乎不起作用 int my_size(int filedesc) { int size = 1; int read_output = 1; char *buffer; for (size = 1; read_output != 0 ; size++) { buffer

我正在为我的学校做一个项目,但我不知道如何获得文件的大小。因为我需要读取脚本并在程序中使用它,所以我需要文件的大小来使用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()作为此项目的规则,也不能使用read或fread(任意大小,如100),因为给定的脚本可以是小的也可以是大的。

如果您可以依赖输入作为持久文件(即驻留在存储介质上),并且在程序运行期间该文件未被修改,然后你可以预读到最后,计算其中的字节数,然后倒带

但是,除了学术练习之外,禁止通过
stat()
fseek()
和类似方法测量大小的通常原因是输入可能不驻留在存储介质上,因此

  • 不阅读它就无法确定它的大小,但是
  • 你不能倒带它或在其中寻找
  • 因此,诀窍不是如何预先确定尺寸,而是如何在不预先测量尺寸的情况下确定尺寸。为此,至少有两种主要策略:

    • 首先,不要依赖于将全部内容一次性存储在内存中。取而代之的是,在读取内容时对其进行操作,在任何给定的时间只在内存中保留足够的内容

    • 或者,动态适应文件大小。这方面有很多变化。例如,如果您只是将文件读入一个单片块,那么当您发现需要更多时,您可以
      malloc()
      space和
      realloc()
      。也可以将内容存储在链表中,根据需要分配新的列表节点

    至于问题中提出的方法,有几个问题。这似乎是我第一次描述的尝试——将文件读到底以确定其大小——但是

  • 它似乎假设每个
    read()
    都将从文件的开头开始,或者如果无法读取完整文件,则
    read()
    可能会失败。情况也并非如此。每个
    read()
    将从文件的当前位置开始,并在传输最后一个字节后保留文件的位置

  • 因为它改变了文件的位置,所以您的方法将要求文件在以下情况下被重绕:例如,通过
    lseek()
    。但是如果
    lseek()
    可以用于此目的(请注意我之前对无法查找的文件的评论),那么它将提供一种更干净的方法来测量文件大小

  • 您不需要考虑I/O错误。如果发生了这样的情况,它可能会将您的程序发送到一个无限循环中

  • 动态分配相对来说比较昂贵,而且你做了很多。如果您想实施阅读前策略,那么这将是一个更好的实施:

    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;
    }
    
    ssize\u t count\u字节(int-fd){
    ssize_t num_bytes=0;
    字符缓冲区[2048];
    对结果进行量化;
    做{
    结果=读取(fd、缓冲区、sizeof(缓冲区));
    如果(结果<0){
    //处理错误。。。
    }
    num_bytes+=结果;
    而(结果>0);
    返回num_字节;
    }
    
  • 在您的可执行文件上,使用或将编译所有警告和调试信息:
    gcc-Wall-Wextra-g
    with。仔细阅读您正在使用的每个函数的文档(包括您忘记了其故障的函数)

    您需要使用的结果(实际读取的字节数),并且需要专门处理错误情况(当给出-1时)

    在文件足够长的情况下,可能发生的情况是,在第一个循环中读取1个字节,在第二个循环中读取2个字节,在第三个循环中读取3个字节,等等(在这种情况下,您忘记计算1+2+3)

    您应该累计和汇总所有的
    读取输出
    ,并且当给出的值小于
    大小
    (这应该发生在您上次的
    读取
    给出非零时)时,您应该处理这种情况

    相反,我建议使用固定的缓冲区(常量或固定大小),并反复使用返回的字节计数(还有,处理错误和EOF条件),但要小心

    请注意(中列出的)非常昂贵。根据经验,您应该使用一个几千字节的缓冲区(并仔细处理返回的字节计数,并对其进行错误测试,请参阅)。每次只运行几个字节的程序效率低下


    另外,
    malloc
    (或
    realloc
    )相当昂贵。将大小增加1是很难看的(因为你在每个循环中调用
    malloc
    ;在你的情况下,你甚至不需要使用
    malloc
    )。你最好使用一些几何级数,也许
    newsize=4*oldsize/3+10;
    (或类似).

    如果你不能使用
    fseek
    ,你需要实现你自己的
    fseek
    ,就像你可以做
    size\u t count=0;而(getchar()!=EOF)count++
    -但是为什么你不能使用
    fseek()
    plus
    ftell()
    stat()
    (大概
    fstat
    也是不允许的)?拒绝这些内容的动机是什么?您的输入可能来自终端、管道或其他不可查找(不可重复)的设备吗?您需要保存文件内容的副本吗?@无用:按上述方法重复读取(),您将无法获得正确的大小,如read()函数将从上一次读取操作设置的偏移量中读取。您的代码是特殊的。您首先排除文件为空的可能性。您为2个字节分配空间;您读取一个字节;您释放缓冲区;您将
    size
    1
    增加到2;您分配