2016-09-11 7 views
4

Я хотел бы обновить существующий файл json.Чтение и запись в тот же файл fstream

Это пример файла JSON:

{ 
    "Foo": 51.32, 
    "Number": 100, 
    "Test": "Test1" 
} 

Бревна из программы:

Operation successfully performed 
100 
"Test1" 
51.32 
46.32 
Done 

Похоже Everythink работает, как ожидалось ...

Если изменить fstream в ifstream для чтения и позже, чтобы написать, что он работает ...

Я пробовал использовать отладчик и как Я вижу, что у меня неправильные данные в объекте basic_ostream ... но я не знаю, почему, я использую данные из строки с исправленными (обновленными данными). Любая идея, что не так :-)?

+0

Правильный инструмент для решения таких проблем является ваш отладчик. Перед тем, как просить о переполнении стека, вы должны пропустить свой код по очереди *. Для получения дополнительной информации, пожалуйста, прочтите [Как отлаживать небольшие программы (Эрик Липперт)] (https://ericlippert.com/2014/03/05/how-to-debug-small-programs/). Как минимум, вы должны \ [изменить] ваш вопрос, чтобы включить пример [Минимальный, полный и проверенный] (http://stackoverflow.com/help/mcve), который воспроизводит вашу проблему, а также замечания, сделанные вами в отладчик. –

+1

Вам нужно будет использовать 'clear()' и, скорее всего, 'seek()' перед тем, как переписать его содержимое. Обратите внимание, что если новое содержимое короче существующего содержимого, это не приведет к усечению размера файла, и в конце вы получите конечный мусор. –

+1

Сообщение обновлено :-) – user3490777

ответ

1

У вас здесь несколько проблем.

Сначала команда json json_data(fs); считывает в конец файла значение EOF. Поток перестанет работать до тех пор, пока этот флаг не будет очищен.

Во-вторых, указатель файла находится в конце файла. Если вы хотите перезапись файл, который нужно переместить обратно в начало снова:

if (fs.is_open()) 
{ 
    json json_data(fs); // reads to end of file 
    fs.clear(); // clear flag 
    fs.seekg(0); // move to beginning 

К сожалению, это еще не все исправить, потому что, если файл вы пишете Спинка меньше, чем тот, который вы читали там будут какие-то старые данные, помеченных к концу новых данных:

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 файла:

{ 
    "Foo": 4.32, // this number is smaller than before 
    "Number": 100, 
    "Test": "Test1" 
}} // whoops trailing character from previous data!! 

В этой ситуации я бы просто открыл один файл для чтения, затем другой для записи, его гораздо меньше подвержен ошибкам и выразил намерение перезаписать все.

Что-то вроде:

#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; 
} 
+0

Спасибо! Поэтому я могу использовать вторую версию моей программы. Теперь я понимаю, почему это не сработало. Благодаря ! – user3490777