gpt4 book ai didi

c - 文件分块和缓冲?

转载 作者:行者123 更新时间:2023-11-30 14:22:06 25 4
gpt4 key购买 nike

最终,我只是想将二进制文件切成大小不大于 X 的片段。不要用它做任何其他事情。如果输入文件是 21MB,我想要 3 个 7MB 的 block ,我可以用 cat 或其他东西连接。在下面有效的简单示例中,我使用 7MB block 大小的缓冲区。我是否必须使用它来获取 7MB 文件 block ?如果 block 大小为 2GB,那么这显然不是我想要放入内存中的东西。那么我是否需要创建一个缓冲区。

我确实阅读了这里和其他网站上关于此的几篇文章,但它们似乎都使用了由 malloc 或数组创建的某种缓冲区,并且查找非缓冲方式使我远远超出了我对套接字和TCP/IP 相关主题。

我注定要使用大量的 if/while 语句吗?

附注在哪里可以找到有关 C 语言 I/O 流的书籍?我可以找到很多 C++ 的内容,但找不到 C。

ifp = fopen(ifile, "rb"); // ifile is a 25MB sound file
ofp = fopen(ofile, "w"); // Omitted error checking.

setvbuf( ifp, NULL, _IOFBF, 1024); // Are these on
setvbuf( ofp, NULL, _IOFBF, 1024); // by default?

size_t CHUNK = 7000000; // 7MB Chunk sizes
size_t result = 0;
size_t *buffer = malloc(CHUNK);

if (buffer == NULL) {fputs ("Could not allocate memory",stderr); exit (1);}
// Read 1 btye at a time?
result = fread(buffer, 1, CHUNK, ifp);
if (result != CHUNK) {fputs ("ERROR: Buffer/read mismatch.",stderr); exit (1);}

fwrite(buffer, CHUNK, 1, ofp);

free(buffer);

最佳答案

这是一个程序,bsplit,是我最初在 1991 年编写的。它将文件分割成任意大小的 block ;默认大小以千字节为单位指定(好吧,kibibytes — 1024 字节)。

/*
@(#)File: $RCSfile: bsplit.c,v $
@(#)Version: $Revision: 1.11 $
@(#)Last changed: $Date: 2008/08/09 05:54:55 $
@(#)Purpose: Split file into blocks -- binary
@(#)Author: J Leffler
*/

#if __STDC_VERSION__ >= 199901L
#define _XOPEN_SOURCE 600
#else
#define _XOPEN_SOURCE 500
#endif /* __STDC_VERSION__ */

#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "stderr.h"
#include "filter.h"

#define MAXFILENAMELEN 256
#define KILOBYTE 1024
#define MEGABYTE (KILOBYTE*KILOBYTE)
#define GIGABYTE (MEGABYTE*KILOBYTE)
#define NIL(x) ((x)0)
#define MIN(a,b) (((a) < (b)) ? (a) : (b))

char *prefix = "bsplit.";
size_t blocksize = 64;
size_t nblocks = 0;
size_t skipblocks = 0;
char buffer[64*KILOBYTE];
long counter = 0;

static int bsplit(FILE *ifp, const char *fn)
{
size_t n; /* Bytes read this time */
size_t bsize; /* Size written for current block */
size_t tsize; /* Size written for current file */
size_t rsize; /* Amount to read */
FILE *op; /* Output file stream */
char file[MAXFILENAMELEN]; /* Output file name */

tsize = 0;
bsize = 0;
op = NIL(FILE *);
rsize = MIN(sizeof(buffer), blocksize);
while ((n = fread(buffer, sizeof(char), rsize, ifp)) > 0)
{
tsize += n;
if (tsize > skipblocks)
{
if (bsize == 0)
{
sprintf(file, "%s%03ld", prefix, counter++);
if ((op = fopen(file, "w")) == NIL(FILE *))
{
err_sysrem2("failed to open file", file);
return(-1);
}
printf("%s\n", file);
}
bsize += n;
if (fwrite(buffer, sizeof(char), n, op) != n)
{
err_sysrem2("failed to write to file", file);
return(-1);
}
if (bsize >= blocksize)
{
fclose(op);
bsize = 0;
}
if (nblocks > 0 && tsize >= nblocks)
break;
}
}
return 0;
}

int main(int argc, char **argv)
{
int opt;
size_t multiplier = KILOBYTE;
char *p;
char c;
int rc;

opterr = 0;
err_setarg0(argv[0]);

while ((opt = getopt(argc, argv, "s:n:p:b:V")) != -1)
{
switch (opt)
{
case 'p':
prefix = optarg;
if (strlen(prefix) > MAXFILENAMELEN - sizeof("000"))
err_error("file name prefix (%s) is too long (max %d)", prefix,
(int)(MAXFILENAMELEN-sizeof("000")));
break;
case 's':
skipblocks = atoi(optarg);
break;
case 'n':
nblocks = atoi(optarg);
break;
case 'b':
blocksize = atoi(optarg);
p = optarg + strspn(optarg, "0123456789");
if (*p != '\0')
{
c = tolower((unsigned char)*p);
if (c == 'c')
multiplier = 1;
else if (c == 'b')
multiplier = KILOBYTE/2;
else if (c == 'k')
multiplier = KILOBYTE;
else if (c == 'm')
multiplier = MEGABYTE;
else if (c == 'g')
multiplier = GIGABYTE;
else
err_error("unknown size multiplier suffix %s\n", p);
if (p[1] != '\0')
err_error("unknown size multiplier suffix %s\n", p);
}
break;
case 'V':
err_version("BSPLIT", &"@(#)$Revision: 1.11 $ ($Date: 2008/08/09 05:54:55 $)"[4]);
break;
default:
err_usage("[-b blocksize][-p prefix][-s skipblocks][-n blocks][file [...]]");
break;
}
}

/* Convert sizes to bytes */
blocksize *= multiplier;
skipblocks *= blocksize;
if (nblocks > 0)
nblocks = skipblocks + nblocks * blocksize;

rc = filter_stdout(argc, argv, optind, bsplit);
return(rc);
}

头文件stderr.h声明了一系列错误报告例程;我在我的大多数程序中都使用它。头文件 filter.h 声明了函数 filter_stdout(),该函数逐步遍历参数列表,打开文件以读取和调用函数 — 在本例中为 bsplit( ) — 依次处理每个文件。它自动处理“无参数意味着读取标准输入”等。 (联系我获取代码 - 请参阅我的个人资料。)

请注意,乘数 c 表示“字符”,b 表示 512 字节 block ,kmg 分别表示 KiB、MiB 和 GiB。

<小时/>

支持代码现已在我的 GitHub 上的 SOQ(Stack Overflow Questions)存储库中作为文件 filter.cfilter.hfilterio.c 提供stderr.cstderr.hsrc/libsoq 子目录中。还有一个头文件 posixver.h 将替换 __STDC_VERSION__ 节 - 并使用 #define _XOPEN_SOURCE 700 而不是 600 code> 请求 POSIX.1 2008 (2018) 支持。

关于c - 文件分块和缓冲?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14106901/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com