【问题标题】:Missing values when reading using fread in a binary file在二进制文件中使用 fread 读取时缺少值
【发布时间】:2020-07-11 15:40:41
【问题描述】:

我有一个二进制文件,我在其中编写包含以下字段的结构

typedef struct super_bloque{
    size_t s_filesystem_type;
    size_t s_inodes_count;
    size_t s_blocks_count;
    size_t s_free_blocks_count;
    size_t s_free_inodes_count;
    time_t s_mtime;
    time_t s_umtime;
    size_t s_mnt_count;
    size_t s_magic;
    size_t s_inode_size;
    size_t s_block_size;
    size_t s_first_ino;
    size_t s_first_blo;
    size_t s_bm_inode_start;
    size_t s_bm_block_start;
    size_t s_inode_start;
    size_t s_block_start;    
}SUPER_BLOQUE;

我有以下方法在文件中写入结构

void Operacion::formatear_ext2(char type, size_t part_start, size_t part_size, FILE *disco){
    MBR mbr;
    fseek(disco, 0, SEEK_SET);
    fread(&mbr, sizeof(mbr), 1, disco);
    size_t n = (size_t)floor((part_size - sizeof(SUPER_BLOQUE)) / (sizeof(I_NODO) + 3 * sizeof(BLOQUE_ARCHIVO) + 4));
    printf("n = %zu\n", n);
    SUPER_BLOQUE super_block;
    memset(&super_block, 0, sizeof(SUPER_BLOQUE));
    super_block.s_filesystem_type = (size_t)2;
    super_block.s_inodes_count = n;
    super_block.s_blocks_count = (size_t)3 * n;
    super_block.s_free_blocks_count = (size_t)3 * n;
    super_block.s_free_inodes_count = n;
    super_block.s_mtime = time(0);
    super_block.s_umtime = time(0);
    super_block.s_mnt_count = 1;
    super_block.s_magic = 0xEF53;
    super_block.s_inode_size = sizeof(I_NODO);
    super_block.s_block_size = sizeof(BLOQUE_ARCHIVO);
    super_block.s_first_ino = 0;
    super_block.s_first_blo = 0;
    super_block.s_bm_inode_start = part_start + sizeof(SUPER_BLOQUE);
    super_block.s_bm_block_start = part_start + sizeof(SUPER_BLOQUE) + n;
    super_block.s_inode_start = part_start + sizeof(SUPER_BLOQUE) + n + 3 * n;
    super_block.s_block_start = part_start + sizeof(SUPER_BLOQUE) + n + 3 * n + n * sizeof(I_NODO);
    fseek(disco, part_start, SEEK_SET);
    fwrite(&super_block, sizeof(SUPER_BLOQUE), 1, disco);

    for(size_t i = 0; i < super_block.s_inodes_count; i++){
       fseek(disco, super_block.s_first_ino + i, SEEK_SET);
       fwrite("0", 1, 1, disco);
    }
    for(size_t i = 0; i < super_block.s_blocks_count; i++){ 
       fseek(disco, super_block.s_first_blo + i, SEEK_SET);
       fwrite("0", 1, 1, disco);
    }
    if(type == '1'){ 
        size_t tam_ino_bloq = super_block.s_block_start + n * sizeof(BLOQUE_ARCHIVO); 
       for(size_t i = super_block.s_inode_start; i < tam_ino_bloq; i++){
        fseek(disco, i, SEEK_SET);
        fwrite("\0", 1, 1, disco);
      }
   }

然后我读取磁盘内部的结构来检查数据是否存储正确

fseek(disco, part_start, SEEK_SET);
    fread(&tmp_sb, sizeof(SUPER_BLOQUE), 1, disco);
    printf("**************************** SUPERBLOQUE ****************************\n");
    printf("fs: %zu\n", tmp_sb.s_filesystem_type);
    printf("i-nodes count : %zu\n", tmp_sb.s_inodes_count);
    printf("blocks count : %zu\n", tmp_sb.s_blocks_count);
    printf("free blocks count: %zu\n", tmp_sb.s_free_blocks_count);
    printf("free i-nodes count: %zu\n", tmp_sb.s_free_inodes_count);
    printf("i-nodes size: %zu\n", tmp_sb.s_inode_size);
    printf("blocks size: %zu\n", tmp_sb.s_block_size);
    printf("first ino: %zu\n", tmp_sb.s_first_ino);
    printf("first blo: %zu\n", tmp_sb.s_first_blo);
    printf("bm i-node start: %zu\n", tmp_sb.s_bm_inode_start);
    printf("bm block start: %zu\n", tmp_sb.s_bm_block_start);
    printf("i-node start: %zu\n", tmp_sb.s_inode_start);
    printf("block start: %zu\n", tmp_sb.s_block_start);
    printf("***********************************************************************");
} // Finish the method

