簡體   English   中英

讀取文件的最后一行

[英]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答案似乎對我來說最合適,如果你無法控制你的文件格式,但......

如果您可以控制文件格式,則可以使用O(1)復雜度來執行此操作。 當您向其寫入數據時,只需將最后一行開頭的偏移量寫入文件開頭的(常量)偏移量。 如果要讀取它,請讀取此偏移量,然后轉到其中的指定偏移量。

我想出了這個,試圖改進布魯斯,好處是緩沖區不需要調整大小,只是繼續讀取距離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();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM