这是我最初在 1991 年编写的一个程序bsplit
。它将文件分割成任意大小的块;默认大小以千字节为单位指定(好吧,千字节- 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 字节块,而k
, m
, 和g
分别表示 KiB、MiB 和 GiB。
支持代码现在可以在我的 GitHub 上的SOQ(堆栈溢出问题)存储库中以 files 、 、 和filter.c
src filter.h
/ filterio.c
libsoq子目录的形式获得。还有一个标题将替换该节 - 并且将使用而不是请求 POSIX.1 2008 (2018) 支持。stderr.c
stderr.h
posixver.h
__STDC_VERSION__
#define _XOPEN_SOURCE 700
600