在C中使用fwrite错误的int值

时间:2018-11-30 00:23:49

标签: c struct fwrite fread

我试图为C中的一个简单UDP客户端-服务器应用程序创建一个密钥管理器。我遇到了将密钥写入文本文件的问题。我目前正在将结构存储到txt文件中,但是使用整数时,我的输出是相同的。

// ...
// if the principal is requesting to registering, store it in a file
if (req.request_type == regista) {
    printf("Writing key to file...\n");
    pFile = fopen("crypt.txt", "ab");
    fwrite(&req, sizeof(struct P2Key), 1, pFile);
    printf("Written: %u %i ", req.principal_id, req.public_key);
    fclose(pFile);
    printf("Done\n");
}

// if pincipal is requesting key
if (req.request_type == request_key) {
    pFile = fopen("crypt.txt", "rb");
    printf("Key requested for: %u %i ", req.principal_id, req.public_key);
    printf("Searching for Requested Key\n");

    while (fread(&res, sizeof(struct P2Key), 1, pFile) == 1) {
        printf("Read: %u %i\n", res.principal_id, res.public_key);
        printf("Line Number: %ld\n", ftell(pFile));

        // if this is the client requested, send the key
        if (req.principal_id == res.principal_id) {
            send_key.principal_id = req.principal_id;
            send_key.public_key = req.public_key;
            printf("Sending Key...\n");
            // ...
        }

这是要写入文件的结构

typedef struct P2Key {
    enum {
        regista, request_key
    } request_type; /* same size as an unsigned int */
    unsigned int principal_id; /* client or server identifier */
    int public_key; /*  public key */
} P2Key;

当我尝试读取文件时得到的输出:

 Writing key to file...
 Written: 2 7 Done
 ...
 Writing key to file...
 Written: 1 7 Done
 Key requested for: 2 7 Searching for Requested Key
 Read: 512 1792
 Line Number: 12
 Read: 256 1792
 Line Number: 24
 End of file reached.

我已经待了几个小时了,感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

您正在以附加模式书写;自切换到编写结构以来,您是否重新创建了文件?您无需显示甚至不测试写入的字节数,因此不知道写入是否成功。

我的第一个怀疑是,随着时间的推移,您一直在追加此文件,并且该文件的开头附近有旧数据,与您的结构不符。我建议先清空文件。在UNIX / Linux上,您可以通过外壳程序中的““> crypt.txt”来执行此操作。

现在开始调试代码。捕获所有读取和写入的返回值,它们返回size_t,因此您至少可以在调试器中查看返回值。如果您没有写期望的字节数(结构的大小),则可能要记录一个错误等。单步执行写操作并关闭调试器,然后使用十六进制转储或类似实用程序查看文件。文件中的值看起来是否像您期望的那样?文件包含的字节数与结构的大小相同吗?

然后继续阅读代码。观看代码使用fread从文件加载每个值。观察从fread中获得的返回值-它是结构的大小吗?读取完成后,查看结构中的值。看起来像在读您写的内容吗?

答案 1 :(得分:1)

您的程序似乎在这里起作用。请注意,我使用的是Linux,但是由于您在b参数中使用了fopen,即使您使用的是WinX,它也应该相同。

我必须综合一些缺少的要素才能获得完整的程序。我从req传递了main,所以[new] action函数必须使用req->*而不是req.*,但是,否则应该相同作为您的代码:


#include <stdio.h>

typedef struct P2Key {
    enum {
        regista, request_key
    } request_type;                     /* same size as an unsigned int */
    unsigned int principal_id;          /* client or server identifier */
    int public_key;                     /* public key */
} P2Key;

void
action(P2Key *req)
{
    FILE *pFile;
    P2Key res;
    P2Key send_key;

    printf("request_type=%d regista=%d request_key=%d\n",
        req->request_type,regista,request_key);

// ...
// if the principal is requesting to registering, store it in a file
    if (req->request_type == regista) {
        printf("Writing key to file...\n");
        pFile = fopen("crypt.txt", "ab");
        fwrite(req, sizeof(struct P2Key), 1, pFile);
        printf("Written: %u %i ", req->principal_id, req->public_key);
        fclose(pFile);
        printf("Done\n");
    }

// if pincipal is requesting key
    if (req->request_type == request_key) {
        pFile = fopen("crypt.txt", "rb");
        printf("Key requested for: %u %i ", req->principal_id, req->public_key);
        printf("Searching for Requested Key\n");

        while (fread(&res, sizeof(struct P2Key), 1, pFile) == 1) {
            printf("Read: %u %i\n", res.principal_id, res.public_key);
            printf("Line Number: %ld\n", ftell(pFile));

            // if this is the client requested, send the key
            if (req->principal_id == res.principal_id) {
                send_key.principal_id = req->principal_id;
                send_key.public_key = req->public_key;
                printf("Sending Key...\n");
                // ...
            }
        }

        fclose(pFile);
    }
}

int
main(void)
{
    P2Key req;

    while (1) {
        printf("Cmd (regista=%d request_key=%d): ",regista,request_key);
        fflush(stdout);
        scanf("%d",&req.request_type);
        scanf("%u %d",&req.principal_id,&req.public_key);

        action(&req);
    }
}

这是我得到的输出:

Cmd (regista=0 request_key=1): 0 5 6
request_type=0 regista=0 request_key=1
Writing key to file...
Written: 5 6 Done
Cmd (regista=0 request_key=1): 0 8 9
request_type=0 regista=0 request_key=1
Writing key to file...
Written: 8 9 Done
Cmd (regista=0 request_key=1): 1 8 9
request_type=1 regista=0 request_key=1
Key requested for: 8 9 Searching for Requested Key
Read: 1 2
Line Number: 12
Read: 5 6
Line Number: 24
Read: 8 9
Line Number: 36
Sending Key...
Cmd (regista=0 request_key=1): ^C

答案 2 :(得分:0)

您需要检查您的文件,由于某种原因,其中似乎有一个额外的字节(或多个字节),这导致您以错误的偏移量读取结构。

我基于以下几点:

  1. 您只需将结构附加到现有文件,而不管文件中当前有多少字节;和
  2. 您正在读取的值是256的精确倍数。更重要的是,它们是256乘以127({{1},256512)。 / li>

一种简单的检查方法是简单地删除文件(或将其清空)并​​再次运行程序。如果您没有其他要写入文件的文件,它应该可以正常工作。


如果您愿意的话,实际上有一些方法可以解决此类问题。其中包括:

  • 打开时检查文件大小是否是结构大小的精确倍数。
  • 在您的结构中添加一个或多个指示符字段以检查每一项,例如,您将开头的一个字段称为1792,然后将另一个字段称为check_dead。 >在写记录时始终设置为check_beef0xdead,并在读取记录时总是检查。