如何实现类似十六进制编辑器的文件写入,避免生成额外数据?
问题:十六进制编辑器替换函数写入额外数据的解决方法
我想为项目制作一个小型十六进制编辑器,编写了如下用于替换原代码的函数:
int replace(FILE *binaryFile, long offset, unsigned char *replaced, int length) { if (binaryFile != NULL) { for (int i = 0; i < length; i++) { fseek(binaryFile, offset + i, SEEK_SET); fwrite(&replaced[i], sizeof(replaced), 1, binaryFile); } fclose(binaryFile); return 1; } else return -1; }
测试代码如下,向地址0x0写入数据:
unsigned char code[] = "\x1E\xFF\x2F\xE1";
得到的十六进制结果为:
1e ff 2f e1 00 10 2b 35 ff fe 07 00
但我不需要E1之后的额外数据(00 10 2b 35 ff fe 07 00),请问如何修改函数以仅存储传入的指定数据?
问题原因
原函数的核心错误在于fwrite的第二个参数:sizeof(replaced)是指针类型的字节数(32位系统为4,64位为8),而非单个unsigned char的大小(1字节)。这导致每次调用fwrite都会从replaced[i]开始写入指针大小的字节,越界读取了数组后方的栈内存数据,最终写入了额外内容。此外,循环逐个字节写入的逻辑既低效又容易出错。
修改后的函数
#include <stdio.h> // 若需截断文件,根据系统选择包含头文件: // POSIX系统(Linux/macOS):#include <unistd.h> // Windows系统:#include <io.h> int replace(FILE *binaryFile, long offset, unsigned char *replaced, int length) { if (binaryFile == NULL) { return -1; } // 定位到目标偏移位置 if (fseek(binaryFile, offset, SEEK_SET) != 0) { fclose(binaryFile); return -1; } // 一次性写入指定长度的数据 size_t written = fwrite(replaced, sizeof(unsigned char), length, binaryFile); if (written != length) { fclose(binaryFile); return -1; } // 可选:若需截断文件(仅保留写入的内容,删除原文件后续数据),取消对应注释 // POSIX系统: // if (ftruncate(fileno(binaryFile), offset + length) != 0) { // fclose(binaryFile); // return -1; // } // Windows系统: // if (_chsize_s(_fileno(binaryFile), offset + length) != 0) { // fclose(binaryFile); // return -1; // } fclose(binaryFile); return 1; }
关键说明
- 修复写入参数:将
sizeof(replaced)改为sizeof(unsigned char)(或直接写1),确保每次写入的是单个字节的数据,避免越界读取。 - 优化写入逻辑:通过一次
fseek定位后,一次性写入全部数据,提升效率且避免循环错误。 - 截断文件选项:如果你的需求是让文件仅包含传入的指定数据(删除原文件中偏移+长度之后的内容),则根据操作系统启用对应的截断代码;若只需覆盖指定位置内容、保留原文件其他部分,则无需启用。
内容的提问来源于stack exchange,提问作者mr ice
相关产品推荐
相关产品推荐

