C ++将文件的所有字节放入char数组中?

Posted

技术标签:

【中文标题】C ++将文件的所有字节放入char数组中?【英文标题】:C++ Get all bytes of a file in to a char array? 【发布时间】:2016-04-16 00:14:57 【问题描述】:

给定:

const string inputFile = "C:\MyFile.csv";
char buffer[10000];

如何将文件的字符读入上述缓冲区?我一直在网上四处寻找,但似乎没有一个答案有效。他们都希望调用 getline()。

【问题讨论】:

【参考方案1】:

注意:以Remy Lebeau's answer 开头。对于一般的文件读取,这是完成这项工作的艰难方法;它更符合此特定提问者的特定需求,但不一定能满足您的需求以及 std::vectorstd::istreambuf_iterator 方法。


大多数时候他们对getline 的看法是正确的,但是当您想要获取文件时as a stream of bytes, you want ifstream::read()

//open file
std::ifstream infile("C:\\MyFile.csv");

//get length of file
infile.seekg(0, std::ios::end);
size_t length = infile.tellg();
infile.seekg(0, std::ios::beg);

// don't overflow the buffer!
if (length > sizeof (buffer))

    length = sizeof (buffer);


//read file
infile.read(buffer, length);

Docs for ifstream::seekg()

Docs for ifstream::tellg()

注意:seekg()tellg() 获取文件大小属于“通常有效”的类别。这不能保证。 tellg() 只承诺一个可用于返回特定点的数字。那就是……

注意:该文件不是以二进制模式打开的。可能有一些幕后字符翻译,例如 \r\n 的 Windows 换行符被转换为 C++ 使用的 \nlength 可以大于最终放入 buffer 的字符数。

2019 年重新思考

size_t chars_read;
//read file
if (!(infile.read(buffer, sizeof(buffer)))) // read up to the size of the buffer

    if (!infile.eof()) // end of file is an expected condition here and not worth 
                       // clearing. What else are you going to read?
    
        // something went wrong while reading. Find out what and handle.
    

chars_read = infile.gcount(); // get amount of characters really read.

如果您在使用整个文件之前循环缓冲读取,则需要一些额外的智能来捕捉它。

如果您想一次性读取整个文件,并且有能力使用可调整大小的缓冲区,请采纳Remy Lebeau's answer 中的建议。

【讨论】:

根据doc,我认为你应该使用ifstream::endifstream::beg而不是ifs::endifs::beg @tjysdsg 在这里无关紧要,但值得遵循的建议。使用静态成员获得的优势,尤其是一直回到 ios 的好处是,您可以更改流的标识符和类型,而不必进行太多重构。零成本的通用代码几乎总是比特定代码更好。我还需要清理一些其他问题。【参考方案2】:

另一种选择是使用std::vector 作为缓冲区,然后使用std::istreambuf_iteratorstd::ifstream 直接读取std::vector,例如:

const std::string inputFile = "C:\\MyFile.csv";
std::ifstream infile(inputFile, std::ios_base::binary);

std::vector<char> buffer( std::istreambuf_iterator<char>(infile),
                          std::istreambuf_iterator<char>() );

或者:

const std::string inputFile = "C:\\MyFile.csv";
std::ifstream inFile(inputFile, std::ios_base::binary);

inFile.seekg(0, std::ios_base::end);
size_t length = inFile.tellg();
inFile.seekg(0, std::ios_base::beg);

std::vector<char> buffer;
buffer.reserve(length);
std::copy( std::istreambuf_iterator<char>(inFile),
           std::istreambuf_iterator<char>(),
           std::back_inserter(buffer) );

如果您使用@user4581301 的解决方案,我仍然建议使用std::vector 作为缓冲区,至少:

//open file
std::ifstream infile("C:\\MyFile.csv");
std::vector<char> buffer;

//get length of file
infile.seekg(0, infile.end);
size_t length = infile.tellg();
infile.seekg(0, infile.beg);

//read file
if (length > 0) 
    buffer.resize(length);    
    infile.read(&buffer[0], length);

【讨论】:

【参考方案3】:

如果您关心效率(您拒绝了 getline()),那么 C 风格的 mmap 可能是最好的:

#include <sys/stat.h>
#include <sys/mman.h>

struct stat s;
stat(inputFile.c_str(), &s);
size_t file_size = st.st_size;

int fhand = open(inputFile);
char* file_buf = (char*)mmap(0, file_size, PROT_READ, MAP_FILE|MAP_PRIVATE, fhand, 0);
...
munmap(file_buf, file_size);

【讨论】:

或者,在没有mmap()的Windows上,您可以使用CreateFile()CreateFileMapping()MapViewOfFile()来完成同样的事情。

以上是关于C ++将文件的所有字节放入char数组中?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在 C 中将 char[] 转换为 char*?

字符串数组中的文件名 c# Universal Windows

将字符串存储在 mmap 共享数组中? (C)

java读取文件中多个数据,放入不同数组

Linux下C编程读取文件中每行的数据

将 FILE 中的二进制字节值存储到 C 数组中