这个问题非常不清楚。您如何确定具体
线?如果是第n行,最简单的解决方案就是调用
getlinen次,扔掉除最后一个结果以外的所有结果;呼唤
ignoren-1次可能会快一点,但我怀疑如果
您总是读入相同的字符串(而不是构造一个
每次都更新一次),时间上的差异不会很大。如果你
还有其他条件,文件确实很大(从您的
描述(不是)并进行排序,则可以尝试使用二进制搜索,
寻求文件的中间,请提前阅读以找到
下一行的开始,然后根据其决定下一步
值。 (我已使用它在日志文件中查找相关条目。但是
我们正在谈论的文件大小为几千兆字节。)
如果您愿意使用系统相关代码,则可能会有所帮助
内存映射文件,然后搜索\'\\ n \'的第n个出现位置
(std::findn次)。
添加:只是一些快速基准测试。在我的Linux机器上,获取
/usr/share/dict/words起的第100000个字(479623个字,每行一个,
在我的机器上),大约需要
272毫秒,读取所有单词
变成std::vector,然后索引,
256毫秒执行相同操作,但是
加上std::deque
30毫秒,使用getline,但是
只是忽略结果,直到
我感兴趣的一个
20毫秒使用
istream::ignore,以及
使用mmap和6毫秒
在std::find上循环播放。
FWIW,每种情况下的代码是:
对于std ::容器:
template
void Using::operator()()
{
std::ifstream input( m_filename.c_str() );
if ( !input )
Gabi::ProgramManagement::fatal() << \"Could not open \" << m_filename;
Container().swap( m_words );
std::copy( std::istream_iterator( input ),
std::istream_iterator(),
std::back_inserter( m_words ) );
if ( static_cast( m_words.size() ) < m_target )
Gabi::ProgramManagement::fatal()
<< \"Not enough words, had \" << m_words.size()
<< \", wanted at least \" << m_target;
m_result = m_words[ m_target ];
}
对于不保存的getline:
void UsingReadAndIgnore::operator()()
{
std::ifstream input( m_filename.c_str() );
if ( !input )
Gabi::ProgramManagement::fatal() << \"Could not open \" << m_filename;
std::string dummy;
for ( int count = m_target; count > 0; -- count )
std::getline( input, dummy );
std::getline( input, m_result );
}
对于ignore:
void UsingIgnore::operator()()
{
std::ifstream input( m_filename.c_str() );
if ( !input )
Gabi::ProgramManagement::fatal() << \"Could not open \" << m_filename;
for ( int count = m_target; count > 0; -- count )
input.ignore( INT_MAX, \'\\n\' );
std::getline( input, m_result );
}
而对于mmap:
void UsingMMap::operator()()
{
int input = ::open( m_filename.c_str(), O_RDONLY );
if ( input < 0 )
Gabi::ProgramManagement::fatal() << \"Could not open \" << m_filename;
struct ::stat infos;
if ( ::fstat( input, &infos ) != 0 )
Gabi::ProgramManagement::fatal() << \"Could not stat \" << m_filename;
char* base = (char*)::mmap( NULL, infos.st_size, PROT_READ, MAP_PRIVATE, input, 0 );
if ( base == MAP_FAILED )
Gabi::ProgramManagement::fatal() << \"Could not mmap \" << m_filename;
char const* end = base + infos.st_size;
char const* curr = base;
char const* next = std::find( curr, end, \'\\n\' );
for ( int count = m_target; count > 0 && curr != end; -- count ) {
curr = next + 1;
next = std::find( curr, end, \'\\n\' );
}
m_result = std::string( curr, next );
::munmap( base, infos.st_size );
}
在每种情况下,代码都将运行