You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++服务器写入JSON文件后VS保存异常及乱码问题求助

问题原因分析
  • 前端请求格式错误:你用axios.post发送{ api_data }时,axios默认会把数据编码为application/x-www-form-urlencoded格式(类似api_data=xxx),而非纯JSON字符串。后端收到的不是干净的JSON,而是包含表单字段的HTTP请求内容。
  • HTTP请求未正确解析:你的C++服务器基于winsock直接接收字节流,但没有解析HTTP请求的结构——实际收到的数据流包含HTTP请求头(如POST /user_data.json HTTP/1.1等内容)和body,你直接对整个流做find("{")提取JSON,可能误取到请求头中的{,或混入请求末尾的二进制垃圾数据,导致写入的文件包含无效内容。
  • 文件编码与写入模式问题:Windows下默认std::ofstream使用本地编码(如GBK)写入,而JSON是UTF-8编码,编码不匹配导致Visual Studio加载时无法正确解析,出现Unicode替换字符;同时未用二进制模式写入,可能导致换行符等字符被自动转换,破坏JSON结构。
解决方法

前端调整(确保发送纯JSON)

修改axios.post的调用方式,直接发送JSON字符串并指定请求头:

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)

    // 直接发送JSON字符串,指定Content-Type为application/json
    await axios.post('http://127.0.0.1:5174/user_data.json', api_data, {
      headers: { 'Content-Type': 'application/json' }
    })
    console.log('Data saved on server:', api_data)
  } catch (error) {
    console.error('Error fetching data: ', error)
  }
}

C++后端调整

1. 正确解析HTTP请求的Body部分

基于winsock接收数据后,需要先解析HTTP请求,分离出请求头和body:

  • 读取到的数据流以\r\n\r\n为分隔符,前面是请求头,后面是body内容。
  • 从请求头中获取Content-Length字段,确定body的长度,只读取对应长度的内容作为JSON数据,避免混入无效内容。

示例解析逻辑(简化版):

std::string extractHttpBody(const std::string& rawRequest) {
    size_t headerEnd = rawRequest.find("\r\n\r\n");
    if (headerEnd == std::string::npos) {
        return "";
    }
    // 提取body部分
    std::string body = rawRequest.substr(headerEnd + 4);
    
    // 可选:验证Content-Type是否为application/json
    size_t contentTypePos = rawRequest.find("Content-Type: application/json");
    if (contentTypePos == std::string::npos) {
        std::cerr << "Invalid request content type" << std::endl;
        return "";
    }
    
    return body;
}

调用时,先提取body再传入writeData:

// 假设rawRequest是从winsock接收的完整HTTP请求数据
std::string body = extractHttpBody(rawRequest);
if (!body.empty()) {
    writeData(body);
}

2. 修复文件写入逻辑

  • 用std::ios::trunc模式自动清空文件,无需提前remove。
  • 以二进制模式写入,保留UTF-8编码的原始字节,避免编码转换:
void TcpServer::writeData(const std::string& jsonData)
{
    // 直接用trunc模式清空文件,无需remove
    std::ofstream file(user_data_path, std::ios::out | std::ios::binary | std::ios::trunc);
    if (file.is_open())
    {
        // 直接写入原始字节,确保UTF-8编码不被转换
        file.write(jsonData.c_str(), jsonData.size());
        file.close();
        std::cout << "Data saved to user_data.json" << std::endl;
    }
    else
    {
        std::cerr << "Failed to open file for writing." << std::endl;
    }
}

3. 移除错误的JSON提取逻辑

因为已经通过HTTP解析拿到了纯JSON的body,无需再用find("{")截取,直接写入即可。

内容的提问来源于stack exchange,提问作者genjutsu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 03:26:16