读取文件的最后一行
Reading last line of a file
我有一个大文件,我只需要从中得到最后一行(n
只是行分隔符)。
我需要在iOS设备上完成此操作,因此它不会占用太多内存或cpu时间(如读取整个文件)。
我如何在Objective-C,c++或c++11中做到这一点?
从概念上讲,我认为您想要打开文件并寻找整个方式到结束减去N字节(可能是80或其他)。然后读取并寻找n。如果没有找到,那么先查找N个字节,然后在这N个字节的集合上进行尝试,以此类推,直到找到 N .
对于特定的调用,这只是查找如何打开文件,在其中查找并读取数据的问题。应该很简单。但我认为以上就是你想要做的,为N选择一个不太大的大小。
我的生产代码中有这个特性。这个想法是通过寻找和阅读来读最后一行。请看一看。
bool readLastLine(std::string const& filename, std::string& lastLine)
{
std::ifstream in(filename.c_str(),std::ifstream::binary);
if(!in) return false;
in.seekg(0, std::ifstream::end);
const std::streamoff len = in.tellg();
//empty file
if(len == 0)
{
lastLine = "";
return true;
}
int buf_size = 128;
std::vector<char> buf;
while(in)
{
if(buf_size > len)
{
buf_size = len;
}
buf.resize(buf_size);
in.seekg(0 - buf_size, std::ifstream::end);
in.read(&buf[0],buf_size);
//all content is in the buffer or we already have the complete last line
if(len == buf_size || std::count(buf.begin(), buf.end(), 'n') > 1)
{
break;
}
//try enlarge the buffer
buf_size *= 2;
}
//find the second line seperator from the end if any
auto i = std::find(++buf.rbegin(),buf.rend(), 'n');
lastLine.assign(i == buf.rend() ? buf.begin() : buf.begin() + std::distance(i, buf.rend()), buf.begin() + buf_size);
return true;
}
@Nerdtron的回答似乎对我来说是最合适的,如果你不能控制你的文件格式,但是…
如果你可以控制文件格式,你可以用0(1)复杂度来完成。当您向文件写入数据时,只需将最后一行开始的偏移量写入文件开头的(常量)偏移量。当您想要读取它时,读取此偏移量,并转到其中指定的偏移量
我想到了这个,试图改进Bruce,好处是缓冲区不需要调整大小,只是保持读取相同大小的字符块,远离EOF:
std::string lastLine(std::ifstream &file)
{
if (!file.good()) throw exception("Bad stream on input");
const size_t bufSize = 80; // because why not? tweak if need to
char buf[bufSize];
string line;
int seek, nloff;
// iterate over multiples of bufSize while file ok
for (size_t n = 1; file; ++n)
{
// next seek position will be a multiple of bufSize
seek = -static_cast<int>(n * bufSize);
file.seekg(seek, file.end);
// read "bufSize" bytes into buffer
file.read(buf, bufSize);
// in case no newline found, seek past eof
nloff = -seek;
// find offset of last newline in buffer
for (size_t i = 0; i < bufSize; ++i)
{
if (buf[i] == 'n') nloff = i;
}
seek += nloff + 1; // new seek position is one character after found newline
if (seek >= 0) continue; // just kidding about the "past eof" part ;)
// seek to after found newline and get line
file.seekg(seek, file.end);
getline(file, line);
if (!line.empty()) break; // have result, break and return
}
if (file.good()) return line;
else return string();
}
相关文章:
- 用c++从输入文件中读取另一行
- 读取文件的最后一行并输入到链接列表时出错
- 我正在使用嵌套的while循环来解析具有多行的文本文件,但由于某种原因,它只通过第一行,我不知道为什么
- 如何使代码打印文本文件中的第一行?
- 如何格式化我的文本文件以使其不会一遍又一遍地重复同一行?
- 逐字读取文本文件中的每一行并转换为 int(无限循环或崩溃?
- 将字符串存储到文件下一行的变量中
- 为什么这个.c文件只有一行"../xx/xx.c"?
- 比较两个没有一行共同点的大文件
- 如何在c ++中以一行(水平)打印两个文件的数据?如给定的.这两种形式来自两个不同的文本文件
- 到达分隔符时跳到文本文件的下一行
- 从文本文件中读取一行并将其存储在 C++ 中的 2D 矢量中
- 从文本文件中随机选取一行
- 在获取从文件到矢量的每一行之后,数字将被更改或销毁
- 从文件中的一行读取特定数据-C++
- 从文本文件中的每一行读取数字,并计算数字重复的次数
- 为什么这一行不输出我的文本文件?
- 从文件读取并在一行中写入 cout
- 如何有效地读取C 中的最后一行文件
- 将一行文件读入对象中的两个变量