C 是否可以在不将文件加载到内存的情况下读取文件?

C 是否可以在不将文件加载到内存的情况下读取文件?,c,file,memory,C,File,Memory,我想读取一个文件,但它太大,无法完全加载到内存中 有没有一种方法可以在不载入内存的情况下读取它?还是有更好的解决方案 我想读取一个文件,但它太大,无法完全加载到内存中 请注意,在实践中,这是一个由你的thru提供的(某种程度上是一个幻觉)。阅读(可免费下载)了解有关操作系统的更多信息。文件可能相当大(即使大多数文件都很小),例如,在当前的笔记本电脑或台式机上有几十GB的文件(许多文件在服务器上,甚至更多) 您没有定义什么是内存,C11标准以不同的方式使用该词,在§3.14中提到内存位置,在§7.

我想读取一个文件,但它太大,无法完全加载到内存中

有没有一种方法可以在不载入内存的情况下读取它?还是有更好的解决方案

我想读取一个文件,但它太大,无法完全加载到内存中

请注意,在实践中,这是一个由你的thru提供的(某种程度上是一个幻觉)。阅读(可免费下载)了解有关操作系统的更多信息。文件可能相当大(即使大多数文件都很小),例如,在当前的笔记本电脑或台式机上有几十GB的文件(许多文件在服务器上,甚至更多)

您没有定义什么是内存,C11标准以不同的方式使用该词,在§3.14中提到内存位置,在§7.22.3中提到内存管理功能

在实践中,a有它的,与

在许多情况下,尤其是Linux和POSIX,您可以使用和相关的更改虚拟地址空间,并且可以使用

有没有一种方法可以在不载入内存的情况下读取它

当然,您可以读取和写入某些文件的部分块(例如,使用、或较低级别的系统调用、、…)。出于性能原因,最好使用大缓冲区(至少几千字节)。在实践中,大多数(或)可以在很长的数据流上分块计算

许多库都是在这些原语之上构建的(按块执行直接IO)。例如,数据库库能够处理(超过可用RAM)的数据库文件。您可以使用(它们是用C或C++编写的软件)

因此,您当然可以处理比可用RAM大的文件,并按块(或“记录”)读写它们,至少从20世纪60年代起就是这样。我甚至可以说,从直觉上看,文件可以(通常)比RAM大很多,但比单个磁盘小(然而,即使这并不总是正确的;有些文件系统能够跨越多个物理磁盘,例如使用技术)

(在我的内存为32GB的Linux桌面上,最大的文件有69GB,在一个可用空间为669G、总空间为780G的ext4文件系统上,过去我的文件超过100GB)

您可能会发现值得使用一些数据库(或者是一些RDBMS之类的客户机,等等),或者您可能对索引文件的库感兴趣,例如。当然,您也可以执行直接I/O操作(例如,
fseek
然后
fread
fwrite
,或
lseek
然后
读取
写入
,或
pwrite
…)

我想读取一个文件,但它太大,无法完全加载到内存中

请注意,在实践中,这是一个由你的thru提供的(某种程度上是一个幻觉)。阅读(可免费下载)了解有关操作系统的更多信息。文件可能相当大(即使大多数文件都很小),例如,在当前的笔记本电脑或台式机上有几十GB的文件(许多文件在服务器上,甚至更多)

您没有定义什么是内存,C11标准以不同的方式使用该词,在§3.14中提到内存位置,在§7.22.3中提到内存管理功能

在实践中,a有它的,与

在许多情况下,尤其是Linux和POSIX,您可以使用和相关的更改虚拟地址空间,并且可以使用

有没有一种方法可以在不载入内存的情况下读取它

当然,您可以读取和写入某些文件的部分块(例如,使用、或较低级别的系统调用、、…)。出于性能原因,最好使用大缓冲区(至少几千字节)。在实践中,大多数(或)可以在很长的数据流上分块计算

许多库都是在这些原语之上构建的(按块执行直接IO)。例如,数据库库能够处理(超过可用RAM)的数据库文件。您可以使用(它们是用C或C++编写的软件)

因此,您当然可以处理比可用RAM大的文件,并按块(或“记录”)读写它们,至少从20世纪60年代起就是这样。我甚至可以说,从直觉上看,文件可以(通常)比RAM大很多,但比单个磁盘小(然而,即使这并不总是正确的;有些文件系统能够跨越多个物理磁盘,例如使用技术)

(在我的内存为32GB的Linux桌面上,最大的文件有69GB,在一个可用空间为669G、总空间为780G的ext4文件系统上,过去我的文件超过100GB)


您可能会发现值得使用一些数据库(或者是一些RDBMS之类的客户机,等等),或者您可能对索引文件的库感兴趣,例如。当然,您也可以执行直接I/O操作(例如,
fseek
然后
fread
fwrite
,或
lseek
然后
读取
写入
,或
pwrite

如果问题是RAM,而不是虚拟地址空间,那么一种方法是内存映射文件,在POSIX系统上或/在Windows上

这可以让你们得到一个看起来像原始文件字节数组的东西,但操作系统负责在你们运行的过程中对内容进行分页(若你们修改了内容,将它们写回磁盘)。当映射为只读时,它非常类似于只
malloc
-ing一个内存块和
fread
-ing填充它,但是:

  • 它是懒惰的:对于一个1GB的文件,你不需要等待5-30秒就可以读入整个文件,而只需在访问时为每一页付费(有时,操作系统会在后台预读,所以你甚至不需要等待每一页的加载)
  • 它在记忆压力下反应更好;如果内存不足,操作系统可以直接从内存中删除干净的页面,而无需将其写入交换,因为它知道它可以在需要时从文件中的金色副本将其重新分页;使用
    malloc
    -ed内存,它必须写入i
    #include <stdio.h>
    #include <string.h>
    #include <errno.h>
    #include <stdlib.h>
    #include <glib.h>
    
    int main(void) {
        char filename[] = "test.txt";
    
        // Create a SHA256 checksum
        GChecksum *sum = g_checksum_new(G_CHECKSUM_SHA256);
        if( sum == NULL ) {
            fprintf(stderr, "Could not create checksum.\n");
            exit(1);
        }
    
        // Open the file we'll be checksuming.
        FILE *fp = fopen( filename, "rb" );
        if( fp == NULL ) {
            fprintf(stderr, "Could not open %s: %s.\n", filename, strerror(errno));
            exit(1);
        }
    
        // Read one buffer full at a time (BUFSIZ is from stdio.h)
        // and update the checksum.    
        unsigned char buf[BUFSIZ];
        size_t size_read = 0;
        while( (size_read = fread(buf, 1, sizeof(buf), fp)) != 0 ) {
            // Update the checksum
            g_checksum_update(sum, buf, (gssize)size_read);
        }
    
        // Print the checksum.
        printf("%s %s\n", g_checksum_get_string(sum), filename);
    }
    
    $ ./test
    0c46af5bce717d706cc44e8c60dde57dbc13ad8106a8e056122a39175e2caef8 test.txt
    $ sha256sum test.txt 
    0c46af5bce717d706cc44e8c60dde57dbc13ad8106a8e056122a39175e2caef8  test.txt