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
相关产品推荐
相关产品推荐

