【问题标题】:Read till end of a boost memory mapped file in VC++在 VC++ 中读取到 boost 内存映射文件的末尾
【发布时间】:2014-10-08 08:56:51
【问题描述】:

我正在使用 VS2010 用 C++ 编写一个程序来读取文本文件并从中提取某些信息。我使用文件流完成了代码,它运行良好。但是现在我被要求将文件映射到内存并使用它而不是文件操作。

在内存映射的情况下,我绝对是新手。我写的部分代码如下。

boost::iostreams::mapped_file_source apifile;

apifile.open(LogFileName,LogFileSize);

if(!apifile.is_open()) 

return FILE_OPEN_ERROR;

// Get pointer to the data.

PBYTE Buffer = (PBYTE)apifile.data();

while(//read till end of the file)
{
     // read a line and check if it contains a specific word
}

在使用文件流时,我会使用 eofgetlinestring::find 来执行操作。但我不知道如何使用内存映射文件来做到这一点。

编辑 1:

int ProcessLogFile(string file_name)
{
    LogFileName = file_name;

    apifile.open(LogFileName);//boost::iostreams::mapped_file_source apifile(declared globally)

    streamReader.open(apifile, std::ios::binary);//boost::iostreams::stream <boost::iostreams::mapped_file_source> streamReader(declared globally)

    streamoff Curr_Offset = 0;

    string read_line;

    int session_id = 0;

    int device_id = 0;

    while(!streamReader.eof())
    {
        \\COLLECT OFFSETS OF DIFFERENT SESSIONS
    }

    streamReader.close();
}

这个函数有效,我得到了所需结构的偏移量。

现在调用这个函数后,我又调用了另一个函数,如下:

int GetSystemDetails()
{   
    streamReader.open(apifile, std::ios::binary);

    string read_line;

    getline(streamReader,read_line);

    cout << "LINE : " << read_line;

    streamReader.close();
}

我在 read_line 中没有得到任何数据。该内存映射仅适用于单个功能吗?如何在不同的函数中使用相同的内存映射文件?

【问题讨论】:

  • 文件很大吗?您需要文件映射吗?
  • @MarcoA。 : 是的,我需要文件映射。该文件具有动态性质,大小主要为 MB。
  • mapped_file_sourcedata()size() 方法,你当然可以将data() 返回的指针增加到size() 倍?
  • @sjdowling:你介意举个小例子吗?

标签: c++ visual-studio-2010 memory boost


【解决方案1】:

如果您只是按顺序阅读文件,我同意有人质疑 mmap 的使用。

boost::mapped_file_source 为设备建模。使用这种设备有两种方法:

  1. 直接使用(尝试使用data()
  2. 使用流包装器

1。使用原始设备源

您可以使用 mapped_file_source 报告实际大小 (m.data()+m.size())。

让我们抽样来计算行数:

#include <boost/iostreams/device/mapped_file.hpp> // for mmap
#include <algorithm>  // for std::find
#include <iostream>   // for std::cout
#include <cstring>

int main()
{
    boost::iostreams::mapped_file mmap("input.txt", boost::iostreams::mapped_file::readonly);
    auto f = mmap.const_data();
    auto l = f + mmap.size();

    uintmax_t m_numLines = 0;
    while (f && f!=l)
        if ((f = static_cast<const char*>(memchr(f, '\n', l-f))))
            m_numLines++, f++;

    std::cout << "m_numLines = " << m_numLines << "\n";
}

你可能会适应这个。我有几个基于内存映射文件的更复杂的解析示例:


2。将源设备包装在 istream

这为您提供了 c++ 标准流的所有常用的基于流的操作,因此您可以像往常一样检测文件的结尾:

#include <boost/iostreams/device/mapped_file.hpp> // for mmap
#include <boost/iostreams/stream.hpp>             // for stream
#include <algorithm>                              // for std::find
#include <iostream>                               // for std::cout
#include <cstring>

int main()
{
    using boost::iostreams::mapped_file_source;
    using boost::iostreams::stream;
    mapped_file_source mmap("test.cpp");
    stream<mapped_file_source> is(mmap, std::ios::binary);

    std::string line;

    uintmax_t m_numLines = 0;
    while (std::getline(is, line))
    {
        m_numLines++;
    }

    std::cout << "m_numLines = " << m_numLines << "\n";
}

【讨论】:

  • 我使用了第二种方法,它帮助了我。感谢您以如此简单但内容丰富的方式回答。
  • 我在一个函数中执行了这个内存映射,并使用is.tellg 方法将某些偏移量存储到一个结构中。稍后我必须在另一个函数中使用这个偏移量。那会是一致的吗?
  • 看来您确实想要原始设备访问权限。设备是随机访问的。流(主要)是顺序 IO。我只会将流用于文本处理(这就是您在问题中显示的内容)。您是否看过实际存储数据结构directly into memory mapped files with Boost Interprocess?该页面下方有一个示例。
  • @sehe 你忘了在你的例子中调用 mmap.close()。
  • @FranciscoAguilera 它在最后一行。 RAII 万岁
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-06
  • 2016-01-08
相关资源
最近更新 更多