如何在C++中只将常量间隔的项目从char缓冲区写入磁盘

Ros*_*oss 4 c++ file-io

如何在char缓冲区中只编写每三个项目以便在C++中快速编写文件?

我从相机中获得了三通道图像,但每个通道包含相同的信息(图像为灰度).我想只写一个通道到磁盘以节省空间并使写入更快,因为这是实时数据采集系统的一部分.

C++的ofstream :: write命令似乎只编写连续的二进制数据块,因此我的当前代码会写入所有三个通道并且运行速度太慢:

char * data = getDataFromCamera();
int dataSize = imageWidth * imageHeight * imageChannels;
std::ofstream output;
output.open( fileName, std::ios::out | std::ios::binary );
output.write( data, dataSize );
Run Code Online (Sandbox Code Playgroud)

我希望能够通过以下呼叫替换最后一行:

int skipSize = imageChannels;
output.write( data, dataSize, skipSize );
Run Code Online (Sandbox Code Playgroud)

其中skipSize会导致write只将每三分之一放入输出文件中.但是,我还没有找到任何能够做到这一点的功能.

我很想听听有关将单个频道快速写入磁盘的任何想法.谢谢.

Jer*_*fin 6

您可能必须将每个第三个元素复制到缓冲区中,然后将该缓冲区写入磁盘.

  • +1缓冲数据应该比一次写出一个字节有一个明显的加速.您甚至可以对`std :: ofstream`进行子类化,并添加一个`write_pattern(char*ptr,int dataSize,int write_bytes,int skip_bytes)成员函数,它将为您完成所有操作. (3认同)

Mar*_*ork 5

您可以在本地使用codecvt facet来过滤掉部分输出.
一旦创建,您可以使用适当的本地来填充任何流,它只会看到输入中的每个第三个字符.

#include <locale>
#include <fstream>
#include <iostream>

class Filter: public std::codecvt<char,char,mbstate_t>
{
    public:
   typedef std::codecvt<char,char,mbstate_t> MyType;
   typedef MyType::state_type          state_type;
   typedef MyType::result              result;

    // This indicates that we are converting the input.
    // Thus forcing a call to do_out()
    virtual bool do_always_noconv() const throw()   {return false;}

    // Reads   from -> from_end
    // Writes  to   -> to_end
    virtual result do_out(state_type &state,
             const char *from, const char *from_end, const char* &from_next,
             char       *to,   char       *to_limit, char*       &to_next) const
   {
       // Notice the increment of from
       for(;(from < from_end) && (to < to_limit);from += 3,to += 1)
       {
            (*to) = (*from);
       }
       from_next   = from;
       to_next     = to;

       return((to > to_limit)?partial:ok);
   }
};
Run Code Online (Sandbox Code Playgroud)

一旦获得了方面,您只需知道如何使用它:

int main(int argc,char* argv[])
{
   // construct a custom filter locale and add it to a local.
   const std::locale filterLocale(std::cout.getloc(), new Filter());

   // Create a stream and imbue it with the locale
   std::ofstream   saveFile;
   saveFile.imbue(filterLocale);


   // Now the stream is imbued we can open it.
   // NB If you open the file stream first. 
   // Any attempt to imbue it with a local will silently fail.
   saveFile.open("Test");
   saveFile << "123123123123123123123123123123123123123123123123123123";

   std::vector<char>   data[1000];
   saveFile.write( &data[0], data.length() /* The filter implements the skipSize */ );
                                           // With a tinay amount of extra work
                                           // You can make filter take a filter size
                                           // parameter.

   return(0);
}
Run Code Online (Sandbox Code Playgroud)