I try to serialize to a binary archive then load this archive using the code show below. The issue I have is that when loading the file, I get an "input stream error".
#include "project.h"
// Std
#include <fstream>
// Boost
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/algorithm/string.hpp>
// Qt
#include <QtGui/QMessageBox>
#include <QFileInfo>
#include <QDir>
BOOST_CLASS_VERSION(Tools::CommentModel, 1)
using namespace std;
namespace Sawe {
template<class Archive>
void runSerialization(Archive& ar, Project*& project, QString path)
{
const unsigned magicConst=65553;
unsigned magic = magicConst;
ar & BOOST_SERIALIZATION_NVP(magic);
if (magic != magicConst)
throw std::ios_base::failure("Wrong project type");
ar & BOOST_SERIALIZATION_NVP(project);
}
bool Project::
save()
{
if (project_filename_.empty()) {
return saveAs();
}
try
{
std::ofstream ofs(project_filename_.c_str());
assert(ofs.good());
boost::archive::binary_oarchive xml(ofs);
Project* p = this;
runSerialization(xml, p, project_filename_.c_str());
p->is_modified_ = false;
}
catch (const std::exception& x)
{
QString msg = "Error: " + QString::fromStdString(vartype(x)) +
"\nDetails: " + QString::fromLocal8Bit(x.what());
QMessageBox::warning( 0, "Can't save file", msg );
TaskInfo("======================\nCan't save file\n%s\n======================", msg.toStdString().c_str());
}
return true;
}
#endif
pProject Project::
openProject(std::string project_file)
{
std::ifstream ifs(project_file.c_str());
boost::archive::binary_iarchive xml(ifs);
Project* new_project = 0;
runSerialization(xml, new_project, project_file.c_str());
new_project->project_filename_ = project_file;
new_project->updateWindowTitle();
new_project->is_modified_ = false;
pProject project( new_project );
return project;
}
}
Any idea ?
Thanks in advance for your help!
Cheers
I had the same problem, when i added the binary flag to the fstream ctors everything worked.
Related
So I'm in the middle of implementing SIFT and the thing is that I don't know how to deal with channel in OpenCV. Here is what I've done so far.
#ifndef QUANTIZATION_DATABASE_DATA_READ_H
#define QUANTIZATION_DATABASE_DATA_READ_H
// C HEADERS
#include <stdlib.h>
#include <fcntl.h>
// C++ HEADERS
#include <iostream>
#include <string>
// OPENCV HEADERS
#include <opencv2/opencv.hpp>
namespace cv
{
class DataReader
{
public:
explicit DataReader(int _flags) : flags(_flags)
{
}
void read(std::string filename, const char *key, Mat &res)
{
try
{
FileStorage fs(filename, FileStorage::Mode::FORMAT_XML | FileStorage::Mode::READ);
fs[key] >> res;
fs.release();
}
catch (Exception e)
{
std::cerr << e.msg << std::endl;
}
}
private:
int flags;
};
}
The algorithm that I want to implement is as follow.
Read the 4 dimensional matrix(NHWC) from a xml file.
Store it in a matrix
Convert it into NHWC
The thing is that I don't have to do step 3 when I do some stuffs using Tensorflow. It just automatically knows the last dimension is channel. So, what should I do?
It seems like there is no way whatsoever to make 4 dimensional buffer to a batch of images. So I decided to change the format of the xml file and it worked like a charm.
Below is temporarily workaround for this problem.
#ifndef QUANTIZATION_DATABASE_DATA_READ_H
#define QUANTIZATION_DATABASE_DATA_READ_H
// C HEADERS
#include <stdlib.h>
#include <fcntl.h>
// C++ HEADERS
#include <iostream>
#include <string>
// OPENCV HEADERS
#include <opencv2/opencv.hpp>
namespace cv
{
class DataReader
{
public:
explicit DataReader(int _flags) : flags(_flags)
{
}
void read(std::string filename, Mat &res)
{
try
{
float length = 0;
FileStorage fs(filename, FileStorage::Mode::FORMAT_XML | FileStorage::Mode::READ);
fs["size"] >> length;
for (int i = 0; i < (int)length; ++i) {
std::string key("image");
std::string index = std::to_string(i);
Mat image;
key = key + index;
fs[key.c_str()] >> image;
std::cout << image.channels() << std::endl;
res.push_back(image);
}
fs.release();
}
catch (Exception e)
{
std::cerr << e.msg << std::endl;
}
}
private:
int flags;
};
}
I am trying to use WritePrivateProfileString and GetPrivateProfileInt for a .ini parser.
When I put the code below into main(), or into a class constructor, it works for writing and reading.
But, when I make functions for writing and reading, and call the functions in main(), nothing happens, although the functions are run as they will cout something if I ask them to.
Here is the test program I wrote to demonstrate this:
#include <iostream>
#include <Windows.h>
#include <fstream>
#include <string>
#define CStringify(x) std::to_string(x).c_str()
int testvar = 12;
int returntestvar = 0;
std::fstream config;
std::string configstring = ".//config.ini";
int main()
{
WriteINI();
ReadINI();
std::cout << returntestvar << std::endl;
getchar();
}
void WriteINI()
{
config.open("config.ini", std::ios::app);
WritePrivateProfileString("Test", "Test1", CStringify(testvar), configstring.c_str());
}
void ReadINI()
{
config.open("config.ini", std::ios::app);
returntestvar = GetPrivateProfileInt("Test", "Test1", 0, configstring.c_str());
}
The above code creates and then edits an .ini file, as it is expected to.
However, if I move the code into a class, it will no longer work.
main.cpp
#include <iostream>
#include <Windows.h>
#include <fstream>
#include <string>
#include "INIClassTest.h"
extern INIParser* Parse;
int main()
{
Parse->WriteINI();
Parse->ReadINI();
std::cout << Parse->returntestvar << std::endl;
getchar();
}
INIClassTest.h
#pragma once
#include <fstream>
#include <string>
#include <Windows.h>
#define CStringify(x) std::to_string(x).c_str()
class INIParser
{
public:
INIParser();
void WriteINI();
void ReadINI();
int testvar;
int returntestvar;
std::fstream config;
std::string configstring;
};
extern INIParser* Parse;
INIClassTest.cpp
#include "INIClassTest.h"
#include <iostream>
INIParser* Parse = new INIParser();
INIParser::INIParser()
{
returntestvar = 0;
testvar = 18;
std::string configstring = ".//config.ini";
}
void INIParser::WriteINI()
{
config.open("config.ini", std::ios::app);
WritePrivateProfileString("Test", "Test1", CStringify(testvar), configstring.c_str());
}
void INIParser::ReadINI()
{
config.open("config.ini", std::ios::app);
returntestvar = GetPrivateProfileInt("Test", "Test1", 0, configstring.c_str());
}
The above code creates an .ini file, but it doesn't edit it or return anything.
You should NOT be using an fstream at all to create/open the INI file manually. WritePrivateProfileString() and GetPrivateProfileInt() handle that for you.
Also, if you read their documentation, you would see that you SHOULD NOT use a relative path for the INI file, or else the file will be relative to the Windows installation folder, not your app folder. So, you probably ARE reading/writing the INI file, just not where you are expecting from/to. If you want your INI file to be relative to your app's folder, you need to retrieve the path of your app's folder 1 and append the INI filename to it.
1: that is really not a good idea in general, though. Depending on where you install your app, the user might not have write access to that folder. You should instead use SHGetFolderPath() or SHGetKnownFolderPath() to get the user's local %AppData% folder, then create your own subfolder inside of it, and then create your INI file inside of that subfolder.
Try this instead:
#include <Windows.h>
#include <iostream>
#include <string>
#define CStringify(x) std::to_string(x).c_str()
std::string GetAppFolder();
std::string GetINIPath();
void WriteINI();
void ReadINI();
int testvar = 12;
int returntestvar = 0;
std::string configstring = GetINIPath();
int main()
{
WriteINI();
ReadINI();
std::cout << returntestvar << std::endl;
std::cin.get();
return 0;
}
std::string GetAppFolder()
{
char szFileName[MAX_PATH];
DWORD len = GetModuleFileName(NULL, szFileName, MAX_PATH);
std::string result(szFileName, len);
std::string::size_type pos = result.find_last_of("\\/");
result.resize(pos+1);
return result;
}
std::string GetINIPath()
{
return GetAppFolder() + "config.ini";
}
void WriteINI()
{
WritePrivateProfileString("Test", "Test1", CStringify(testvar), configstring.c_str());
}
void ReadINI()
{
returntestvar = GetPrivateProfileInt("Test", "Test1", 0, configstring.c_str());
}
The main reason your INIParser class fails is because your constructor is storing the INI file path in a local variable named configstring, instead of in the class's member also named configstring. Thus, the class member is blank when WriteINI() and ReadINI() are called.
Try this instead:
main.cpp
#include <iostream>
#include "INIClassTest.h"
int main()
{
Parse.WriteINI();
Parse.ReadINI();
std::cout << Parse.returntestvar << std::endl;
std::cin.get();
return 0;
}
INIClassTest.h
#pragma once
#include <string>
class INIParser
{
public:
INIParser();
void WriteINI();
void ReadINI();
int testvar;
int returntestvar;
std::string configstring;
};
extern INIParser Parse;
INIClassTest.cpp
#include <Windows.h>
#include "INIClassTest.h"
#include <string>
#define CStringify(x) std::to_string(x).c_str()
INIParser Parse;
static std::string GetAppFolder()
{
char szFileName[MAX_PATH];
DWORD len = GetModuleFileName(NULL, szFileName, MAX_PATH);
std::string result(szFileName, len);
std::string::size_type pos = result.find_last_of("\\/");
result.resize(pos+1);
return result;
}
static std::string GetINIPath()
{
return GetAppFolder() + "config.ini";
}
INIParser::INIParser()
{
returntestvar = 0;
testvar = 18;
configstring = GetINIPath();
}
void INIParser::WriteINI()
{
WritePrivateProfileString("Test", "Test1", CStringify(testvar), configstring.c_str());
}
void INIParser::ReadINI()
{
returntestvar = GetPrivateProfileInt("Test", "Test1", 0, configstring.c_str());
}
I want to make a program that reads the highest value from one file and stores it in another. I've read about ifstream and ofstream but how do I let the ofstream store the highest value from the instream in another file? Here is what I have so far:
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <iterator>
#include <vector>
using namespace std;
struct CsvWhitespace : ctype<char> {
static const mask* make_table() {
static vector<mask> v{classic_table(), classic_table() + table_size};
v[','] |= space; // comma will be classified as whitespace
return v.data();
}
CsvWhitespace(size_t refs = 0) : ctype{make_table(), false, refs} {}
} csvWhitespace;
int main() {
string line;
ifstream myfile ("C:/Users/Username/Desktop/log.csv");
ofstream myfile2 ("C:/Users/Username/Desktop/log2.csv");
return 0;
}
auto v = vector<int>{};
myfile.imbue(locale{myfile.getloc(), &csvWhitespace});
copy(istream_iterator<int>{myfile}, istream_iterator<int>{}, back_inserter(v));
myfile2 << *max_element(begin(v), end(v));
}
Thanks in advance :)
You could just copy from the one file in the other, without having to worry about the format, by treating them in binary mode. Here is an example:
#include <stdio.h>
#include <string.h>
#define bufSize 1024
int main(int argc, char *argv[])
{
FILE *ifp, *ofp;
char buf[bufSize];
if (argc != 3)
{
fprintf(stderr,
"Usage: %s <soure-file> <target-file>\n", argv[0]);
return 1;
}
if ((ifp = fopen(argv[1], "rb")) == NULL)
{ /* Open source file. */
perror("fopen source-file");
return 1;
}
if ((ofp = fopen(argv[2], "wb")) == NULL)
{ /* Open target file. */
perror("fopen target-file");
return 1;
}
while (fgets(buf, sizeof(buf), ifp) != NULL)
{ /* While we don't reach the end of source. */
/* Read characters from source file to fill buffer. */
/* Write characters read to target file. */
fwrite(buf, sizeof(char), strlen(buf), ofp);
}
fclose(ifp);
fclose(ofp);
return 0;
}
which was given as an example in IP, source. You just need to specify the cmd arguments as the desired files.
You can do it like this. Live example using cin and cout rather than files.
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <iterator>
#include <vector>
using namespace std;
struct CsvWhitespace : ctype<char> {
static const mask* make_table() {
static vector<mask> v{classic_table(), classic_table() + table_size};
v[','] |= space; // comma will be classified as whitespace
return v.data();
}
CsvWhitespace(size_t refs = 0) : ctype{make_table(), false, refs} {}
};
int main() {
string line;
ifstream myfile("log.csv");
ofstream myfile2("log2.csv");
auto v = vector<int>{};
myfile.imbue(locale{myfile.getloc(), new CsvWhitespace{}});
copy(istream_iterator<int>{myfile}, istream_iterator<int>{}, back_inserter(v));
myfile2 << *max_element(begin(v), end(v));
}
I am having trouble with this library... My code works fine, the parsers/creator works too, but an err appears, I don't know why:
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/thread.hpp>
#include <string>
#include <exception>
#include <set>
#include <iostream>
#include "journal.h"
unsigned short port = 2013;
unsigned short maxConnec = 250;
unsigned short fPort() {return port;}
unsigned short fMaxConnec() {return maxConnec;}
bool load(const std::string &file)
{
using boost::property_tree::ptree;
ptree objectXML;
std::cout << "bbb";
read_xml(file, objectXML);
std::cout << "aaa";
if (file.length() == 0) // By the way, no way to do that better ? "if file doesn't exist..."
{
return 0;
}
else
{
port = objectXML.get<unsigned short>("configuration.server.port");
maxConnec = objectXML.get<unsigned short>("configuration.server.maxConnections");
return 1;
}
}
bool save(const std::string &file)
{
try
{
using boost::property_tree::ptree;
ptree objectXML;
objetXML.put("configuration.server.port", port);
objetXML.put("configuration.server.maxConnections", maxConnec);
write_xml(file, objectXML, std::locale(), boost::property_tree::xml_writer_make_settings<ptree::key_type>(' ', 4));
return 1;
}
catch (std::exception e)
{
return 0;
}
}
void generate()
{
std::string file = "configuration.xml";
try{
if (!load(fichier))
{
save(file);
}
}
catch (std::exception &e)
{
load(file);
}
}
Get a bad path, I totally don't know why because when I try to read data I can and it gets the data in configuration.xml even if I change it...
The ptree_bad_path exception is raised from the throwing version of get and signals that "configuration.server.port" or "configuration.server.maxConnections" path to the XML element doesn't exist.
The error isn't related to the configuration.xml file path.
So you should check the element name or, for optional elements, use the default-value / optional-value version of get.
Why istream object after calling readsome() method don't give any chars in buffer? Is there any error in class construction?
StreamBuffer.h
#ifndef StreamBuffer_h
#define StreamBuffer_h
#include <string>
#include <fstream>
#include <iostream>
#include <iterator>
enum StreamBufferState
{
STREAMBUFFER_OK = 0,
STREAMBUFFER_EOF = 1
};
class StreamBuffer
{
std::fstream file;
std::istream istrm;
int maxBufferSize;
std::string buffer;
public:
StreamBuffer(int maxBuffSize, const std::string& filename);
~StreamBuffer();
void SetMaxBufferSize(unsigned int maxBuffSize);
StreamBufferState FullBufferWithData();
std::string GetDataBuffer();
};
#endif
StreamBuffer.cpp
#include "StreamBuffer.h"
using namespace std;
StreamBuffer::StreamBuffer(int maxBuffSize, const std::string& filename) : istrm( !filename.empty() ? file.rdbuf() : cin.rdbuf() )
{
SetMaxBufferSize(maxBuffSize);
if(!filename.empty())
{
file.open(filename.c_str(),ios::in | ios::binary);
}
else
{
std::cin>>noskipws;
}
}
StreamBuffer::~StreamBuffer()
{
file.close();
}
void StreamBuffer::SetMaxBufferSize(unsigned int maxBuffSize)
{
maxBufferSize = maxBuffSize;
}
StreamBufferState StreamBuffer::FullBufferWithData()
{
istrm.readsome((char*)&buffer[0],maxBufferSize);
if(istrm.eof())
return STREAMBUFFER_EOF;
return STREAMBUFFER_OK;
}
std::string StreamBuffer::GetDataBuffer()
{
string buf = buffer;
return buf;
}
File is opened, but readsome() don't read buffer.
You have undefined behavior in your code, as you try read into an empty string. You need to set the size of buffer.
An unrelated logical error: In the FullBufferWithData function you will return "OK" even if there is an error reading the file.