[英]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];
} *
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.