これが私が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 (Stack Overflow Questions)リポジトリで、ファイルfilter.c
、、、およびsrc/libsoqサブディレクトリで利用できるようになりました。スタンザを置き換えるヘッダーもあります—そしてPOSIX.1 2008(2018)サポートを要求するのではなく使用します。filter.h
filterio.c
stderr.c
stderr.h
posixver.h
__STDC_VERSION__
#define _XOPEN_SOURCE 700
600