I am new to C++ and I am trying to output a wave file in. I have had success with binary files in both C# and Java but I am not yet comfortable with C++ yet. I know about that arrays and objects should generally be created on the heap.
It is fine with the strings and the first getter
Whenever it gets to the second getter for the base class it runs out of memory.
This class is called waveWriter and it extends a class called WaveFormat that contains the getters
WaveWriter header:
class WaveWriter : WaveFormat {
private:
std::string fileName;
public:
WaveWriter(uint16_t channels, uint32_t sampleRate,
uint16_t bitsPerSample, double* lSampleData,
uint32_t lSampleLength, double* rSampleData,
uint32_t rSampleLength, bool isFloat, std::string outputName);
~WaveWriter();
void writeWave() {
std::ofstream myFile;
myFile = std::ofstream(fileName, std::ios::out | std::ios::binary);
// write the header
// sGroupID
myFile << S_GROUP_ID_HEADER;
// dwfilelength
myFile.write(reinterpret_cast<const char *> (GetDwFileLength()),
sizeof (GetDwFileLength()));
// sRiffType
myFile << S_RIFF_TYPE;
// write the format
// sGroupID
myFile << S_GROUP_ID_FORMAT;
// dwChunkSize
myFile.write(reinterpret_cast<const char *> (GetDwFormatChunkSize()),
sizeof (GetDwFormatChunkSize()));
// wFormatTag
........ blah blah blah
// close file
myFile.close();
return;
}
};
cpp for this class:
WaveWriter::WaveWriter(uint16_t channels, uint32_t sampleRate,
uint16_t bitsPerSample, double* lSampleData,
uint32_t lSampleLength, double* rSampleData,
uint32_t rSampleLength, bool isFloat, std::string outputName) :
WaveFormat(channels, sampleRate, bitsPerSample,
lSampleData, lSampleLength, rSampleData,
rSampleLength, isFloat) {
outputName.append(".wav");
this->fileName = outputName;
}
WaveWriter::~WaveWriter() {
this->~WaveFormat();
}
Header for WaveFormat contains private variables a constructor and getters like these to access the private variables:
public:
uint16_t GetCbSize() {
return cbSize;
}
uint32_t GetDwAvgBytesPerSec() {
return dwAvgBytesPerSec;
}
uint32_t GetDwChannelMask() {
return dwChannelMask;
}......
This is speculation based on your functions name, but I think this code:
myFile.write(reinterpret_cast<const char *> (GetDwFileLength()),sizeof (GetDwFileLength()));
is incorrect. Assuming GetDwFileLength() return size as value, it is incorrect to cast it to const char *. You need to save it in another argument and post its address to cast. Something like this:
auto val = GetDwFileLength();
myFile.write(reinterpret_cast<const char *> (&val), sizeof (val));
I see similar mistake several times in your code. This mistake can make invalid memory access.
In addition you should use virtual base destructor rather than calling base destructor from derived class. Never call base destructor in derived class.
Related
I am currently developing some software in C++ where I am sending and receiving custom data packets. I want to parse and manage these packets in a well structured manner. Obviously I am first receiving the header and after that the body of the data. The main problem is that I don't like creating a Packet-Object with only the header information and later on adding the body data. What is an elegant way of parsing and storing custom data packets?
Here is a rough sketch of what such a custom data packet could look like:
+-------+---------+---------+----------+------+
| Magic | Command | Options | Bodysize | Body |
+-------+---------+---------+----------+------+
(Lets assume Magic is 4 bytes, Command 1 byte, Options 2 bytes, Bodysize 4 bytes and the body itself is variable in length.)
How would I parse this without using any third party libraries?
Normally I'd say something like this could be done to store packet data:
#include <array>
class Packet {
public:
explicit Packet(std::array<char, 10> headerbytes);
void set_body(std::vector<char> data);
std::vector<char> get_body();
int8_t get_command();
int16_t get_options();
bool is_valid();
private:
bool valid;
int8_t _command;
int16_t _options;
int32_t body_size;
std::vector<char> _data;
};
The problem is that I provide the header-information first and than add the body data in a hacky way later on. The packet object has a point of time where it is accessible in an incomplete state.
I first receive the header and after the header was received another receive call is made to read the body.
Would it make sense to have a parser instance that populates information into the packet object only make it accessible once it holds all needed information? Would it make sense to have a separate class for the header and the body? What would be the best design choice?
I am developing with C++ and for the sending and receiving of data over sockets the boost library is used.
If you don’t want to tie the data reading into one complete constructor (for understandable reasons of separation of concerns), this is a good application for non-polymorphic inheritance:
struct Header {
static constexpr SIZE=10;
Header(std::array<char,SIZE>);
std::int8_t get_command() const {return command;}
std::int16_t get_options() const {return options;}
std::int32_t body_size() const {return length;}
private:
std::int8_t command;
std::int16_t options;
std::int32_t length;
};
struct Packet : private Header {
using Body=std::vector<char>;
Packet(const Header &h,Body b) : Header(h),body(std::move(b))
{if(body.size()!=body_size()) throw …;}
using Header::get_command;
using Header::get_options;
const Body& get_body() const {return body;}
private:
Body body;
};
// For some suitable Stream class:
Header read1(Stream &s)
{return {s.read<Header::SIZE>()};}
Packet read2(const Header &h,Stream &s)
{return {h,s.read(h.body_size())};}
Packet read(Stream &s)
{return read2(read1(s),s);}
Note that the private inheritance prevents undefined behavior from deleting a Packet via a Header*, as well as the surely-unintended
const Packet p=read(s);
const Packet q=read2(p,s); // same header?!
Composition would of course work as well, but might result in more adapter code in a full implementation.
If you were really optimizing, you could make a HeaderOnly without the body size and derive Header and Packet from that.
For this case I would use the pipeline design pattern creating 3 packet processor classes:
Command (handles magic bytes too)
Options
Body (handles body size too)
all derived from one base class.
typedef unsigned char byte;
namespace Packet
{
namespace Processor
{
namespace Field
{
class Item
{
public:
/// Returns true when the field was fully processed, false otherwise.
virtual bool operator () (const byte*& begin, const byte* const end) = 0;
};
class Command: public Item
{
public:
virtual bool operator () (const byte*& begin, const byte* const end);
};
class Options: public Item
{
public:
virtual bool operator () (const byte*& begin, const byte* const end);
};
class Body: public Item
{
public:
virtual bool operator () (const byte*& begin, const byte* const end);
};
}
class Manager
{
public:
/// Called every time new data is received
void operator () (const byte* begin, const byte* const end)
{
while((*fields[index])(begin, end))
{
incrementIndex();
}
}
protected:
void incrementIndex();
Field::Command command;
Field::Options options;
Field::Body body;
Field::Item* const fields[3] = { &command, &options, &body };
byte index;
};
}
}
You can use exceptions to prevent creation of incomplete packet objects.
I'd use char pointers instead of vectors for performance.
// not intended to be inherited
class Packet final {
public:
Packet(const char* data, unsigned int data_len) {
if(data_len < header_len) {
throw std::invalid_argument("data too small");
}
const char* dataIter = data;
if(!check_validity(dataIter)) {
throw std::invalid_argument("invalid magic word");
}
dataIter += sizeof(magic);
memcpy(&command, dataIter, sizeof(command)); // can use cast & assignment, too
dataIter += sizeof(command);
memcpy(&options, dataIter, sizeof(options)); // can use cast & assignment, too
dataIter += sizeof(options);
memcpy(&body_size, dataIter, sizeof(body_size)); // can use cast & assignment, too
dataIter += sizeof(body_size);
if( data_len < body_size+header_len) {
throw std::invalid_argument("data body too small");
}
body = new char[body_size];
memcpy(body, dataIter, body_size);
}
~Packet() {
delete[] body;
}
int8_t get_command() const {
return command;
}
int16_t get_options() const {
return options;
}
int32_t get_body_size() const {
return body_size;
}
const char* get_body() const {
return body;
}
private:
// assumes len enough, may add param in_len for robustness
static bool check_validity(const char* in_magic) {
return ( 0 == memcmp(magic, in_magic, sizeof(magic)) );
}
constexpr static char magic[] = {'a','b','c','d'};
int8_t command;
int16_t options;
int32_t body_size;
char* body;
constexpr static unsigned int header_len = sizeof(magic) + sizeof(command)
+ sizeof(options) + sizeof(body_size);
};
Note: this is my first post in SO, so please let me know if something's wrong with the post, thanks.
I'm guessing you are trying Object-oriented networking. If so, the best solution for such parsing would be Flatbuffers or Cap’n Proto C++ code generator. By defining a schema, you will get state machine code that will parse the packets in an efficient and safe way.
I need to write a class to a binary file, and then I need to read it back.
I have Triangle and BinaryFile classes, and some other classes. I am not sure if I am writing incorrectly or reading incorrectly. An error occurs when reading. After debugging, I think that it gets inappropriate data for my private variables. I will be very glad if someone can give me some advice on how to make it work properly.
I wasn't sure if I should paste the whole code or not, so I will give you a short snippet of code. Just in case, here is a download link for my source code:
https://my.pcloud.com/publink/show?code=XZJ7CYZbsLWLglqV5p83csijcEUTFqqpM3k
I am a newbie in programming and I don't speak English very well, so I apologize in advance for my mistakes.
class Point
{
private:
int x;
int y;
};
class Figure
{
private:
string name;
string type;
};
class Triangle: public Figure
{
private:
Point p1, p2, p3;
};
class BinaryFile
{
private:
string FileName;
fstream File;
public:
//...
void AddNewFigure(istream& stream)
{
File.open(this->FileName, ios::binary | ios::app);
if(!this->File)
{
cerr<<"File error <"<<this->FileName<<">\n";
exit(1);
}
Triangle fig;
fig.MakeNewFigure(stream);
File.write((char*)&fig, sizeof(Triangle));
File.close();
}
Triangle GetTriangle()
{
Triangle trig;
Point p;
string str(""); int x(0);
File.open(this->FileName, ios::binary | ios::in);
if(!this->File)
{
cerr<<"File error <"<<this->FileName<<">\n";
exit(1);
}
File.read((char*)&trig, sizeof(Triangle));
File.close();
return trig;
}
};
The answer depends on whether you are just doing this to learn how files work or whether saving to the file is just incidental and you don't care how it works.
If you just want to get the stuff to save and restore and you don't care how it works then use a third party library. There are many many of them.
If you want to learn how to read and write things to files then you will need to make your own read and write functions. I have made a sample program that will explain how it works:
#include <string>
#include <fstream>
#include <iostream>
class Point
{
private:
int x;
int y;
public:
Point():x(0),y(0){}
Point(int x,int y):x(x),y(y){}
void write(std::ostream& f)
{
// We can just write out the bytes for x and y because
// they are primitive types stored in the class
f.write( (char*)&x, sizeof(x) );
f.write( (char*)&y, sizeof(y) );
}
void read(std::istream& f)
{
// We can just read the bytes directly into x and y because
// they are primitive types stored in the class
f.read( (char*)&x, sizeof(x) );
f.read( (char*)&y, sizeof(y) );
}
};
class Figure
{
private:
std::string name;
std::string type;
public:
Figure(){}
Figure(std::string name,std::string type):name(name),type(type){}
void write(std::ostream& f)
{
size_t size;
// we need to store the data from the string along with the size
// because to restore it we need to temporarily read it somewhere
// before storing it in the std::string (istream::read() doesn't
// read directly to std::string)
size = name.size();
f.write( (char*)&size, sizeof(size_t) );
f.write( (char*)name.c_str(), size );
size = type.size();
f.write( (char*)&size, sizeof(size_t) );
f.write( (char*)type.c_str(), size );
}
void read(std::istream& f)
{
size_t size;
char *data;
// when we read the string data we need somewhere to store it
// because we std::string isn't a primitive type. So we read
// the size, allocate an array, read the data into the array,
// load the std::string, and delete the array
f.read( (char*)&size, sizeof(size) );
data = new char[size+1];
f.read( data, size );
data[size]='\0';
name = data;
delete data;
f.read( (char*)&size, sizeof(size) );
data = new char[size+1];
f.read( data, size );
data[size]='\0';
type = data;
delete data;
}
};
class Triangle: public Figure
{
private:
Point p1, p2, p3;
public:
Triangle(){}
Triangle(Point x,Point y,Point z,Figure f):p1(x),p2(y),p3(z),Figure(f){}
void write(std::ostream& f)
{
// First write the base class then write the members of this class
Figure::write(f);
p1.write(f);
p2.write(f);
p3.write(f);
}
void read(std::istream& f)
{
// First read the base class then read the members of this class
Figure::read(f);
p1.read(f);
p2.read(f);
p3.read(f);
}
};
class BinaryFile
{
private:
std::string FileName;
std::fstream File;
public:
BinaryFile(std::string FileName) : FileName(FileName) {};
void WriteTriangle()
{
File.open(FileName, std::ios::binary | std::ios::out);
if(!File)
{
std::cerr<<"File error <"<<FileName<<">\n";
exit(1);
}
Triangle trig({1,2},{3,4},{5,6},{"name","type"}); // something new
trig.write(File);
File.close();
}
Triangle ReadTriangle()
{
File.open(FileName, std::ios::binary | std::ios::in);
if(!File)
{
std::cerr<<"File error <"<<FileName<<">\n";
exit(1);
}
Triangle trig; // default values
trig.read(File);
File.close();
return trig;
}
};
main()
{
BinaryFile bin("file.bin");
bin.WriteTriangle();
Triangle trig = bin.ReadTriangle();
// at this point trig has the values we stored
return 0;
}
It's not easy to reproduce the error, due to your large source code and missing data file. But a quick inspection shows that you read and write the binary data using bloc operations:
Triangle trig;
...
File.read((char*)&trig, sizeof(Triangle));
Unfortunately this kind of approach only works if the object you want to save/load is of a class that is trivially copyable, as the following code will demonstrate:
if (is_trivially_copyable<Triangle>::value)
cout << "Triangle is trivially copyable" << endl;
else cout << "Triangle is not trivially copyable" << endl;
So you'll have to serialize the object content writing field by field instead of using a bloc operation. This FAQ on serialization should help you to consider the alternatives.
What you are looking for is to serialize your classes/data that should be saved to file. There are several libraries that has been optimized regarding time and memory consumption for this. Would you mind using a 3rd party library?
If not, have a look at for example boost serialization, cereal or maybe even Google's ProtoBuf. I recon Cereal is a good start if you are using C++11.
If you'd like to write your own serialization you'd have to consider that for every object that has a dynamic size (such as a string), you will also need to save the object's size to the file. For more info please have a look here:
https://stackoverflow.com/a/11003590/5874704
I have to:
Define a File_handle class with constructor that takes a string argument (file name), opens the file in the constructor, and closes it in the destructor.
As I understand it, this class is used to provide RAII and I am trying to implement the class using FILE* as basic data structure where my goal basically is to make FILE* a smart pointer:
fileHandler.h:
// Class CFile_handler based on FILE*
class CFile_handler {
public:
CFile_handler(); // default constructor
CFile_handler(const std::string& fileName, // constructor
const std::string& mode);
~CFile_handler (); // destructor
// modifying member function
void open_file(const std::string& fileName,
const std::string& mode);
protected:
typedef FILE* ptr;
private:
CFile_handler(const CFile_handler&); // prevent copy creation
CFile_handler& operator= (const CFile_handler&); // prevent copy assignment
ptr c_style_stream; // data member
};
fileHandler.cpp:
// Class CFile_handler member implementations
// default constuctor
CFile_handler::CFile_handler() {
}
// constructor
CFile_handler::CFile_handler(const std::string& fileName, const std::string& mode = "r")
: c_style_stream( fopen( fileName.c_str(), mode.c_str() ) )
{
}
// destructor
CFile_handler::~CFile_handler() {
if (c_style_stream) fclose(c_style_stream);
}
// Modifying member functions
void CFile_handler::open_file(const std::string& fileName, const std::string& mode) {
c_style_stream = ( fopen( fileName.c_str(), mode.c_str() ) );
}
However, I'm having difficulties in overloading I/O operators<< / >>, as I can't figure out how to implement either of them.
How to overload operator<< such that the class works with iostream objects?
Edit:
As it was proposed by #LokiAstari, it would be better strategy to inherit from istream and define own streambuf.
Could someone give an example or directions for the implementation of streambuf that handles FILE*?
What I want to provide is:
CFile_handler fh("filename.txt", "r");
std::string file_text;
fh >> file_text;
or:
CFile_handler fh("filename.txt", "w");
fh << "write this to file";
You can derive types of the std::streams using std::streambuf to handle the FILE*
#include <iostream>
#include <stdio.h>
class OutputFilePointerStream: public std::ostream
{
class OutputFilePointerStreamBuf: public std::streambuf
{
FILE* buffer;
public:
OutputFilePointerStreamBuf(std::string const& fileName)
{
buffer = fopen(fileName.c_str(), "w");
}
~OutputFilePointerStreamBuf()
{
fclose(buffer);
}
virtual std::streamsize xsputn(const char* s, std::streamsize n) override
{
static char format[30];
sprintf(format, "%%.%lds", n);
fprintf(buffer, format, s);
return n;
}
};
OutputFilePointerStreamBuf buffer;
public:
OutputFilePointerStream(std::string const& fileName)
: std::ostream(nullptr)
, buffer(fileName)
{
rdbuf(&buffer);
}
};
int main()
{
OutputFilePointerStream fileStream("Test");
fileStream << "Testing: " << 5 << "><\n";
fileStream << "Line Again\n";
}
Your operator<< function is to output a CFile_handler object to a C++ output stream, it's not for outputting to a CFile_handler object.
To output to a CFile_handler object you have two choices:
As a member function
CFile_handler& CFile_handler::operator<<(int value)
{
// Output an integer to the contained file
return *this;
}
Or as a non-member function which takes a CFile_handler reference as first argument:
CFile_handler& operator<<(CFile_handler& file, int value)
{
// Output an integer to the file contained in `file`
return file;
}
For both of the above variants, you can then do e.g.
CFile_handler my_file(...);
my_file << 1234;
I have a dictionary class , for spell checking . I have an array as the list of words , and I must initialize it with a file that there are words in it .
my problem is that , I need my wordlist variable to be a static variable , cause only one of it is enough for any other extra object created from the dictionary class and it is logical , however there is no need for a second object of the class , but what if we needed more than one object? is there a way?
#ifndef DICTIONARY_H
#define DICTIONARY_H
class Dictionary
{
public:
static const int SIZE = 109582;
Dictionary();
bool lookUp(const char *)const;
private:
void suggestion(const char *)const;
char *wordList[SIZE];
};
#endif
wordlist must be static ...
I only can think of this kind of defining ...
Dictionary::Dictionary()
{
ifstream inputFile("wordsEn.txt", std::ios::in);
if (!inputFile)
{
cerr << "File could not be opened." << endl;
throw;
}
for (int i = 0; i < SIZE && !inputFile.eof(); ++i)
{
wordList[i] = new char[32];
inputFile >> wordList[i];
}
}
There are many ways to solve the programming problem.
Here's my suggestion:
Move the static members out of the class.
class Dictionary
{
public:
Dictionary();
bool lookUp(const char *)const;
private:
void suggestion(const char *)const;
};
In the .cpp file, use:
static const int SIZE = 109582;
static std::vector<std::string> wordList(SIZE);
static int initializeWordList(std::string const& filename)
{
// Do the needul to initialize the wordList.
}
Dictionary::Dictionary()
{
static int init = initializeWordList("wordsEn.txt");
}
This will make sure that the word list is initialized only once, regardless of how may instances of Dictionary you create.
All I want is to store multiple char arrays as member data in the private field of my FileIO class. For some reason I can have one char array and it works fine, but I soon as I add a second, I get an the error stated in the title.
This code works fine:
class FileIO
{
private:
char accNum[];
public:
FileIO();
~FileIO();
void WriteData(Account*);
void WriteData(Person*);
void ReadData(Account*);
};
This code throws an error:
class FileIO
{
private:
char accNum[];
char persName[];
public:
FileIO();
~FileIO();
void WriteData(Account*);
void WriteData(Person*);
void ReadData(Account*);
};
accNum[] is being used in the ReadData(Account*) function to store one character retrieved from a text file using getline(). Here's the code for that:
void FileIO::ReadData(Account * acc)
{
ifstream accFile("accInfo.txt");
accFile.getline(accNum, 100);
cout << accNum << "\n";
accFile.close();
}
There are more lines in the same text file that I want to store in separate char arrays, but as you can see, I can apparently only have one array as a member variable of the FileIO class. Why is this?
char accNum[]; is a zero sized array and is illegal in C++.
If you are going to be dealing with "strings" then you should scrap using c-style strings and use a std::string. Using a std::string your code would then become
class FileIO
{
private:
std::string accNum;
public:
FileIO();
~FileIO();
void WriteData(Account*);
void WriteData(Person*);
void ReadData(Account*);
};
void FileIO::ReadData(Account * acc)
{
ifstream accFile("accInfo.txt");
getline(accFile, accNum);
cout << accNum << "\n";
accFile.close();
}