So I recently installed JSONCPP and for some reason it gives me errors when I try this code:
#include <json.h>
#include <iostream>
#include <fstream>
int main(){
bool alive = true;
while (alive){
Json::Value root; // will contains the root value after parsing.
Json::Reader reader;
std::string test = "testis.json";
bool parsingSuccessful = reader.parse( test, root, false );
if ( !parsingSuccessful )
{
// report to the user the failure and their locations in the document.
std::cout << reader.getFormatedErrorMessages()
<< "\n";
}
std::string encoding = root.get("encoding", "UTF-8" ).asString();
std::cout << encoding << "\n";
alive = false;
}
return 0;
}
And here is the file:
{
"encoding" : "lab"
}
It says that there is a syntax error on Line 1, Column 1, and that there must be a value, object or array. Anyone know how to fix this?
EDIT: Changed to current code, from pastebin
See the Json::Reader::parse documentation. For that overload, the string needs to be the actual document, not the filename.
You can use the istream overload with a ifstream instead.
std::ifstream test("testis.json", std::ifstream::binary);
EDIT: I got it work with:
#include "json/json.h"
#include <iostream>
#include <fstream>
int main(){
bool alive = true;
while (alive){
Json::Value root; // will contains the root value after parsing.
Json::Reader reader;
std::ifstream test("testis.json", std::ifstream::binary);
bool parsingSuccessful = reader.parse( test, root, false );
if ( !parsingSuccessful )
{
// report to the user the failure and their locations in the document.
std::cout << reader.getFormatedErrorMessages()
<< "\n";
}
std::string encoding = root.get("encoding", "UTF-8" ).asString();
std::cout << encoding << "\n";
alive = false;
}
return 0;
}
#include "json/json.h"
#include <iostream>
#include <fstream>
int main(){
Json::Value root; // will contain the root value after parsing.
std::ifstream stream("testis.json", std::ifstream::binary);
stream >> root;
std::string encoding = root.get("encoding", "UTF-8" ).asString();
std::cout << encoding << "\n";
return 0;
}
Or more generally:
#include "json/json.h"
#include <iostream>
#include <fstream>
int main(){
Json::Value root; // will contain the root value after parsing.
Json::CharReaderBuilder builder;
std::ifstream test("testis.json", std::ifstream::binary);
std::string errs;
bool ok = Json::parseFromStream(builder, test, &root, &errs);
if ( !ok )
{
// report to the user the failure and their locations in the document.
std::cout << errs << "\n";
}
std::string encoding = root.get("encoding", "UTF-8" ).asString();
std::cout << encoding << "\n";
return 0;
}
http://open-source-parsers.github.io/jsoncpp-docs/doxygen/namespace_json.html
json cannot contain newlines. Try this instead:
{"encoding": "lab"}
You may need to ensure the file is saved without a final newline.
EDIT: Maybe your parser tolerates newlines, but some don't. Something to try if the other answers don't work
Related
I've written this code, which it get the repository and look for the files within. it aims to create binary files for each file found so as to write some data inside it later. However, the code is not running as expected. and the binary file are not created this the issue.
the directory has two images, and the output I get is as follows :
Creating bin files
C:\repo\1.bin
Error: failed to create file
Press <RETURN> to close this window...
I really do not know where I miss it. Any advice I'd be glad.
#include <vector>
#include <string>
#include <iostream> // for standard I/O
#include <string> // for strings
#include <iomanip> // for controlling float print precision
#include <sstream> // string to number conversion
#include <fstream>
using namespace std;
void getDir(string d, vector<string> & f)
{
FILE* pipe = NULL;
string pCmd = "dir /B /S " + string(d);
char buf[256];
if( NULL == (pipe = _popen(pCmd.c_str(),"rt")))
{
cout<<"Error"<<endl;
return;
}
while (!feof(pipe))
{
if(fgets(buf,256,pipe) != NULL)
{
f.push_back(string(buf));
}
}
_pclose(pipe);
}
void replaceExt(string& s, const string& newExt) {
string::size_type i = s.rfind('.', s.length());
if (i != string::npos) {
s.replace(i+1, newExt.length(), newExt);
}
}
using namespace std;
int main(int argc, char* argv[])
{
vector<string> files;
string path = "C:\\repo";
getDir(path, files);
vector<string>::const_iterator it = files.begin();
cout<<"Creating bin files "<<endl;
ofstream myOfstream;
while( it != files.end())
{
string fileName = (string) *it;
replaceExt(fileName, "bin");
cout << fileName << '\n';
std::stringstream ss;
ss << fileName << "" ;
myOfstream.open(ss.str(), fstream::binary);
if ( !myOfstream )
{
std::cerr << "Error: failed to create file " << '\n';
break;
}
myOfstream.close();
it++;
}
return 0;
}
First I have to say, if you directory you are looking for doesn't exists or is empty, the program gets locked, it would be nice to have that fixed if making a bigger program.
Then, for your case, I don't see whars the point of that stringstream, so I tried removing that, and changing it by a normal string, removing the last \n character you get from reading the filenames:
cout << fileName << '\n';
string ss = fileName.substr(0, fileName.size() - 1);
myOfstream.open(ss.c_str(), fstream::binary);
if (!myOfstream)
{
hope it helps
I found the issue bro, after debugging ;D
the problem is in the "newline", the string fileName has a "\n" at the end that's whats rise your error. Thus you have to erase it, I ve used this statement fileName.erase(std::remove(fileName.begin(), fileName.end(), '\n'), fileName.end());
and I included algorithm lib.
the working code is as follows :
#include <vector>
#include <string>
#include <iostream> // for standard I/O
#include <string> // for strings
#include <iomanip> // for controlling float print precision
#include <sstream> // string to number conversion
#include <fstream>
#include <algorithm>
using namespace std;
void getDir(string d, vector<string> & f)
{
FILE* pipe = NULL;
string pCmd = "dir /B /S " + string(d);
char buf[256];
if( NULL == (pipe = _popen(pCmd.c_str(),"rt")))
{
cout<<"Error"<<endl;
return;
}
while (!feof(pipe))
{
if(fgets(buf,256,pipe) != NULL)
{
f.push_back(string(buf));
}
}
_pclose(pipe);
}
void replaceExt(string& s, const string& newExt) {
string::size_type i = s.rfind('.', s.length());
if (i != string::npos) {
s.replace(i+1, newExt.length(), newExt);
}
}
using namespace std;
int main(int argc, char* argv[])
{
vector<string> files;
string path = "C:\\repo";
getDir(path, files);
vector<string>::const_iterator it = files.begin();
cout<<"Creating bin files "<<endl;
ofstream myOfstream;
while( it != files.end())
{
string fileName = (string) *it;
replaceExt(fileName, "bin");
cout << fileName << '\n';
fileName.erase(std::remove(fileName.begin(), fileName.end(), '\n'), fileName.end());
std::stringstream ss;
ss << fileName << "" ;
myOfstream.open(ss.str(), fstream::binary);
if ( !myOfstream )
{
std::cerr << "Error: failed to create file " << '\n';
break;
}
myOfstream.close();
it++;
}
return 0;
}
Lets start with that I have absolutely no experience with C++ , but I got this project to connect a POS with a verifone. We do not have the standard verifone SDK but something custom.
At fist I needed to prepair data to send to C++ and C++ will send it to the Verifone. This is where I am getting stuck, I have a .txt file, which I can read with C++ but now I need to split the data.
This is my current code:
#include "stdafx.h"
#include <sstream>
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
string file_get_contents(const char *filename)
{
ifstream in(filename);
if (in.fail())
{
cerr << "File not found: " << filename << endl;
return "";
}
std::stringstream buffer;
buffer << in.rdbuf();
in.close();
return buffer.str();
}
int main(int argc, char **argv)
{
vector<string> strings;
string contents = file_get_contents("C:/wamp/www/cmd/config.txt");
string s;
while (contents, s, '||') {
cout << s << endl;
strings.push_back(s);
}
cout << s; // ECHO CONTENTS
std::cin.ignore(); // pause
return 0;
}
With this code my console just stays blank, no data is being displayed.
The full string I am splitting is:
"notepad://amount=10320.53||session_id=7946548443287465/"
The result that I want is to get an array that uses "amount" and "session_id" as keys and their values as value.
What is the best way of achieving this?
I used the following code to actually display the string in my console which was working:
int main(int argc, char **argv)
{
string contents = file_get_contents("config.txt");
cout << contents; // ECHO CONTENTS
std::cin.ignore(); // pause
return 0;
}
This shows how to use a regex to extract the information you want, there are a lot of online resources on how to read files properly so I left that part out.
#include <iostream>
#include <regex>
#include <unordered_map>
#include <string>
int main(int argc, char **argv)
{
std::regex pattern("amount=([[:digit:]\\.]*)\\|\\|session_id=([[:digit:]]*)");
std::smatch results;
std::unordered_map<std::string, std::string> data;
std::string contents = "notepad://amount=10320.53||session_id=7946548443287465/";
//string contents = file_get_contents("C:/wamp/www/cmd/file.txt");
if(std::regex_search(contents, results, pattern))
{
data["amount"] = results[1];
data["session_id"] = results[2];
}
std::cout << "Amount: " << data["amount"] << std::endl;
std::cout << "Seesion ID: " << data["session_id"] << std::endl;
return 0;
}
My code below crashes(Debug Error! R6010 abort() has been called). Can you help me? I'd also would like to know how to initialize the json object from a string value.
Json::Value obj;
obj["test"] = 5;
obj["testsd"] = 655;
string c = obj.asString();
Hello it is pretty simple:
1 - You need a CPP JSON value object (Json::Value) to store your data
2 - Use a Json Reader (Json::Reader) to read a JSON String and parse into a JSON Object
3 - Do your Stuff :)
Here is a simple code to make those steps:
#include <stdio.h>
#include <jsoncpp/json/json.h>
#include <jsoncpp/json/reader.h>
#include <jsoncpp/json/writer.h>
#include <jsoncpp/json/value.h>
#include <string>
int main( int argc, const char* argv[] )
{
std::string strJson = "{\"mykey\" : \"myvalue\"}"; // need escape the quotes
Json::Value root;
Json::Reader reader;
bool parsingSuccessful = reader.parse( strJson.c_str(), root ); //parse process
if ( !parsingSuccessful )
{
std::cout << "Failed to parse"
<< reader.getFormattedErrorMessages();
return 0;
}
std::cout << root.get("mykey", "A Default Value if not exists" ).asString() << std::endl;
return 0;
}
To compile: g++ YourMainFile.cpp -o main -l jsoncpp
I hope it helps ;)
Json::Reader is deprecated. Use Json::CharReader and Json::CharReaderBuilder instead:
std::string strJson = R"({"foo": "bar"})";
Json::CharReaderBuilder builder;
Json::CharReader* reader = builder.newCharReader();
Json::Value json;
std::string errors;
bool parsingSuccessful = reader->parse(
strJson.c_str(),
strJson.c_str() + strJson.size(),
&json,
&errors
);
delete reader;
if (!parsingSuccessful) {
std::cout << "Failed to parse the JSON, errors:" << std::endl;
std::cout << errors << std::endl;
return;
}
std::cout << json.get("foo", "default value").asString() << std::endl;
Kudos to p-a-o-l-o for their answer here: Parsing JSON string with jsoncpp
You can avoid using Json::CharReader and Json::CharReaderBuilder by using stringstream instead.
#include <string>
#include <sstream>
#include "jsoncpp/json/json.h"
int main() {
std::string strJson = "{\"mykey\" : \"myvalue\"}";
Json::Value obj;
// read a JSON String
stringstream(strJson) >> obj;
// get string value
std::string value1 = obj["mykey"].asString();
// or to get a default value if it isn't set
std::string value2 = obj.get("mykey", "...").asString();
return 0;
}
I am writing a simple program to take in two files. The terminal command line looks like this.
./fileIO foo.code foo.encode
When it runs, the second file is not read in. When I enter
./fileIO foo.code foo.code
it works. I can't seem to figure out why the second one is not opening. Any ideas? Thanks!
#include <fstream>
#include <iostream>
#include <queue>
#include <iomanip>
#include <map>
#include <string>
#include <cassert>
using namespace std;
int main( int argc, char *argv[] )
{
// convert the C-style command line parameter to a C++-style string,
// so that we can do concatenation on it
assert( argc == 3 );
const string code = argv[1];
const string encode = argv[2];
string firstTextFile = code;
string secondTextFile = encode;
//manipulate the first infile
ifstream firstFile( firstTextFile.c_str(), ios::in );
if( !firstFile )
{
cerr << "Cannot open text file for input" << endl;
return 1;
}
string lineIn;
string codeSubstring;
string hexSubstring;
while( getline( firstFile, lineIn ) )
{
hexSubstring = lineIn.substr(0, 2);
codeSubstring = lineIn.substr(4, lineIn.length() );
cout << hexSubstring << ", " << codeSubstring << endl;
}
//manipulate the second infile
ifstream secondFile( secondTextFile.c_str(), ios::in );
if( !secondFile )
{
cerr << "Cannot open text file for input" << endl;
return 1;
}
char characterIn;
while( secondFile.get( characterIn ) )
{
cout << characterIn << endl;
}
return 0;
}
One thing you might want to try is adding the close() call as is standard procedure after you're done using files. Sometimes issues arise with re-opening files if they were not closed properly in a previous run.
firstFile.close();
secondFile.close();
Also, you may try restarting the computer if there is some lingering file handle that hasn't been released.
I want to create a small code in C++ with the same functionality as "tail-f": watch for new lines in a text file and show them in the standard output.
The idea is to have a thread that monitors the file
Is there an easy way to do it without opening and closing the file each time?
Have a look at inotify on Linux or kqueue on Mac OS.
Inotify is Linux kernel subsystem that allows you to subscribe for events on files and it will report to your application when the even happened on your file.
Just keep reading the file. If the read fails, do nothing. There's no need to repeatedly open and close it. However, you will find it much more efficient to use operating system specific features to monitor the file, should your OS provide them.
Same as in https://stackoverflow.com/a/7514051/44729 except that the code below uses getline instead of getc and doesn't skip new lines
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
using namespace std;
static int last_position=0;
// read file untill new line
// save position
int find_new_text(ifstream &infile) {
infile.seekg(0,ios::end);
int filesize = infile.tellg();
// check if the new file started
if(filesize < last_position){
last_position=0;
}
// read file from last position untill new line is found
for(int n=last_position;n<filesize;n++) {
infile.seekg( last_position,ios::beg);
char test[256];
infile.getline(test, 256);
last_position = infile.tellg();
cout << "Char: " << test <<"Last position " << last_position<< endl;
// end of file
if(filesize == last_position){
return filesize;
}
}
return 0;
}
int main() {
for(;;) {
std::ifstream infile("filename");
int current_position = find_new_text(infile);
sleep(1);
}
}
I read this in one of Perl manuals, but it is easily translated into standard C, which, in turn, can be translated to istreams.
seek FILEHANDLE,POSITION,WHENCE
Sets FILEHANDLE's position, just like the "fseek" call of
"stdio".
<...>
A WHENCE of 1 ("SEEK_CUR") is useful for not moving the file
position:
seek(TEST,0,1);
This is also useful for applications emulating "tail -f". Once
you hit EOF on your read, and then sleep for a while, you might
have to stick in a seek() to reset things. The "seek" doesn't
change the current position, but it does clear the end-of-file
condition on the handle, so that the next "<FILE>" makes Perl
try again to read something. We hope.
As far as I remember, fseek is called iostream::seekg. So you should basically do the same: seek to the end of the file, then sleep and seek again with ios_base::cur flag to update end-of-file and read some more data.
Instead of sleeping, you may use inotify, as suggested in the other answer, to sleep (block while reading from an emulated file, actually) exactly until the file is updated/closed. But that's Linux-specific, and is not standard C++.
I needed to implement this too, I just wrote a quick hack in standard C++. The hack searches for the last 0x0A (linefeed character) in a file and outputs all data following that linefeed when the last linefeed value becomes a larger value. The code is here:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int find_last_linefeed(ifstream &infile) {
infile.seekg(0,ios::end);
int filesize = infile.tellg();
for(int n=1;n<filesize;n++) {
infile.seekg(filesize-n-1,ios::beg);
char c;
infile.get(c);
if(c == 0x0A) return infile.tellg();
}
}
int main() {
int last_position=-1;
for(;;) {
ifstream infile("testfile");
int position = find_last_linefeed(infile);
if(position > last_position) {
infile.seekg(position,ios::beg);
string in;
infile >> in;
cout << in << endl;
}
last_position=position;
sleep(1);
}
}
#include <iostream>
#include <fstream>
#include <string>
#include <list>
#include <sys/stat.h>
#include <stdlib.h>
#define debug 0
class MyTail
{
private:
std::list<std::string> mLastNLine;
const int mNoOfLines;
std::ifstream mIn;
public:
explicit MyTail(int pNoOfLines):mNoOfLines(pNoOfLines) {}
const int getNoOfLines() {return mNoOfLines; }
void getLastNLines();
void printLastNLines();
void tailF(const char* filename);
};
void MyTail::getLastNLines()
{
if (debug) std::cout << "In: getLastNLines()" << std::endl;
mIn.seekg(-1,std::ios::end);
int pos=mIn.tellg();
int count = 1;
//Get file pointer to point to bottom up mNoOfLines.
for(int i=0;i<pos;i++)
{
if (mIn.get() == '\n')
if (count++ > mNoOfLines)
break;
mIn.seekg(-2,std::ios::cur);
}
//Start copying bottom mNoOfLines string into list to avoid I/O calls to print lines
std::string line;
while(getline(mIn,line)) {
int data_Size = mLastNLine.size();
if(data_Size >= mNoOfLines) {
mLastNLine.pop_front();
}
mLastNLine.push_back(line);
}
if (debug) std::cout << "Out: getLastNLines()" << std::endl;
}
void MyTail::printLastNLines()
{
for (std::list<std::string>::iterator i = mLastNLine.begin(); i != mLastNLine.end(); ++i)
std::cout << *i << std::endl;
}
void MyTail::tailF(const char* filename)
{
if (debug) std::cout << "In: TailF()" << std::endl;
int date = 0;
while (true) {
struct stat st;
stat (filename, &st);
int newdate = st.st_mtime;
if (newdate != date){
system("#cls||clear");
std::cout << "Print last " << getNoOfLines() << " Lines: \n";
mIn.open(filename);
date = newdate;
getLastNLines();
mIn.close();
printLastNLines();
}
}
if (debug) std::cout << "Out: TailF()" << std::endl;
}
int main(int argc, char **argv)
{
if(argc==1) {
std::cout << "No Extra Command Line Argument Passed Other Than Program Name\n";
return 0;
}
if(argc>=2) {
MyTail t1(10);
t1.tailF(argv[1]);
}
return 0;
}