用C语言将二进制文件读入HashTable

时间:2018-06-21 03:41:57

标签: c io binary hashtable read-write

所以我要创建一个密码库,需要能够将HashTable保存到二进制文件,并在登录后将这些相同的内容从二进制文件读取回HashTable程序中

我一直在使用fwrite和fread玩了4个小时,似乎无法找到我要去的地方。目前,我正在进行段故障测试,我已经尝试了GDB来找到它,但是只得到消息:

Thread 2 received signal SIGSEGV, Segmentation fault.
0x00007fff9a9a16a0 in ?? ()

我用于读取文件的代码是:

void readFile(char * fileName, HTable * hashTable){
//Create file pointer and point it at fild to open
FILE * fp;
fp = fopen(fileName, "rb+");

//check if file exists
if(!fp){
    printf("File could not be opened\n");
    return;
}

//Set a temp Node to hold data, read data into the temp Node
//and insert temp into hashtable
Node * temp;    
while(1){
    fread(&temp, sizeof(Node), 1, fp);
    insertData(hashTable, temp->key, temp->data);
    if(feof(fp) != 0)
        break;
    printf("is this working?\n");
}

//Close file pointer
fclose(fp);
}

我写文件的代码是:

void saveFile(char * fileName, HTable * hashTable){
//Create a FILE pointer and point it to the file to open or create
FILE * fp;
fp = fopen(fileName, "wb+");

//If the file does not exist or cannot be created give error message
if(!fp){
    printf("ERROR: File could not be created\n");
    return;
}


//for each index of the hashTable write its contents to the file
for(int i = 0; i < hashTable->size; i++){
    Node * temp = hashTable->table[i];
    while(temp != NULL){
        fwrite(&temp, sizeof(Node), 1, fp);
        temp = temp->next;
        printf("saved....\n");
    }
    printf("Index %d saved\n", i);
}

//Close file pointer
fclose(fp);

}

我知道segfault不是来自insertData函数,因为我已经对其进行了测试,并且知道它可以正常工作。对于我做错的最好的猜测是,关于我的写入条件的某些信息不正确,或者当我读取数据时,我在某处管理内存错误。

HashTable结构也是:

typedef struct HTable
{
size_t size; 
Node **table;
void (*destroyData)(void *data);
int (*hashFunction)(size_t tableSize, char * key);
void (*printData)(void *toBePrinted); 
}HTable;

我被击中的节点是:

typedef struct Node
{
char * key;
void *data;
struct Node *next;
} Node;

感谢您的任何反馈!

2 个答案:

答案 0 :(得分:0)

首先,fwrite()/ fread()的参数1是 void * ,而不是** void ****。

第二,您不能使用 fwrite()/ fread()来保存/恢复数据,因为Node的成员{key,data}是指示额外内容的指针内存数据,但是使用fwrite()/ fread()只能操作指针{char *,void *,Node *},而不是多余的数据。

对于密钥,有一个示例:

Node n;
n.key = malloc(sizeof(char) * DEF_SIZE); // Suppose n.key = 0xb8b270
strcpy(n.key, "Hello world!");
fwrite(&n, sizeof(Node), 1, fp); // Only 0xb8b270 is written.

仅将字符串(n.key)的地址写入文件,而不是字符串“ Hello world”。你能听懂我说的话吗?

简而言之,fwrite()/ fread()只是写入/读取原始数据,当您的结构包含指示额外内存数据的指针时,请小心使用它们。

对于结构

typedef struct Item
{
    char key[128];
    char value[128];
    struct Item *next;
} Item;

在这里使用fwrite()/ fread()可能是可以的,因为{char [],char [],Item *}将被写入/读取,只有{Item *}是无效数据,{char [],char []}可以正确保存/恢复。

在您的情况下,我想使用fprintf()/ fscanf()替换fwrite()/ fread()。

第三,有一个我的哈希映射实现,可以帮助您: https://github.com/foreverpersist/hashmap

答案 1 :(得分:-1)

这是一些代码。它可以编译,但是我还没有测试。我会完蛋,但我必须睡觉。

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string.h>
#include <malloc.h>

typedef struct Node
{
    char * key; //assuming this is null terminated
    void *data;
    int datasize; //number of bytes in data
    Node *next; //is this actually necessary?
} Node;

typedef struct HTable
{
    size_t size;
    Node *table;
    void(*destroyData)(void *data);
    int(*hashFunction)(size_t tableSize, char *key);
    char *(*printData)(void *data);
} HTable;


void writenode(FILE* fp, Node *node) {
    fprintf(fp, "%s\n", node->key);
    fprintf(fp, "%d\n", node->datasize);
    fwrite(node->data, sizeof(char), node->datasize, fp);
}

void readnode(FILE* fp, Node *node) {
    char buffer[5001];
    int len;
    //key
    fgets(buffer, 5000, fp);
    len = strlen(buffer) + 1;
    node->key = (char*) malloc(sizeof(char)*len);
    strcpy(node->key, buffer);
    //datasize
    fgets(buffer, 5000, fp);
    fscanf(fp, "%d", &(node->datasize));
    fread(buffer, node->datasize, sizeof(char), fp);
    //data
    node->data = malloc(sizeof(char)*node->datasize);
    memcpy(node->data, buffer, sizeof(char)*node->datasize);
}