C++ (или Visual Studio) при сохранении файла не сохранит исходное содержимое файла

Я новичок в серверной разработке, но знаю много вещей из фронтенд-разработки.

Моя проблема:

1. Со стороны клиента (приложение React.js) строка JSON отправляется (POST-запрос) на C++-сервер:

  const handleFetchData = async () => {
    try {
      dispatch(setRepoUrl(inputUrl))
      const urlParts = inputUrl.split('/')
      const username = urlParts[3]
      const repo = urlParts[4]
      const response = await axios.get(
        `https://api.github.com/repos/${username}/${repo}/issues`
      )
      dispatch(setIssues(response.data))

      const api_data = JSON.stringify(response.data)

      await axios.post('http://127.0.0.1:5174/user_data.json', { api_data })
      console.info('Data saved on server:', api_data)
    } catch (error) {
      console.error('Error fetching data: ', error)
    }
  }

2. Сервер C++ обрабатывает этот запрос и записывает его в файл, но сначала удаляет существующие данные в файле .json:

    void TcpServer::writeData(const std::string& data)
    {
        remove(user_data_path);
        size_t start = data.find("{");
        if (start == std::string::npos)
        {
            std::cerr << "JSON data not found in the input string.\n\n" << std::endl;
            return;
        }

        std::string jsonData = data.substr(start);

        std::ofstream file(user_data_path, std::ios::out);
        if (file.is_open())
        {
            file << jsonData << std::endl;
            file.close();
            std::cout << "Data saved to user_data.json\n\n" << std::endl;
        }
        else
        {
            std::cerr << "Failed to open file for writing.\n\n" << std::endl;
        }
    }

3. После записи строки JSON в файл .json приложение Visual Studio отображает окно со следующим сообщением об ошибке:
Загрузка файла
Некоторые байты были заменены символом замены Unicode при загрузке файла
При сохранении файла исходное содержимое файла не сохраняется

4. После этого некоторые символы в строке JSON преобразуются в это - (\r\n\t\t<Ex1 InternalRef = {ref}>\r\n\t\t\t{дети}\r\n \t\t</Ex1>\r\n\t);\r\n});���������������������������� ������7#�

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

P.S. Этот сервер написан для Windows (#include <winsock.h>).
Не хочу вызывать недовольство в комментариях типа "почему он пишет сервер на C++, а не на node.js и т.п."
Я младший фронтенд-разработчик, и мне просто нравится C++, поэтому я выбрал этот язык.
Спасибо за понимание, надеюсь на вашу помощь.

Я долго искал решение проблемы и просто пришел к выводу написать пост по Stack Overflow, поэтому вариантов решения этой проблемы у меня нет.

С опубликованным вами кодом C++ проблем нет — он получает строку, открывает файл, записывает строку в файл. Что содержит эта строка — это другая история. Что вам нужно сделать, так это использовать отладчик и посмотреть, что именно data содержит при вызове writeData. Слишком поздно видеть, что делает Visual Studio. Мой хрустальный шар говорит мне, что вы создали std::string из data, не используя фактическую длину данных, т. е. std::string data = <whatever>; вместо std::string data(whatever, length_of_whatever);.

PaulMcKenzie 30.03.2024 17:19
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
65
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема заключалась в размере буфера, который составлял 30720 байт.

const int BUFFER_SIZE = 500000000;

Я только что изменил размер, который составляет примерно 500 МБ, и теперь выбираю их из кучи.

char* buffer = new char[BUFFER_SIZE];

Здесь используется буфер, я просто беру из него данные и затем передаю их в качестве аргумента функции, которая записывает эти данные в файл:

void TcpServer::startListen()
{
   if (listen(m_socket, 20) < 0)
   {
       exitWithError("Socket listen failed");
   }

   std::ostringstream ss;
   ss << "\n*** Listening on ADDRESS: " << inet_ntoa(m_socketAddress.sin_addr) << " PORT: " << ntohs(m_socketAddress.sin_port) << " ***\n\n";
   log(ss.str());

   int bytesReceived;

   while (true)
   {
       log("====== Waiting for a new connection ======\n\n\n");
       acceptConnection(m_new_socket);

       char* buffer = new char[BUFFER_SIZE];

       bytesReceived = recv(m_new_socket, buffer, BUFFER_SIZE, 0);
       if (bytesReceived < 0)
       {
           exitWithError("Failed to receive bytes from client socket connection");
       }

       std::ostringstream ss;
       ss << "------ Received Request from client ------\n\n";
       log(ss.str());

       sendResponse();

       std::string requestData(buffer);
       handleRequest(requestData);

       delete[] buffer;
       closesocket(m_new_socket);
   }

}

Данные записывались в файл по мере необходимости, поскольку размер буфера не позволял вместить большие данные.

if (bytesReceived < 0) -- Если это произойдет, у вас произойдет утечка памяти. На самом деле, у вас есть утечка памяти, если по какой-либо причине функция startListen выдает исключение и/или не достигает строки delete[]. Используйте правильный класс RAII, который самоочищается. Вместо char* buffer = new char[BUFFER_SIZE]; должно быть std::vector<char> buffer(BUFFER_SIZE);, а затем bytesReceived = recv(m_new_socket, buffer.data(), buffer.size(), 0);. Тогда вызов delete[] можно будет удалить.
PaulMcKenzie 01.04.2024 17:04

Другие вопросы по теме