繁体   English   中英

从文件读取到某个位置,然后从该位置写入文件,以及从文件直接读取到文件之间有什么区别

[英]what is the difference between reading from a file to a location, then writing from that location to a file, and reading from a file directly to file

我正在解决体积(cs50x 中的问题之一) 显然,我编写的代码在从数组中读取文件内容并从该数组写入 output 文件时有效。

当我试图通过指向 output 文件的指针将输入文件内容读取到 output 文件时,它没有弹出任何错误,但 output 不工作。

有人可以解释从一个文件读取到一个位置(比如一个数组)和从一个文件读取到另一个文件有何不同。

这是参考代码

`// Modifies the volume of an audio file

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

// Number of bytes in .wav header
const int HEADER_SIZE = 44;

int main(int argc, char *argv[])
{
    // Check command-line arguments
    if (argc != 4)
    {
        printf("Usage: ./volume input.wav output.wav factor\n");
        return 1;
    }

    // Open files and determine scaling factor
    FILE *input = fopen(argv[1], "r");
    if (input == NULL)
    {
        printf("Could not open file.\n");
        return 1;
    }

    FILE *output = fopen(argv[2], "w");
    if (output == NULL)
    {
        printf("Could not open file.\n");
        return 1;
    }

    float factor = atof(argv[3]);

    // TODO: Copy header from input file to output file

    uint8_t arr[HEADER_SIZE];

    fread(arr, sizeof(uint8_t), HEADER_SIZE, input);

    fwrite(arr, sizeof(uint8_t), HEADER_SIZE, output);

    // creating a temprary location in memory for the content bytes of a wave file

    int16_t buffer;

    // TODO: Read samples from input file and write updated data to output file

    while (fread(&buffer, sizeof(int16_t), 1, input))

    {

        buffer = (buffer) * factor;
        fwrite(&buffer, sizeof(int16_t), 1, output);
    }

    // Close files
    fclose(input);
    fclose(output);
}`

但是如果我写下面的代码,它就不会工作


   ` // TODO: Copy header from input file to output file

    // reading from the input file to the output file.

    fread(output, sizeof(uint8_t), HEADER_SIZE, input);

    // creating a temprary location in memory for the content bytes of a wave file

    int16_t buffer;

    // TODO: Read samples from input file and write updated data to output file

    while (fread(&buffer, sizeof(int16_t), 1, input))

    {
        buffer = (buffer) * factor;
        fwrite(&buffer, sizeof(int16_t), 1, output);
    }`

有人可以解释从一个文件读取到一个位置(比如一个数组)和从一个文件读取到另一个文件有何不同。

在您的第二个示例代码中,您将文件从input读取到output 在这种特定情况下, output被视为用于存储数据的void *缓冲区; 不作为写入数据的文件句柄。

fread(output, sizeof(uint8_t), HEADER_SIZE, input);

你应该考虑这样的事情:

uint8_t buffer[HEADER_SIZE];
size_t read, written;

read = fread(buffer, 1, HEADER_SIZE, input);
written = fwrite(buffer, 1, read, output);

注意:为简单起见,我不在此处检查返回值,我将其留给 OP。

编辑:

1 - 什么是 FILE 指针?

FILE *是指向动态分配的FILE结构的指针。 此结构包含 API 使用的特定信息片段,以确定哪个文件与读、写、查找等有关。

2 - 为什么写入文件句柄不起作用?

fread function 将指针作为第一个参数。 FILE *确实是一个指针。 但是, fread需要一个 memory 区域来写入数据。

传递FILE *将被编译器接受,因为每个指针都可以转换为void *

但是,在运行期间,传递的FILE *指针将用于将读取的数据字节存储为 memory 缓冲区。 这意味着fread将覆盖目标 memory 结构,从指向的地址开始读取内容。

最后, FILE *结构将不再保存 API 数据,因此,当用户使用FILE *指针向文件写入数据时,原始FILE *被破坏, fwrite很可能导致段错误。

从手册页:

function fread() 从 stream 指向的 stream 读取 nmemb 项数据,每个 size 字节长,将它们存储在 ptr 给定的位置。

签名:

size_t fread(void *restrict ptr, size_t size, size_t nmemb,
                    FILE *restrict stream);

fread的第一个参数是要写入的空指针。 您在代码中向它传递了一个FILE *

// reading from the input file to the output file.

fread(output, sizeof(uint8_t), HEADER_SIZE, input);

在基于 Unix 的系统上,您可以使用mmap将文件 map 转换为 memory 然后使用它。 或者只是将文件读入缓冲区,类似于您在第一个示例中所做的那样。

FILE是标准库中定义的结构。 它包含有关打开的文件的所有相关信息。

来自 C11:

(...) FILE 是一个 object 类型,能够记录控制 stream 所需的所有信息,包括其文件 position 指示器,指向其关联缓冲区的指针(如果有),记录是否读/写的错误指示器发生错误,以及记录是否已到达文件末尾的文件结束指示器; (...)

fopen返回指向FILE结构的指针。 指针本身并不指向文件中的 memory,而是指向FILE类型的结构。

该结构的内容完全由实现定义。

这是FILE在我的系统上需要的内容:

type = struct _IO_FILE {
    int _flags;
    char *_IO_read_ptr;
    char *_IO_read_end;
    char *_IO_read_base;
    char *_IO_write_base;
    char *_IO_write_ptr;
    char *_IO_write_end;
    char *_IO_buf_base;
    char *_IO_buf_end;
    char *_IO_save_base;
    char *_IO_backup_base;
    char *_IO_save_end;
    struct _IO_marker *_markers;
    struct _IO_FILE *_chain;
    int _fileno;
    int _flags2;
    __off_t _old_offset;
    unsigned short _cur_column;
    signed char _vtable_offset;
    char _shortbuf[1];
    _IO_lock_t *_lock;
    __off64_t _offset;
    struct _IO_codecvt *_codecvt;
    struct _IO_wide_data *_wide_data;
    struct _IO_FILE *_freeres_list;
    void *_freeres_buf;
    size_t __pad5;
    int _mode;
    char _unused2[20];
} *

请参阅此答案以了解FILE*的含义以及为什么将指针传递给不同类型不能按预期工作。 有关FILE结构的更多详细信息,请参见此处

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM