BOOST.IOstreams: trouble to write to bzip2 - c++

Hello I am would like to store my data in to bzip2 file using Boost.IOstreams.
void test_bzip()
{
namespace BI = boost::iostreams;
{
string fname="test.bz2";
{
BI::filtering_stream<BI::bidirectional> my_filter;
my_filter.push(BI::combine(BI::bzip2_decompressor(), BI::bzip2_compressor())) ;
my_filter.push(std::fstream(fname.c_str(), std::ios::binary|std::ios::out)) ;
my_filter << "test" ;
}//when my_filter is destroyed it is trowing an assertion.
}
};
What I am doing wrong?
I am using boost 1.42.0.
kind regards
Arman.
EDIT
The code is working if I remove the bidirectional option:
#include <fstream>
#include <iostream>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/bzip2.hpp>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <string>
void test_bzip()
{
namespace BI = boost::iostreams;
{
std::string fname="test.bz2";
{
std::fstream myfile(fname.c_str(), std::ios::binary|std::ios::out);
BI::filtering_stream<BI::output> my_filter;
my_filter.push(BI::bzip2_compressor()) ;
//my_filter.push(std::fstream(fname.c_str(), std::ios::binary|std::ios::out)) ; //this line will work on VC++ 2008 V9 but not in G++ 4.4.4
my_filter.push(myfile);
my_filter << "test";
}
}
};
maybe some one can explain why?

An fstream can not be copied, so you must use the reference version of push
template<typename StreamOrStreambuf>
void push( StreamOrStreambuf& t,
std::streamsize buffer_size = default value,
std::streamsize pback_size = default value );
So your function should look something like
std::fstream theFile(fname.c_str(), std::ios::binary | std::ios::out);
// [...]
my_filter.push(theFile) ;
I'm suprised you compiler allows your code, I'd think it complain about a reference to temporary... which compiler are you using?

Related

C++ range-v3: trying to chain together transforms

I'm completely new to the range library, so I shouldn't be surprised that this code isn't compiling and I cannot figure out why:
#include <iostream>
#include <algorithm>
#include <fstream>
#include <iterator>
#include <vector>
#include <range/v3/all.hpp>
#include <range/v3/view/all.hpp>
using namespace ranges::v3;
std::ifstream open_file(const std::string &filename) {
return std::ifstream{filename};
}
int count_lines(std::ifstream &in) {
return std::count(std::istreambuf_iterator<char>{in},
std::istreambuf_iterator<char>{}, '\n');
}
std::vector<int>
count_lines_in_files(const std::vector<std::string> &filenames) {
auto a1 = filenames | view::transform(open_file) | view::transform(count_lines);
return a1;
}
int main() {
const std::vector<std::string> files{"listing1_1.cpp",
"listing1_2.cpp",
"listing1_4.cpp",
"listing1_5.cpp"};
const auto result = count_lines_in_files(files);
std::cout << ranges::view::all(result) << '\n';
}
It appears that the complaint is about a1, which the compiler tells me "error: variable has incomplete type 'void'."
Can someone see what I'm doing wrong, or tell me how to properly chain these together if possible?
Thanks in advance!
As noted by Porsche9II, "std::ifstream doesn't have a copy constructor". You can find more on this topic here:
Why are iostreams not copyable?
C++11 introduced a move constructor (6) for std::basic_ifstream, so you could write
auto open_file(const std::string &filename) {
return std::ifstream{filename};
}
auto count_lines(std::ifstream &&in) {
return std::count(std::istreambuf_iterator<char>{in},
std::istreambuf_iterator<char>{}, '\n');
}
Testable HERE.
std::ifstream doesn't have a copy constructor - returning std::ifstream by a function is not a good idea. One possible solution: opening and counting should take place in one function.

using std::string disables program output

Whenever I use std::string to declare a string variable in c++ it prevents the program from outputting anything. for example:
#include <cstdlib>
#include <iostream>
#include <string>
int main() {
std::cout << "Hello";
// std::string s;
return 0;
}
This will output Hello to the command-line as it should do.
#include <cstdlib>
#include <iostream>
#include <string>
int main() {
std::cout << "Hello";
std::string s;
return 0;
}
This will not output anything (and no errors) since i'm declaring a variable using std::string
I'm using the minGW compiler on a Windows 10 64bit machine

How to convert class object to json string using boost library in C++?

I am fairly new to C++ and I apologise beforehand if you find this very easy.
I have the following files
POST1.h
#ifndef POST1_HH
#define POST1_HH
#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
using namespace std ;
using boost::property_tree::ptree;
using boost::property_tree::read_json;
using boost::property_tree::write_json;
using boost::property_tree::basic_ptree;
#include "DBAccess2.h"
class POST1
{
public:
string TokenNo;
string CommandStatus;
string CommandID;
string CPUID;
string ISEncrypted;
string JSON_Cmnd_String;
void POST_Device_Status(sqliteDB & DB_OBJ);
};
#endif
Below is POST1.cpp
#include <iostream>
#include <sstream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include "DBAccess2.h"
#include "POST1.h"
using namespace std ;
using boost::property_tree::ptree;
using boost::property_tree::read_json;
using boost::property_tree::write_json;
using boost::property_tree::basic_ptree;
void POST1::POST_Device_Status(sqliteDB & DB_OBJ)
{
POST1 POST_OBJ;
POST_OBJ.TokenNo = "1122";
POST_OBJ.CommandStatus = "0";
POST_OBJ.CommandID = "00";
POST_OBJ.CPUID = "A1234B1234";
POST_OBJ.ISEncrypted = "0";
POST_OBJ.JSON_Cmnd_String = DB_OBJ.dump(DB_OBJ);
}
NOTE:-
(1) sqliteDB is another class declared in a .cpp file.
(2) the output of function dump() is a json string. this get stored into JSON_Cmnd_string.
So, I want to convert the class object into JSON string, How can I do that ?
Do I have to first put these object into a container (like vector or list) and then write it into JSON?
This is not "fairly easy", because C++ doesn't have JSON support.
Neither does Boost:
how to get boost json to use the correct data types
That said, this appears to be what you want:
http://www.boost.org/doc/libs/1_57_0/doc/html/boost_propertytree/tutorial.html
So, I want to convert the class object into JSON string, How can I do that ? Do I have to first put these object into a container (like vector or list) and then write it into JSON?
Yes, you put them into a tree container, namely boost::property_tree::ptree:
Live On Coliru
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <iostream>
#include <sstream>
using boost::property_tree::ptree;
namespace Entities {
struct POST1 {
std::string TokenNo;
std::string CommandStatus;
std::string CommandID;
std::string CPUID;
std::string ISEncrypted;
};
std::string to_json(POST1 const& o) {
ptree out;
out.put("POST1.TokenNo", o.TokenNo);
out.put("POST1.CommandStatus", o.CommandStatus);
out.put("POST1.CommandID", o.CommandID);
out.put("POST1.CPUID", o.CPUID);
out.put("POST1.ISEncrypted", o.ISEncrypted);
std::ostringstream oss;
boost::property_tree::write_json(oss, out);
return oss.str();
}
}
// ADL trigger; `using Entities::to_json` would be roughly equivalent, but not
// make it clear that ADL is happening
void to_json();
int main() {
Entities::POST1 obj { "1122", "0", "00", "A1234B1234", "0" };
std::cout << to_json(obj);
}
Output:
{
"POST1": {
"TokenNo": "1122",
"CommandStatus": "0",
"CommandID": "00",
"CPUID": "A1234B1234",
"ISEncrypted": "0"
}
}
with boost 1.78.0,you can use this
use this simple way
pt::ptree root;
root.put("POST1 .TokenNo", "1122");
root.put("POST1 .CommandStatus", "0");
root.put("POST1 .CommandID", "00");
root.put("POST1 .CPUID", "A1234B1234");
root.put("POST1 .ISEncrypted", "0");
// Once our ptree was constructed, we can generate JSON on standard output
pt::write_json(std::cout, root);
OUT PUT
{
"POST1": {
"TokenNo": "1122",
"CommandStatus": "0",
"CommandID": "00",
"CPUID": "A1234B1234",
"ISEncrypted": "0"
}
}

Is <iostream> needed to use a string in c++?

This code works for me:
#include <string>
#include <iostream>
int main()
{
std::string s;
s = "hello world";
cout << s;
return 0;
}
But this one doesn't:
#include <string>
int main()
{
string s;
s = "hello world";
return 0;
}
Is the include of <iostream> needed as well as the <string> one?
I'm using Eclipse CDT IDE.
Iostream is not needed to use string. You are missing using namespace std (or alternatively using the std:: prefix) in the second example, that's why it's not working.

How to pass string type arguments to c++ methods

I am a C++ noob, fiddling with the following problem for some hours now. Hopefully, someone can enlighten me.
I had a cpp file with content like so:
test.cpp file content
#include <iostream>
#include <exception>
#include <stdlib.h>
#include <string.h>
using std::cin; using std::endl;
using std::string;
string foobar(string bar) {
return "foo" + bar;
}
int main(int argc, char* argv[])
{
string bar = "bar";
System::convCout << "Foobar: " << foobar(bar) << endl;
}
This one compiles and runs well. Now I'd like to put foobar into an external library:
mylib.h file content
string foobar(string bar);
mylib.cpp file content
#include <string.h>
using std::cin; using std::endl;
using std::string;
string foobar(string bar) {
return "foo" + bar;
}
test.cpp file content
#include <iostream>
#include <exception>
#include <stdlib.h>
#include "mylib.h"
int main(int argc, char* argv[])
{
string bar = "bar";
System::convCout << "Foobar: " << foobar(bar) << endl;
}
I adjusted my Makefile, so that test.cpp compiles and links mylib, but I always encounter the error:
test.cpp::8 undefined reference to `foobar(std::string)
How do I have to handle string arguments? My attempts seems to be completely wrong here.
Regards
Felix
The C++ standard library type std::string is in the header string. To use it, you must include <string>, not <string.h>. Your mylib.h should look something like
#ifndef MYLIB_H
#define MYLIB_H
#include <string>
std::string foobar(std::string bar);
#endif
and your mylib.cpp should include it:
#include "mylib.h"
std::string foobar(std::string bar) {
return "foo" + bar;
}
Note that it may be unnecessary to pass bar by value. Looking at your code, a const reference might do.