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

fwrite()写入文件末尾出现垃圾数据,PostgreSQL执行SQL文件异常排查

问题分析与解决方案

核心问题:文本模式导致字节数不匹配

你用"r"(文本模式)打开输入文件,在Windows系统下,文件里的\r\n会被自动转换为\n,这使得fread实际读取的字节数比stat获取的st_size要少。此时dbschema数组中,从实际读取的字节位置到buf.st_size之间的内存是未初始化的垃圾数据,之后你用fwrite写入了buf.st_size+1字节(包含这些垃圾数据),直接导致输出文件多出大量无效内容。

其他潜在问题

  • 未校验fread的返回值,无法确认是否读取了预期的全部字节;
  • 未判断输出文件tbout.sql的打开结果,如果打开失败,后续的写操作都会出错;
  • 未校验stat函数的返回值,若获取文件信息失败,后续逻辑全是错误的。

修正后的代码

struct stat buf;
if (stat("treebase.sql", &buf) != 0) {
    wxMessageBox(_("Failed to get file info"));
    return;
}

char* dbschema = new (std::nothrow) char[buf.st_size + 1];
if (!dbschema) {
    wxMessageBox(_("Not Enough memory"));
    return;
}

FILE* fl = fopen("treebase.sql", "rb"); // 用二进制模式打开,避免换行转换
if (!fl) {
    wxMessageBox(_("Can not open treebase.sql"));
    delete[] dbschema;        
    return;
}

FILE* fo = fopen("tbout.sql", "wb"); // 二进制模式写入,保证字节一致
if (!fo) {
    wxMessageBox(_("Can not open tbout.sql"));
    fclose(fl);
    delete[] dbschema;        
    return;
}

size_t read_bytes = fread(dbschema, sizeof(char), buf.st_size, fl);
fclose(fl);

// 验证是否读取了完整文件
if (read_bytes != buf.st_size) {
    wxMessageBox(_("Failed to read entire file"));
    fclose(fo);
    delete[] dbschema;        
    return;
}

dbschema[buf.st_size] = '\0';
// 只写入文件实际大小的内容,不需要额外多写一个字节
fwrite(dbschema, sizeof(char), buf.st_size, fo);
fflush(fo);
fclose(fo);

delete[] dbschema;

关键修正点

  1. 改用二进制模式"rb"和"wb"打开文件,彻底避免换行符转换带来的字节数偏差;
  2. 增加所有关键IO函数的返回值校验,提前拦截异常情况;
  3. 写入文件时只写原文件大小的内容,不再包含未初始化的垃圾数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 00:36:27