LevelDB C迭代器

我需要用c语言遍历leveldb数据库 – https://github.com/google/leveldb/blob/master/include/leveldb/ch 。 一切都有效,除了迭代。结果与一些二进制噪声数据:

key: value1 key: value2 key#&^$&*# value one1(*@(# value1 two2%*@( value2 

使用$&*#等符号我显示了二进制输出,stackoverflow不允许将二进制输出放在这里。

代码:

 #include  #include  int main() { leveldb_t *db; leveldb_options_t *options; leveldb_readoptions_t *roptions; leveldb_writeoptions_t *woptions; char *err = NULL; char *read; size_t read_len; /******************************************/ /* OPEN */ options = leveldb_options_create(); leveldb_options_set_create_if_missing(options, 1); db = leveldb_open(options, "testdb", &err); if (err != NULL) { fprintf(stderr, "Open fail.\n"); return(1); } /* reset error var */ leveldb_free(err); err = NULL; /******************************************/ /* WRITE */ woptions = leveldb_writeoptions_create(); leveldb_put(db, woptions, "one", 3, "value1", 6, &err); if (err != NULL) { fprintf(stderr, "Write fail.\n"); return(1); } leveldb_free(err); err = NULL; /******************************************/ /* WRITE 2 */ woptions = leveldb_writeoptions_create(); leveldb_put(db, woptions, "two", 3, "value2", 6, &err); if (err != NULL) { fprintf(stderr, "Write fail.\n"); return(1); } leveldb_free(err); err = NULL; /******************************************/ /* READ */ roptions = leveldb_readoptions_create(); read = leveldb_get(db, roptions, "one", 3, &read_len, &err); if (err != NULL) { fprintf(stderr, "Read fail.\n"); return(1); } printf("key: %s\n", read); leveldb_free(err); err = NULL; /******************************************/ /* READ 2 */ roptions = leveldb_readoptions_create(); read = leveldb_get(db, roptions, "two", 3, &read_len, &err); if (err != NULL) { fprintf(stderr, "Read fail.\n"); return(1); } printf("key: %s\n", read); leveldb_free(err); err = NULL; /******************************************/ /* ITERATE */ roptions = leveldb_readoptions_create(); leveldb_iterator_t *iter = leveldb_create_iterator(db, roptions); for (leveldb_iter_seek_to_first(iter); leveldb_iter_valid(iter); leveldb_iter_next(iter)) { size_t key_len, value_len; const char *key_ptr = leveldb_iter_key(iter, &key_len); const char *value_ptr = leveldb_iter_value(iter, &value_len); /* Prints some binary noise with the data */ printf("%s %s\n", key_ptr, value_ptr); } leveldb_iter_destroy(iter); leveldb_free(err); err = NULL; /******************************************/ /* CLOSE */ leveldb_close(db); return(0); } 

如何正确迭代C中的LevelDB?

似乎leveldb_iter_keyleveldb_iter_value返回的值不是以NULL结尾的正确字符串。

因此,可以使用肮脏的解决方案

 printf("%.*s %.*s\n", (int) key_len, key_ptr, (int) value_len, value_ptr); 

代替

 printf("%s %s\n", key_ptr, value_ptr); 

但是,IMO最好根据它们的长度复制这些值,然后再使用它们。

正如您在https://github.com/google/leveldb/blob/master/db/c.cc#L197中看到的那样, leveldb_get创建了适当长度的Slice(key, keylen) L205上的Slice(key, keylen) )并返回密钥的副本( CopyString上的CopyString)。

额外:

我用valgrind检查了你的代码,并且有一些内存泄漏的选项。 你应该手动释放它们(例如leveldb_writeoptions_destroy用于woptions )。 leveldb_get结果( read )也应该被释放。

示例代码:

 // allocate new strings char * key = (char *) malloc(key_len + 1); char * value = (char *) malloc(value_len + 1); // copy string content and ensure that string is null-terminated memcpy(key, key_ptr, key_len); key[key_len] = 0; memcpy(value, value_ptr, value_len); value[value_len] = 0; // print printf("%s %s\n", key, value); // free free(key); free(value); 

LevelDB不使用C(++)字符串作为键和值,它使用可能包含NUL且不是NUL终止的字节数组。 这在此记录: 1 。

使用任何面向C字符串的函数来操作这些数组是错误的。 您无法使用printf安全地显示返回的值。