如何高效地从C文件中检索数据

3

我有一个程序,应该能在启动时从文本文件中检索数据。这个文件可能会变得非常大,我想知道如何加速这个过程并评估它的当前性能。用于检索数据的代码如下:

void startUpBillsLoading(Bill *Bills)
{
    FILE *BillsDb = 0, *WorkersDb = 0, *PaymentDb = 0;
    BillsDb = fopen("data/bills.db", "r");
    WorkersDb = fopen("data/workers.db", "r");
    PaymentDb = fopen ("data/payments.db", "r");
    char *Buffer = malloc (512);

    if (BillsDb && WorkersDb && PaymentsDb)
    {
        int i = 0, j = 0;

        while (fscanf (BillsDb, "%d;%[^;];%[^;];%[^;];%[^;];%d/%d/%d;%d/%d/%d;%d;%f;%f\n",
                &Bills[i].Id,
                Bills[i].CompanyName,
                Bills[i].ClientName,
                Bills[i].DepartureAddress,
                Bills[i].ShippingAddress,
                &Bills[i].Creation.Day,
                &Bills[i].Creation.Month,
                &Bills[i].Creation.Year,
                &Bills[i].Payment.Day,
                &Bills[i].Payment.Month,
                &Bills[i].Payment.Year,
                &Bills[i].NumWorkers,
                &Bills[i].TotalHT,
                &Bills[i].Charges) == 14)
        {
            Bills[i].Workers = 
                malloc (sizeof(Employee)*Bills[i].NumWorkers);

            fscanf (PaymentDb, "%d;%d;%[^;];%[^;];%[^\n]\n",
                    &Bills[i].Id,
                    &Bills[i].PaymentDetails.Method,
                    Bills[i].PaymentDetails.CheckNumber,
                    Bills[i].PaymentDetails.VirementNumber,
                    Bills[i].PaymentDetails.BankName);

            LatestBillId++;
            i++;
        }

        i = 0;
        while (fscanf (WorkersDb, "%d;%[^;];%[^;];%f\n",
                    &Bills[i].Id,   
                    Bills[i].Workers[j].Surname,
                    Bills[i].Workers[j].Name,
                    &Bills[i].Workers[j].Salary) == 4)
        {
            for (int j = 1; j <= Bills[i].NumWorkers-1; j++)
            {
                fscanf (WorkersDb, "%d;%[^;];%[^;];%f\n",
                                &Bills[i].Id,   
                                Bills[i].Workers[j].Surname,
                                Bills[i].Workers[j].Name,
                                &Bills[i].Workers[j].Salary);
            }
            i++;
        }

        fclose(BillsDb);
        fclose(WorkersDb);
        fclose(PaymentDb);
    }
    else
        printf ("\t\t\tImpossible d'acceder aux factures !\n");

    free (Buffer);
}

我使用了 time.h 库来测量检索所有所需数据所需的时间。 Bill 的数据分为 3 个文件:bills.db、workers.db 和 payments.db。每个文件行从 bills.db 和 payments.db 代表整张账单,而在 workers.db 中,表示账单所需行数是可变的,并且取决于与账单相关的员工人数。
我以以下方式创建了这 3 个文件:
- bills.db 和 payments.db 具有 118087 行(因此有许多账单) - 每张账单都被设置为拥有 4 名员工,因此 workers.db 文件有 118087 * 4 = 472348 行。
该函数运行完全所需的时间约为 0.9 秒。 这个时间好坏如何,如何改进?

1
只是一个小提示,顺序读取文件更快。也许这会有用 https://dev59.com/gFgQ5IYBdhLWcg3wikaT - Tony
对我来说,现在这样已经很好了。如果以后需要处理更大的文件,你可能想要在启动时只加载部分文件,并在真正需要时再加载剩余部分(也许是异步加载?)。不过使用 SQL 数据库可能会更有效率。 - Antoine C.
2
如果性能很重要,为什么不使用一个真正的数据库,比如sqlite3呢? - Antti Haapala -- Слава Україні
@TonyTannous 顺序地是什么意思? - Jenkinx
1
可能会更快,你可以尝试并检查是否更快。我无法确定,因为我不知道你的代码确切的作用。 - Tony
显示剩余7条评论
1个回答

0

有几件事情你必须要读。第一是渐近时间复杂度和渐近空间复杂度,第二是大O符号。大O符号告诉我们程序的运行效率如何。对于你提供的代码,其大O复杂度为O(n^2)左右。因此,最大限制与快速排序相同,但由于你使用的数据长度较长,加载时间将始终增加你的运行时间。如果你想要改进,可以尝试最小化数据长度从文件中读取最少的数据。因为如果n的值增加,时间将会迅速增加。你可以从这里了解渐近符号大O符号


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接