将文件加载到矢量中;

发布于 2024-12-02 05:31:00 字数 439 浏览 0 评论 0原文

我想将文本文件的内容加载到 vector (或任何字符输入迭代器,如果可能的话)。目前我的代码如下所示:

std::vector<char> vec;
std::ifstream file("test.txt");
assert(file.is_open());
while (!(file.eof() || file.fail())) {
    char buffer[100];
    file.read(buffer, 100);
    vec.insert(vec.end(), buffer, buffer + file.gcount());
}

我不喜欢手动使用缓冲区(为什么是 100 个字符?为什么不是 200、25 或其他什么?),也不喜欢这需要大量的行。该代码看起来非常丑陋且非 C++。有更直接的方法吗?

I would like to load the contents of a text file into a vector<char> (or into any char input iterator, if that is possible). Currently my code looks like this:

std::vector<char> vec;
std::ifstream file("test.txt");
assert(file.is_open());
while (!(file.eof() || file.fail())) {
    char buffer[100];
    file.read(buffer, 100);
    vec.insert(vec.end(), buffer, buffer + file.gcount());
}

I do not like the manual use of a buffer (Why 100 chars? Why not 200, or 25 or whatever?), or the large number of lines that this took. The code just seems very ugly and non-C++. Is there a more direct way of doing this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

神仙妹妹 2024-12-09 05:31:00

如果你想避免逐个字符地读取:

if (!file.eof() && !file.fail())
{
    file.seekg(0, std::ios_base::end);
    std::streampos fileSize = file.tellg();
    vec.resize(fileSize);

    file.seekg(0, std::ios_base::beg);
    file.read(&vec[0], fileSize);
}

If you want to avoid reading char by char:

if (!file.eof() && !file.fail())
{
    file.seekg(0, std::ios_base::end);
    std::streampos fileSize = file.tellg();
    vec.resize(fileSize);

    file.seekg(0, std::ios_base::beg);
    file.read(&vec[0], fileSize);
}
南七夏 2024-12-09 05:31:00

另一种方法是首先使用 rdbuf() 来将整个文件读取到 std::stringstream :

#include <fstream>
#include <sstream>
#include <vector>
#include <string>

// for check:
#include <algorithm>
#include <iterator>
#include <iostream>

int main() {
   std::ifstream file("test.cc");
   std::ostringstream ss;
   ss << file.rdbuf();
   const std::string& s = ss.str();
   std::vector<char> vec(s.begin(), s.end());

   // check:
   std::copy(vec.begin(), vec.end(), std::ostream_iterator<char>(std::cout));
}

Another approach, using rdbuf() to read the whole file to a std::stringstream first:

#include <fstream>
#include <sstream>
#include <vector>
#include <string>

// for check:
#include <algorithm>
#include <iterator>
#include <iostream>

int main() {
   std::ifstream file("test.cc");
   std::ostringstream ss;
   ss << file.rdbuf();
   const std::string& s = ss.str();
   std::vector<char> vec(s.begin(), s.end());

   // check:
   std::copy(vec.begin(), vec.end(), std::ostream_iterator<char>(std::cout));
}
美人如玉 2024-12-09 05:31:00

我认为是这样的,但没有环境来测试它:

std::copy(std::istream_iterator<char>(file), std::istream_iterator<char>(), std::back_inserter(vec));

可能你必须使用 io 操纵器来处理诸如换行符/空格之类的事情。

编辑:正如评论中所述,可能会对性能造成影响。

I think it's something like this, but have no environment to test it:

std::copy(std::istream_iterator<char>(file), std::istream_iterator<char>(), std::back_inserter(vec));

Could be you have to play with io manipulators for things like linebreaks/whitespace.

Edit: as noted in comments, could be a performance hit.

最终幸福 2024-12-09 05:31:00

有很多好的回应。谢谢大家!我决定使用的代码是这样的:

std::vector<char> vec;
std::ifstream file;
file.exceptions(
    std::ifstream::badbit
  | std::ifstream::failbit
  | std::ifstream::eofbit);
//Need to use binary mode; otherwise CRLF line endings count as 2 for
//`length` calculation but only 1 for `file.read` (on some platforms),
//and we get undefined  behaviour when trying to read `length` characters.
file.open("test.txt", std::ifstream::in | std::ifstream::binary);
file.seekg(0, std::ios::end);
std::streampos length(file.tellg());
if (length) {
    file.seekg(0, std::ios::beg);
    vec.resize(static_cast<std::size_t>(length));
    file.read(&vec.front(), static_cast<std::size_t>(length));
}

显然,这不适合非常大的文件或性能关键的代码,但对于一般用途来说已经足够了。

There were lots of good responses. Thanks all! The code that I have decided on using is this:

std::vector<char> vec;
std::ifstream file;
file.exceptions(
    std::ifstream::badbit
  | std::ifstream::failbit
  | std::ifstream::eofbit);
//Need to use binary mode; otherwise CRLF line endings count as 2 for
//`length` calculation but only 1 for `file.read` (on some platforms),
//and we get undefined  behaviour when trying to read `length` characters.
file.open("test.txt", std::ifstream::in | std::ifstream::binary);
file.seekg(0, std::ios::end);
std::streampos length(file.tellg());
if (length) {
    file.seekg(0, std::ios::beg);
    vec.resize(static_cast<std::size_t>(length));
    file.read(&vec.front(), static_cast<std::size_t>(length));
}

Obviously, this is not suitable for extremely large files or performance-critical code, but it is good enough for general purpose use.

待"谢繁草 2024-12-09 05:31:00

使用迭代器:

#include <iterator>

istream_iterator<char> data( file );
istream_iterator<char> end;
vec.insert( std::back_inserter(vec), data, end );

use an iterator:

#include <iterator>

istream_iterator<char> data( file );
istream_iterator<char> end;
vec.insert( std::back_inserter(vec), data, end );
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文