关于使用C++istream_iterator从文件中读取部分数据的内容
Something about reading portions of data from file using a C++ istream_iterator
目标:有一个文本文件(在HDD上),其中包含用某种分隔符划分的整数。
示例:
5245
234224
6534
1234
我需要将它们读取到STL容器中。
int main(int argc, char * argv[]) {
using namespace std;
// 1. prepare the file stream
string fileName;
if (argc > 1)
fileName = argv[1];
else {
cout << "Provide the filename to read from: ";
cin >> fileName;
}
unique_ptr<ifstream, ifstream_deleter<ifstream>> ptrToStream(new ifstream(fileName, ios::out));
if (!ptrToStream->good()) {
cerr << "Error opening file " << fileName << endl;
return -1;
}
// 2. value by value reading will be too slow on large data so buffer data
typedef unsigned int values_type;
const int BUFFER_SIZE(4); // 4 is for testing purposes. 16MB or larger in real life
vector<values_type> numbersBuffer(BUFFER_SIZE);
numbersBuffer.insert(numbersBuffer.begin(), istream_iterator<values_type>(*ptrToStream), istream_iterator<values_type>());
// ...
此代码的主要缺点是当文件大小非常大,因此无法将其所有内容存储在内存中时,我如何处理该问题?我也不想使用push_back
,因为它与区间insert
相比是无效的。
因此,问题是:如何使用STL有效地从文件中读取不超过BUFFER_SIZE
的元素?
限制从输入迭代器读取的方法是创建一个包装器,该包装器统计到目前为止处理的元素数量,并且其结束迭代器与该数量进行比较。一般来说,这样做并不简单,专门为std::istream_iterator<T>
做应该不会太难。也就是说,我认为最简单的方法是:
std::vector<T> buffer;
buffer.reserve(size);
std::istreambuf_iterator<T> it(in), end;
for (std::vector<T>::size_type count(0), capacity(size);
it != end && count != capacity; ++it, ++count) {
buffer.push_back(*it);
}
我意识到你不想push_back()
,因为据称它很慢。但是,与I/O操作相比,我怀疑您是否能够衡量较小的开销,尤其是对于I/O库的典型实现。
下面是一个包装迭代器的例子:下面是std::istream_iterator<T>
的计数包装器的样子。有很多不同的方法可以做到这一点,这只是其中之一。
#include <iostream>
#include <iterator>
#include <vector>
#include <sstream>
template <typename T>
class counted_istream_iterator:
public std::iterator<std::input_iterator_tag, T, std::ptrdiff_t>
{
public:
explicit counted_istream_iterator(std::istream& in): count_(), it_(in) {}
explicit counted_istream_iterator(size_t count): count_(count), it_() {}
T const& operator*() { return *this->it_; }
T const* operator->() { return it_->it_.operator->(); }
counted_istream_iterator& operator++() {
++this->count_; ++this->it_; return *this;
}
counted_istream_iterator operator++(int) {
counted_istream_iterator rc(*this); ++*this; return rc;
}
bool operator== (counted_istream_iterator const& other) const {
return this->count_ == other.count_ || this->it_ == other.it_;
}
bool operator!= (counted_istream_iterator const& other) const {
return !(*this == other);
}
private:
std::ptrdiff_t count_;
std::istream_iterator<T> it_;
};
void read(int count)
{
std::istringstream in("0 1 2 3 4 5 6 7 8 9");
std::vector<int> vec;
vec.insert(vec.end(), counted_istream_iterator<int>(in),
counted_istream_iterator<int>(count));
std::cout << "size=" << vec.size() << "n";
}
int main()
{
read(4);
read(100);
}
有可能的方法来解决我的问题:
// 2. value by value reading will be too slow on large data so buffer data
typedef unsigned int values_type;
const int BUFFER_SIZE(4);
vector<values_type> numbersBuffer;
numbersBuffer.reserve(BUFFER_SIZE);
istream_iterator<values_type> begin(*ptrToStream), end;
while (begin != end) {
copy_n(begin, BUFFER_SIZE, numbersBuffer.begin());
for_each(numbersBuffer.begin(), numbersBuffer.end(), [](values_type const &val){ std::cout << val << std::endl; });
++begin;
}
但它有一个缺点。如果输入文件包含以下内容:
8785
245245454545
7767
则8785将被读取,但是245245454545和7767将不被读取,因为2452454545465不能被转换为unsigned int
。错误将是静默的。:(
相关文章:
- 如何从dicom文件中读取二进制数据
- 使用对象文件读取三角形数据网格
- readsome() 适合在 Windows 上读取二进制数据吗?
- 如何在Visual C+++中从JSON文件中读取节点数据
- 如何使用指针直接从托管代码中的非托管代码中读取矢量数据
- 从文件中读取的数据,但发生核心转储错误
- JPG-如何从ICC配置文件部分APP2读取/提取数据
- 将多个效果与 libSox 链接并读取输出数据的正确方法
- 从文本文件中读取并输入到数组结构中,然后显示读取的数据C++
- 从USBPcap库读取原始数据
- 从文件中的一行读取特定数据-C++
- Cocos2D-X:从内存中读取 MP3 数据
- 组织从内存读取的数据的最佳方法(用于调试)c++
- Poco c++ 如何从PostgreSQL DB读取"text"数据类型?
- 从Qt应用程序读取元数据
- 需要根据读取的数据类型将ifstream提取到单独的数组中
- 如何在C 中读取一系列数据文件
- C :如何从格式的文本文件中读取许多数据到程序中
- CPP 在读取结构数据时无限循环错误?
- 从 dll 读取矢量数据C++?