使用 fgets 只读取文件的一部分

using fgets to read only part of the file

在使用 visual studio 2012 时,我使用了两个文件。一个是 phonenumber.db,另一个是 user.db。虽然它们有 .db 格式,但它实际上是用文本编写的,并保存为 .db。 phonenumber.db 只包含数字。例如)

00123123
01231245
09102312

user.db 包含日期、以数字表示的其他本地信息等

20160922 1029000001245123 DAVID HENRY
20192034 1029300275718283 MARK  LO

所以我用fgets读取了phonenumber,在user.db中查找是否有匹配的信息。

我的代码是这样的,

FILE *phoneDB = fopen(/directory of phonenumber.db, "rb");
FILE *userDB = fopen (~~~);
bool numfindFlag = False;
char phonereadbuffer[PHONELEN + 2];
char userreadbuffer[INFOLEN+2];
while(!numfindFlag && fgets(phonereadbuffer, PHONELEN + 2, phoneDB) {
     while(!numfindFlag && fgets(userreadbuffer, INFOLEN + 2, userDB) {
      ----some function works here ----
    }
}

但是,问题是,当我检查日志时,fgets() 工作异常。 它在user.db中读取同一行两次,读取所有数字部分后,虽然我指定INFOLEN大小只读取数字部分,但它也读取其他角色部分也是如此。

它应该只读 20160922 1029000001245123 但它也显示了 DAVID HENRY MARK,LO 部分。

为什么会这样?我使用 fgets() 时是否缺少某些内容?

您有两个嵌套的 while 循环:

while(!numfindFlag && fgets(phonereadbuffer, PHONELEN + 2, phoneDB) {
  while(!numfindFlag && fgets(userreadbuffer, INFOLEN + 2, userDB) {

这基本上意味着:

  • 你读了1条phonelen+2条记录
  • 您阅读了1条infolen+2条记录
  • 您遗漏的循环体中发生了一些事情
  • 您阅读了1条infolen+2条记录
  • 循环体中发生了一些事情...
  • 您阅读了1条infolen+2条记录
  • ...
  • 当 numfindFlag 变为 false 时停止

这里你可能有两个错误:

  • 如果您没有读取到结尾字符的所有内容,则第二次 infolen 读取将读取一个字符串。
  • 即使您正确读取了字符串,您也永远不会再读取 phonelen 记录。

一个更容易编写的实现只是逐行读取文件,并且可以使用 strncmp 进行匹配检查。

您的问题似乎是您希望 fgets 每次调用时都从新行开始。然而,这不是它的工作原理。所以您必须自己阅读该行的其余部分。

此外,您必须确保每次都回到 userDB 文件的开头。

因此您的代码可能如下所示:

while(!numfindFlag && fgets(phonereadbuffer, PHONELEN + 2, phoneDB)) {
    FILE *userDB = fopen ("user.db", "r");
    if (!userDB)
    {
        fclose(phoneDB);
        printf("file error...\n");
        return 0;
    }

    while(!numfindFlag && fgets(userreadbuffer, INFOLEN + 2, userDB)) {
        // ----some function works here ----

        // Read until end of line
        while (strlen(userreadbuffer) &&
               userreadbuffer[strlen(userreadbuffer) - 1] != '\n' && 
               fgets(userreadbuffer, INFOLEN + 2, userDB));
    }
    fclose(userDB);
}