Используйте fs, чтобы изменить одну часть файла json, а не перезаписывать все - PullRequest
0 голосов
/ 02 мая 2020

Для бота Discord у меня есть команда, которая отображает информацию для наших сеансов DnD:

pictured.

Данные хранятся в dndinfo . json файл выглядит следующим образом:

{"time":"**18:00 UK time**",
"date":"**14/05/20**",
"dm":"**Mannion**",
"prime":"Playing",
"smurphy":"Playing",
"calle":"Playing",
"smardon":"Playing",
"james":"Playing",
"mannion":"DMing",
"dex":"Playing",
"module":"Hoard of the Dragon Queen"}

Я хочу, чтобы пользователи могли выполнять команды, такие как '! Te time 17:00', которые обновят время соответствующим образом.

В настоящее время я работаю с этим кодом:

const Discord = module.require('discord.js');
const fs = require('fs');
const dndinfo = require ('../../dndinfo.json');

module.exports = {
    name: 'test',
    aliases: ['te'],
    category: 'dnd',
    description: 'Updates DnD info',
    usage: '!te',
    run: async (client, message, args) => {

        const time = dndinfo.time;
        let editMessage = message.content.slice(9);

        if (message.content.toLowerCase().includes('time')) {

            fs.readFile('dndinfo.json', function(err, data) {
                console.log(time);
                fs.writeFile('dndinfo.json', JSON.stringify(editMessage, null, 2), (err) => {
                    if (err) console.error;
                    message.channel.send ('message written');

                });
            });
        }
    },
};

Когда я запускаю команду '! Te time 17:00', весь файл dndinfo. json заменяется на:

"17:00"

Я понимаю, что это потому, что я использую fs.writeFile, но я не уверен, как указать только «время» и обновил ли это?

Ответы [ 3 ]

0 голосов
/ 02 мая 2020

Нет практических способов обновить только кусок JSON в файле. Это просто не тот формат или формат на диске, который делает это практичным.

Обычный механизм обновления содержимого файла - просто записать всю структуру JSON с вашими изменениями на месте, заменяя исходное содержимое файла с новым содержимым. Если у вас еще нет всего содержимого, необходимого для этого, вы сначала прочитаете содержимое файла, внесете изменения, а затем запишите его.

Вот функция, которая читает его в анализирует JSON до Javascript объекта, модифицирует этот объект, преобразует обратно в JSON и записывает его.

const fsp = require('fs').promises;

async function udpateTimeInFile(time) {
    try {
        let data = await fsp.readFile('dndinfo.json');
        let obj = JSON.parse(data);

        // set whatever property or properties in the object that you are trying to change
        obj.time = time;

        await fsp.writeFile('dndinfo.json', JSON.stringify(obj);
        message.channel.send('message written');
     } catch(e) {
        // error handling here
        console.log(e);
        message.channel.send('error sending message');
        throw e;      // make sure caller can see the message
     }
}
0 голосов
/ 02 мая 2020

Из-за того, как работают файлы, единственный способ изменить часть файла - это заменить его содержимое содержимым точно такого же размера. Кроме того, ваша файловая система, вероятно, записывает данные на контроллер диска в блоках по 8 КБ, поэтому / point / делать это не нужно, за исключением очень исключительных случаев.

Помимо перезаписи всего файла, вам также необходимо Подумайте о том, что произойдет, если файл станет короче, или если на компьютере одновременно выполняются другие операции чтения (или записи!) файла.

Очень распространенным общим решением для этой группы проблем является запишите новый файл с новым именем в том же каталоге и переименуйте его поверх старого. Это означает, что другие процессы, читающие ваш файл, получат либо новый файл, либо старый файл, что почти всегда предпочтительнее решения «пополам».

Забавно, что этот вопрос возник сегодня, когда я случилось, чтобы написать именно эту процедуру ранее сегодня, чтобы сохранить историю REPL для моего отладчика. Если вы хотите прочитать полную [но слегка проверенную] реализацию, взгляните на

https://github.com/wesgarland/niim/blob/cfb64356c4e5a9394ba2e2b0e82b2f3bf2ba0305/lib/niim.js#L373 и https://github.com/wesgarland/niim/blob/cfb64356c4e5a9394ba2e2b0e82b2f3bf2ba0305/lib/niim.js#L459

Они слишком велики для комментария о переполнении стека, но я предоставил статическую c ссылку на указанную c версию файла, и она должна длиться несколько лет.

0 голосов
/ 02 мая 2020

Вместо записи JSON.stringify(editMessage, null, 2) в JSON вы можете сначала отредактировать его содержимое.

Вы можете заменить содержимое вашего файла методом data.replace().

Вы можете обратиться к этому ответу для полного охвата: { ссылка }

...