【问题标题】:correct way to use fwrite and fread使用 fwrite 和 fread 的正确方法
【发布时间】:2017-04-11 23:57:54
【问题描述】:

我写了一个程序

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    FILE *fp;
    int r;
    char arr[] = "this is the string";
    char str[20] = {'\0'};

    fp = fopen("fwrite.txt", "w");
    fwrite(arr, 1, sizeof(arr), fp);
    fseek(fp, SEEK_SET, 0);
    r = fread(str, 1, sizeof(arr), fp);

    if(r == sizeof(arr))
        printf("read successfully\n");
    else
    {
        printf("read unsuccessfull\n");
        exit(1);
    }

    printf("read = %d\n", r);
    printf("%s\n", str);

    fclose(fp);
    return 0;
}

我正在尝试以这种方式阅读,但我做不到。这里有什么问题,是我应该放入&amp;str[i] 并为fread 运行循环还是fread 能够将数据放入str

我越来越垃圾了,我不明白为什么?

【问题讨论】:

  • 您需要fseek(fp, 0L, SEEK_SET)。偏移量在来源之前 (SEEK_SET)。
  • 我猜你是在使用 www.tutorialspoint.com 作为参考,出于某种原因,他们以错误的顺序使用 fseek、fread 和 fwrite 的参数。
  • 还需要w+b模式打开

标签: c fread


【解决方案1】:

主要问题是你有 fseek() 的参数向后 - 你需要在 wherece (SEEK_SET) 之前的偏移量 (0)。第二个问题是您尝试从仅为写入而打开的文件中读取。在这种情况下,一个较小但通常非常重要的问题是您不要错误检查fopen() 调用。 (这个fopen() 失败的可能性相对较小,但更有趣的事情已经知道了。)您还应该检查fwrite() 调用(当然,您已经检查了fread())。

解决所有这些问题可能会导致:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int rc = EXIT_SUCCESS;
    int r;
    const char file[] = "fwrite.txt";
    char arr[] = "this is the string";
    char str[20] = {'\0'};
    FILE *fp = fopen(file, "w+b");
    if (fp == 0)
    {
        fprintf(stderr, "Failed to open file %s for reading and writing\n", file);
        rc = EXIT_FAILURE;
    }
    else
    {
        if (fwrite(arr, 1, sizeof(arr), fp) != sizeof(arr))
        {
            fprintf(stderr, "Failed to write to file %s\n", file);
            rc = EXIT_FAILURE;
        }
        else
        {
            fseek(fp, 0, SEEK_SET);
            r = fread(str, 1, sizeof(arr), fp);
            if (r == sizeof(arr))
            {
                printf("read successful\n");
                printf("read = %d bytes\n", r);
                printf("read data [%s]\n", str);
            }
            else
            {
                printf("read unsuccessful\n");
                rc = EXIT_FAILURE;
            }
        }
        fclose(fp);
    }
    return rc;
}

示例运行:

$ ./fi37
read successful
read = 19 bytes
read data [this is the string]
$

请注意,这部分是因为您将输出字符串末尾的空字节写入文件,然后将其读回。如果文件包含空字节,则该文件不是真正的文本文件。 "w+b" 模式下的 b 在没有二进制文件和文本文件之分的 Unix 系统上并不真正需要。如果您在 Windows 上将空字节写入文件,则应使用 b 指示二进制模式。

如果您选择这样做,您可以通过在 main() 函数中不包含单个 return 来减少“杂乱”(或嵌套深度)。您可以使用return EXIT_FAILURE; 并避免使用else 和另一组大括号。如果文件被打开,显示的代码会小心关闭文件。在通用功能中,这很重要。在main() 中,它不太重要,因为退出进程无论如何都会刷新和关闭打开的文件。

【讨论】:

  • 是的,问题是 fseek 参数和 w+b,我使用的是 ubuntu,如果我将 w+b 删除为 w,它将无法正常工作。
  • 是的;使用"w" 表示只写。使用"w+" 表示在执行任何其他操作之前先读写并清空文件。
  • 不检查fopen的返回值不是小问题,imo,这很重要。忽略库函数的返回值会使调试非常非常痛苦。我什至在文档中发了一篇关于这个的帖子:stackoverflow.com/documentation/c/2006/common-pitfalls/15692/… 不管怎样,+1 提到这个
  • @Dunno:我稍微改写了关于检查fopen() 的评论。你是对的;总的来说,它非常重要,这也是我提到并演示它的原因。
【解决方案2】:

对于fopen,您无法使用"w" 模式读取文件,请改用"w+"

"r" - 打开一个文件进行读取。该文件必须存在。

"w" - 创建一个空文件用于写入。如果已经有同名文件 存在,其内容被删除,该文件被视为一个新的空文件。

"a" - 附加到文件。写操作,在末尾追加数据 文件。如果文件不存在,则创建该文件。

"r+" - 打开一个文件以更新读取和写入。该文件必须存在。

"w+" - 为读写创建一个空文件。

"a+" - 打开一个文件进行读取和附加。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-29
    相关资源
    最近更新 更多