1

I have to write C++ program that like gzip can

*Take input from file or from char stream like compression below

gzip file
type file | gzip

*Program have file or char stream output like decompression below

gzip -d file.gz
gzip -dc file.gz

I don't know how to take to the task and what techniques have to use and how to create classes buffering input and output. I have classes buffering input and output and read/write data from/to file.

DataBuffer.h (taking uncompressed data from file):

#ifndef DataBuffer_h
#define DataBuffer_h

#include <fstream>
#include <string>

enum DataBufferState
{
  DATABUFFER_OK = 0,
  DATABUFFER_EOF = 1
};

class DataBuffer
{
    std::fstream file;
    std::string buffer;
  unsigned int maxBufferSize;
 public:
    DataBuffer(const std::string& filename, unsigned int maxBuffSize);
    ~DataBuffer();
    bool OpenFile(const std::string& filename);
    void SetMaxBufferSize(unsigned int maxBuffSize);
  DataBufferState FullBufferWithDataOld();
    DataBufferState FullBufferWithData();
    std::string GetDataBuffer();
};

#endif

DataBuffer.cpp:

#include "DataBuffer.h"

using namespace std;

DataBuffer::DataBuffer(const string& filename, unsigned int maxBuffSize)
{
    OpenFile(filename);
    SetMaxBufferSize(maxBuffSize);
}

DataBuffer::~DataBuffer()
{
  file.close();
}

bool DataBuffer::OpenFile(const string& filename)
{
    file.open(filename.c_str(),ios::in);
    if(!file.is_open())
    return false;
    return true;
}

void DataBuffer::SetMaxBufferSize(unsigned int maxBuffSize)
{
  maxBufferSize = maxBuffSize;
}

DataBufferState DataBuffer::FullBufferWithDataOld()
{
    while(true)
    {
        string line;
        streampos pos = file.tellg(); // Zapamietaj polozenie przed pobraniem linii
        getline(file,line);
        if( buffer.size()+line.size()>maxBufferSize )
        {
            // Cofnac wskaznik pliku
            file.seekg(pos,ios::beg); // Przywroc polozenie sprzed pobrania linii
            break;
        }
        buffer += line + "\n";
        if(file.eof())
      return DATABUFFER_EOF;
    }
    return DATABUFFER_OK;
}

DataBufferState DataBuffer::FullBufferWithData()
{
    char c;
  for(unsigned int i=0;i<maxBufferSize;++i)
    {
    c = file.get();
        if(file.eof()) break;
    buffer += c;
    }

    if(file.eof())
        return DATABUFFER_EOF;

    return DATABUFFER_OK;
}

string DataBuffer::GetDataBuffer()
{
    string buf = buffer;
    buffer.clear();
  return buf;
}

BufferWriter.h (Save uncompressed data into file):

#ifndef BufferWriter_h
#define BufferWriter_h

#include <string>
#include <fstream>

class BufferWriter
{
    std::string filename;
    std::fstream file;
 public:
     BufferWriter(const std::string& filename_);
    ~BufferWriter();
    bool OpenFile(const std::string& filename, bool appending);
    void SendBufferToFile(std::string& buffer);
};


#endif

BufferWriter.cpp

#include "BufferWriter.h"

using namespace std;

BufferWriter::BufferWriter(const string& filename_)
{
  filename = filename_;
    OpenFile(filename.c_str(),false);
    file.close();
}

BufferWriter::~BufferWriter()
{
  file.close();
}

bool BufferWriter::OpenFile(const string& filename, bool appending)
{
    if(appending)
        file.open(filename.c_str(),ios::out | ios::app);
    else
    file.open(filename.c_str(),ios::out);
    if(!file.is_open())
        return false;
    return true;
}

void BufferWriter::SendBufferToFile(string& buffer)
{
  OpenFile(filename,true);
    file.write(buffer.c_str(),buffer.size());
    file.close();
}

Can you give me some hints how to improve code for input and output mechanisms?

Assume that I have class presented below, how to use istream or iterators to fill buffer with data from file or standard input. What classes from std or boost? What parameters? Somelike to support definition of class with this functionality.

[EDIT]:

#ifndef StreamBuffer_h
#define StreamBuffer_h

#include <string>

using namespace std;

enum DataBufferState
{
  DATABUFFER_OK = 0,
  DATABUFFER_EOF = 1
};

// gzip plik
// type plik | gzip -d
// gzip -d plik.gz
// gzip -dc plik.gz 

// Parametr konstruktora to strumien z ktorego chcemy czytac i dlugosc bufora
class StreamBuffer
{
    int maxBufferSize;
    std::string buffer;
    StreamBuffer(int maxBuffSize)
    {
    SetMaxBufferSize(maxBuffSize);
    }
    ~StreamBuffer()
    {
    }
    void SetMaxBufferSize(unsigned int maxBuffSize)
    {
    maxBufferSize = maxBuffSize;
    }
    DataBufferState FullBufferWithData()
    {
      // What to use what to do in this method to read part of file or standard char input to buffer?
    }
    std::string GetDataBuffer()
    {
    return buffer;
    }
};

#endif

[EDIT2]:

I want to do the same thing as in this thread: Read from file or stdin, but in C++.

3
  • Is there a specific problem with your code ? Commented Apr 1, 2014 at 9:30
  • My problem is to write universal code that take char stream or file as input and output , don't know how to project classes and what c++ techniques I have to take. Can I do it in another way than istream/ostream iterators and how to create abstract classes doing. this task. Presented code works ok so far. Commented Apr 1, 2014 at 9:44
  • Why no rely on the buffering provided with the standard streams? Commented Apr 1, 2014 at 10:04

1 Answer 1

1

In general you read input from a source and write it to a sink. The simplest case is when you simply write what you read. You, however, want to apply a transformation (or filter) to the data that you read. Seeing as you're after "the c++ way," I'd suggest taking a look at boost::iostreams which abstracts the task in terms of sources/sinks.

Boost defines an abstract source by:

struct Source {
    typedef char        char_type;
    typedef source_tag  category;
    std::streamsize read(char* s, std::streamsize n) 
    {
        // Read up to n characters from the input 
        // sequence into the buffer s, returning   
        // the number of characters read, or -1 
        // to indicate end-of-sequence.
    }
};

And sinks are defined in a similar way (with a write instead of a read, of course). The benefit of this is that the details of the source/sink is irrelevant - you can read/write to file, to a network adapter, or whatever, without any structural changes.

To apply filters I'd again suggest looking at boost::iostreams, although they do abstract a lot which somewhat complicates implementation..

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.