W
Hallo Julian,
Versuche mal unten stehenden Code. Damit schaffe ich 80Millionen 4-stellige Integer-Werte (Datei = 40MB groß) in 0,6 Sekunden in einen std::vector zu schaufeln. Das Lesen selbst liegt bei ca. 0,5s und der std:vector kostet 0,1s.
Du könntest alternativ eine std::deque<> verwenden.
Julian90 schrieb:
... die Daten muss ich ja erstmal in eine Datenstruktur schieben
Nö - nicht 'erstmal' sondern gleich in das Ziel. Daher blebt die Frage nach der entgüligen Verwendung der Daten. Das ist auch entscheidend für die Art&Weise des Einlesens.
#include <fstream>
#include <iostream>
#include <chrono>
#include <locale> // std::num_get<>
#include <vector>
class NumGet : public std::num_get< char >
{
public:
using iter_type = std::istreambuf_iterator< char, std::char_traits< char > >;
NumGet()
: std::num_get< char >()
{}
protected:
iter_type do_get( iter_type in, iter_type end, std::ios_base&,
std::ios_base::iostate& err, long& v) const override
{
// Achtung: liest nur positive Werte
long l = 0;
for( ; in != end; ++in )
{
if( '0' <= *in && *in <= '9' )
(l *= 10) += int(*in - '0'); // Achtung: KEIN Check auf overflow
else
{
v = l;
return in;
}
}
err |= std::ios_base::failbit;
return in;
}
};
class Alles
{
public:
using target_type = std::vector< int >;
Alles( target_type& target )
: target_( target )
{}
friend std::istream& operator>>( std::istream& in, const Alles& all )
{
std::istream::sentry ok( in );
using Traits = std::istream::traits_type;
if( ok )
{
std::ios_base::iostate state = std::ios_base::goodbit;
const NumGet num_get;
try
{
const std::ctype< char >& ctype_ = std::use_facet< std::ctype< char > >( in.getloc() );
std::istreambuf_iterator< char > last;
for(;;)
{
// -- skip leading whitespace
Traits::int_type m = in.rdbuf()->sgetc();
for( ;; m = in.rdbuf()->snextc() )
{
if( Traits::eq_int_type( m, Traits::eof() ) )
{
state |= std::ios_base::eofbit;
break;
}
else if( !ctype_.is( std::ctype_base::space, Traits::to_char_type(m) ) )
break; // kein whitespace
}
if( state == std::ios_base::eofbit )
break; // Lesen am Dateiende ohne Fehler beenden
// -- Integer einlesen
long wert = 0;
num_get.get( std::istreambuf_iterator< char >( in.rdbuf() ), last, in, state, wert );
if( state != std::ios_base::goodbit )
break;
all.target_.push_back( wert ); // <====== was soll mit den Werten geschehen?
}
}
catch(...)
{
state |= std::ios_base::badbit;
if( in.exceptions() & std::ios_base::badbit )
throw;
}
in.setstate( state );
}
return in;
}
private:
target_type& target_;
};
int main()
{
using namespace std;
ifstream in("big.txt");
auto start = chrono::steady_clock::now();
std::vector< int > daten;
if( !(in >> Alles(daten)) )
cerr << "Fehler beim Lesen" << endl;
auto ende = chrono::steady_clock::now();
cout << "Dauer: " << chrono::duration_cast< chrono::milliseconds >(ende-start).count() << "ms" << endl;
cout << "Anzahl= " << daten.size() <<endl;
return 0;
}
Gruß
Werner