将二进制文件加载到未知结构类型

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将二进制文件加载到未知结构类型相关的知识,希望对你有一定的参考价值。

我从二进制文件读取并将其转换为未知类型的结构时遇到问题...

  • 我真的应该避免在链接列表代码中使用保存/加载功能吗?
  • 是因为我正在使用的GCC编译器将具有更多数据的结构堆栈以方便地存储在内存中,并且因为加载函数时不知道这个“偏移”吗?

我正在用C编写一个通用的链表,它本来是一个头文件,所以我可以在任何地方使用它。由于它将是一个泛型类型列表,标题将不知道列表中的数据类型(我正在查看混合类型,所以结构)。为了保存数据,我只传递数据的地址,以及从sizeof(struct)中提取的数据的长度。读取是相同的概念,使用fread(container,sizeof(struct),1,FILE),它由调用程序传递,再次使用sizeof(struct)提取se大小。但在实践中,它不起作用......

#ifndef LINKEDLIST_H_INCLUDED
#define LINKEDLIST_H_INCLUDED
#include <string.h>

typedef struct tagNode{
    void            *data;
    struct tagNode  *next_Node;
} Node;

typedef struct tagLinkedList{
    Node *Head;
    int   Size;
} LinkedList;

int LinkedList_New(LinkedList *llist){
    llist->Head = NULL;
    llist->Size = 0;
    return 1;
}

int LinkedList_Insert(LinkedList *llist, int index, void *Data, size_t s_Data){
    int cur_index = 0;
    if(index > llist->Size || index < 0)
        index = 0;

    Node *newNode = malloc(sizeof(Node));
    newNode->data = malloc(s_Data);
    if(newNode       == NULL){return 0;}
    if(newNode->data == NULL){return 0;}
    newNode->data = Data;

    Node *currentNode = llist->Head;
    Node *lastNode    = llist->Head;

    if(index == 0){
        newNode->next_Node = llist->Head;
        llist->Head = newNode;
    }else{
        while(llist->Head->next_Node != NULL && cur_index != index){
            if(cur_index == index){
                newNode->next_Node  = currentNode;
                lastNode->next_Node = newNode;
            }else{
                lastNode    = currentNode;
                currentNode = currentNode->next_Node;
                cur_index++;
            }
        }
    }
    llist->Size += 1;
}

int LinkedList_Save(char *Path, LinkedList *llist, size_t sData){
    FILE *fp;
    fp = fopen(Path, "w");
    if(fp == NULL){return -1;}

    Node *currentNode;
    currentNode = llist->Head;

    while(currentNode != NULL){
        fwrite(currentNode->data, sData, 1, fp);
        currentNode = currentNode->next_Node;
    }
    fclose(fp);
    return 1;
}

int LinkedList_Load(char *Path, LinkedList *llist, size_t sData){
    FILE *fp;
    fp = fopen(Path, "r");
    if(fp == NULL){fclose(fp);return -1;}

    while(!feof(fp)){
        void *Data = malloc(sData);
        if(Data == NULL){fclose(fp);return -1;}
        fread(Data, sData, 1, fp);
        LinkedList_Insert(llist, 0, Data, sData);
    }
    fclose(fp);
    return 1;
}
#endif // LINKEDLIST_H_INCLUDED

我目前的测试主题是:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../LinkedList.h"
typedef struct{
    int a;
    char b[5];
} tempo;

int main(){
    tempo teste = {5, "oito"};

    LinkedList lista;
    LinkedList_New(&lista);
    LinkedList_Insert(&lista, 0, &teste, sizeof(tempo));
    LinkedList_Save("data.txt", &lista, sizeof(tempo));
    printf("%s", ((tempo*)lista.Head->data)->b);
    LinkedList ls2;
    LinkedList_New(&ls2);
    LinkedList_Load("data.txt", &ls2, sizeof(tempo));

    printf("%s", ((tempo*)ls2.Head->data)->b);

    return 1;
}

第一个printf向我展示了struct中的b变量,这意味着列表的工作方式与它应该的一样。

但是第二个printf,如果用于显示变量(int),我得到一个随机数(类似于8712382),如果用于显示b变量,我得到的只是“L”

答案

你的LinkedList_load函数有问题。将其更新为以下内容

int LinkedList_Load(char *Path, LinkedList *llist, size_t sData){
        FILE *fp;
        fp = fopen(Path, "rb");
        if(fp == NULL){fclose(fp);return -1;}
        fseek(fp,0L,SEEK_SET);
        while(!feof(fp)){
                void *Data = malloc(sData);
                if(Data == NULL){fclose(fp);return -1;}
                int readed=fread(Data, sData, 1, fp);
                if(readed==0){return -1;}
                /*you were displaying the last reading that contains 
                *nothing, the previous check solves the problem.
                */
                printf("readed %d items:  
",readed);
                LinkedList_Insert(llist, 0, Data, sData);       
        }
       fclose(fp);

}

以上是关于将二进制文件加载到未知结构类型的主要内容,如果未能解决你的问题,请参考以下文章

如何用c语言判断一个未知文件的文件类型

分析未知二进制文件的程序

类加载过程

14.VisualVM使用详解15.VisualVM堆查看器使用的内存不足19.class文件--文件结构--魔数20.文件结构--常量池21.文件结构访问标志(2个字节)22.类加载机制概(代码片段

android.view.inflateexception 二进制 xml 文件第 7 行错误膨胀类片段

Weka 未知数据类型