I would like to update existing json file.
This is example json file:
{
"Foo": 51.32,
"Number": 100,
"Test": "Test1"
}
Logs from program:
Operation successfully performed
100
"Test1"
51.32
46.32
Done
Looks like everythink works as expected...
If I change fstream to ifstream to read and later ofstream to write it's working...
I tried use debugger and as I see I have wrong data in basic_ostream object... but I dont know why, I use data from string with corrected (updated data). Any idea what is wrong :-) ?
You have a few problems here.
First the command json json_data(fs);
reads to the end of the file setting the EOF
flag. The stream will stop working until that flag is cleared.
Second the file pointer is at the end of the file. If you want to overwrite the file you need to move back to the beginning again:
if (fs.is_open())
{
json json_data(fs); // reads to end of file
fs.clear(); // clear flag
fs.seekg(0); // move to beginning
Unfortunately that still doesn't fix everything because if the file you write back is smaller than the one you read in there will be some of the old data tagged to the end of the new data:
std::cout << "Operation successfully performed\n";
std::cout << json_data.at("Number") << std::endl;
std::cout << json_data.at("Test") << std::endl;
std::cout << json_data.at("Foo") << std::endl;
json_data.at("Foo") = 4.32; // what if new data is smaller?
Json file:
{
"Foo": 4.32, // this number is smaller than before
"Number": 100,
"Test": "Test1"
}} // whoops trailing character from previous data!!
In this situation I would simply open one file for reading then another for writing, its much less error prone and expresses the intention to overwrite everything.
Something like:
#include "json.hpp"
#include <iostream>
#include <fstream>
#include <string>
using json = nlohmann::json;
void readAndWriteDataToFile(std::string fileName) {
json json_data;
// restrict scope of file object (auto-closing raii)
if(auto fs = std::ifstream(fileName))
{
json_data = json::parse(fs);
std::cout << "Operation successfully performed\n";
std::cout << json_data.at("Number") << std::endl;
std::cout << json_data.at("Test") << std::endl;
std::cout << json_data.at("Foo") << std::endl;
}
else
{
throw std::runtime_error(std::strerror(errno));
}
json_data.at("Foo") = 4.32;
std::cout << json_data.at("Foo") << std::endl;
std::string json_content = json_data.dump(3);
if(auto fs = std::ofstream(fileName))
{
fs.write(json_content.data(), json_content.size());
std::cout << "Done" << std::endl;
}
else
{
throw std::runtime_error(std::strerror(errno));
}
}
int main()
{
try
{
std::string fileName = "C:/new/json1.json";
readAndWriteDataToFile(fileName);
}
catch(std::exception const& e)
{
std::cerr << e.what() << '\n';
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}