struct在写的时候有如下信息

fs: 2
i-nodes count : 64
blocks count : 192
free blocks count: 192
free i-nodes count: 64
i-nodes size: 120
blocks size: 64
first ino: 0
first blo: 0
bm i-node start: 272
bm block start: 336
i-node start: 528
block start: 8208

但是当我阅读信息时,我得到以下结果,信息已经丢失

fs: 3472328296227680304
i-nodes count : 3472328296227680304
blocks count : 3472328296227680304
free blocks count: 3472328296227680304
free i-nodes count: 3472328296227680304
i-nodes size: 120
blocks size: 64
first ino: 0
first blo: 0
bm i-node start: 272
bm block start: 336
i-node start: 528
block start: 8208

前五个字段包含垃圾。为什么会这样?感谢您的帮助

注意:我已经添加了该方法的所有行。我正在使用 Ubuntu 发行版。要打开文件,我使用以下说明

FILE *disco;
disco = fopen(path, "r+b");
if(disco){                        
  if(cmd.fs == '2'){
    formatear_ext2(cmd.type, meta->part_start, meta->part_size, disco);
  }else if(cmd.fs == '3'){
    formatear_ext3(cmd.type, meta->part_start, meta->part_size, disco);                
  }else{
    printf("ERROR\n");
  }
}else{
  printf("ERROR: No se pudo acceder al dispositivo.\n");
}

【问题讨论】:

  • 乍一看,我看不出有什么问题,但您显示的代码中有一个错误的“partición”,这让我认为这实际上不是真正的代码。您也没有进行任何错误检查。请创建一个minimal reproducible example
  • 你能放更多的代码让其他人重现吗?
  • 您在 Windows 上吗?您是否将文件作为二进制文件打开?如果不是,操作系统将删除它猜测为回车符 ('\r') 的字节,这在您的情况下当然是无意义的,必须加以防止。
  • 这也是我的想法,你必须以二进制模式打开文件。 "wb""rb" 在您致电 fopen
  • 又一个观察结果:3472328296227680304 十六进制:3030303030303030。这看起来很可疑......

标签: c++ c struct binaryfiles fread


【解决方案1】:

添加一些代码后,我仍然不知道cmd,meta,I_NODO,BLOQUE_ARCHIVO... 以及它们的值是什么。
我试图从日志中推测值以便可以编译和运行,我找到了值3472328296227680304,就像@Scheff 所说,0x3030303030303030 是由下面的代码编写的("0" 的值是0x30

    for(size_t i = 0; i < super_block.s_inodes_count; i++){
       fseek(disco, super_block.s_first_ino + i, SEEK_SET);
       fwrite("0", 1, 1, disco);
    }
    for(size_t i = 0; i < super_block.s_blocks_count; i++){ 
       fseek(disco, super_block.s_first_blo + i, SEEK_SET);
       fwrite("0", 1, 1, disco);
    }

如果我注释掉部分代码,奇数值不会出现
由于信息丢失,我无法准确指出错误,但我认为这会有所帮助
我建议您添加一些调试代码,例如打印出super_block.s_first_ino 值,以查找错误。

【讨论】:

  • 应该是fwrite("\0", 1, 1, disco); 来清零该区域,而不是一系列 ASCII '0' 字符值?
  • @AndrewHenle 我认为错误是错误的写入位置。即使fwrite("\0"),结果也不会正确,因为值(原为0x3030...)将更改为0。无论写入什么值,都应该检查写入位置。
  • @AndrewHenle 我猜那些fwrite("0")(或'\0')被设计成在头部信息之后写入身体区域,但现在它们被错误地写入头部信息区域。
猜你喜欢
  • 2019-04-13
  • 1970-01-01
  • 2015-08-22
  • 1970-01-01
  • 1970-01-01
  • 2020-06-09
  • 1970-01-01
  • 1970-01-01
  • 2014-06-10
相关资源
最近更新 更多