前回の続き。今まではファイルがない前提で新規にファイルを生成していましたが、ファイルが存在する場合は、指定サイズにファイルサイズを伸長するように改造してみます。
元プログラムです。
takk@deb9:~/tmp$ cat -n t.c 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <unistd.h> 4 5 int main(int argc, char* argv[]) 6 { 7 FILE *fp; 8 int i,size=0; 9 int value=0; 10 int ch; 11 12 while ((ch = getopt(argc, argv, "s:v:")) != -1){ 13 switch (ch) { 14 case 's': 15 size = atoi(optarg); 16 break; 17 case 'v': 18 value = atoi(optarg); 19 break; 20 default: 21 printf("parameter error\n"); 22 return 1; 23 } 24 } 25 26 if(optind >= argc){ 27 printf("parameter error\n"); 28 return 1; 29 } 30 31 for(; optind<argc; optind++){ 32 fp = fopen(argv[optind],"w"); 33 for(i=0; i<size; i++) 34 fputc(value,fp); 35 fclose(fp); 36 } 37 return 0; 38 } 39 takk@deb9:~/tmp$
ファイルが存在する場合のファイル長を収める変数としてlenを定義します。
5 int main(int argc, char* argv[]) 6 { 7 FILE *fp; 8 int i,len,size=0;
ファイルの存在チェックはfopenでやることにします。存在しない場合は、NULLが戻るので、NULLなら、前回までのバイナリ生成をすればよいです。`
32 fp = fopen(argv[optind],"r"); 33 if(fp == NULL){ 34 fp = fopen(argv[optind],"w"); 35 for(i=0; i<size; i++) 36 fputc(value,fp); 37 fclose(fp);
ファイルが存在した場合は、ファイルサイズを取得するためにfgetcを回しています。こんなことしなくても存在チェックもByte長もstat関数を使えば良いのですが、今回は使いません。
38 }else{ 39 fp = fopen(argv[optind],"r"); 40 for(len=0; (ch=fgetc(fp)) != EOF; len++) 41 ; 42 fclose(fp); 43 if(len < size){ 44 fp = fopen(argv[optind],"a"); 45 for(i=len; i<size; i++) 46 fputc(value,fp); 47 fclose(fp); 48 } 49 }
ファイルサイズ(len)が、-sで指定した長さ未満の場合のみ指定サイズまで-vで指定した値で拡張します。
毎度ですが、全ソース。
takk@deb9:~/tmp$ cat -n t.c 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <unistd.h> 4 5 int main(int argc, char* argv[]) 6 { 7 FILE *fp; 8 int i,len,size=0; 9 int value=0; 10 int ch; 11 12 while ((ch = getopt(argc, argv, "s:v:")) != -1){ 13 switch (ch) { 14 case 's': 15 size = atoi(optarg); 16 break; 17 case 'v': 18 value = atoi(optarg); 19 break; 20 default: 21 printf("parameter error\n"); 22 return 1; 23 } 24 } 25 26 if(optind >= argc){ 27 printf("parameter error\n"); 28 return 1; 29 } 30 31 for(; optind<argc; optind++){ 32 fp = fopen(argv[optind],"r"); 33 if(fp == NULL){ 34 fp = fopen(argv[optind],"w"); 35 for(i=0; i<size; i++) 36 fputc(value,fp); 37 fclose(fp); 38 }else{ 39 fp = fopen(argv[optind],"r"); 40 for(len=0; (ch=fgetc(fp)) != EOF; len++) 41 ; 42 fclose(fp); 43 if(len < size){ 44 fp = fopen(argv[optind],"a"); 45 for(i=len; i<size; i++) 46 fputc(value,fp); 47 fclose(fp); 48 } 49 } 50 } 51 return 0; 52 } 53 takk@deb9:~/tmp$
確認してみます。gccでビルドしてから、
takk@deb9:~/tmp$ ./a.out -s5 -v1 1.bin takk@deb9:~/tmp$ od -tx1 1.bin 0000000 01 01 01 01 01 0000005 takk@deb9:~/tmp$ ./a.out -s7 -v2 1.bin takk@deb9:~/tmp$ od -tx1 1.bin 0000000 01 01 01 01 01 02 02 0000007 takk@deb9:~/tmp$
-sと-vは、自分で作ったオプションなので、分かりやすいです。
ファイルと同じサイズを指定した場合は、以下のとおりファイルは更新されません。
takk@deb9:~/tmp$ ls -l 1.bin -rw-r--r-- 1 takk takk 7 4月 7 20:22 1.bin takk@deb9:~/tmp$ sleep 10 takk@deb9:~/tmp$ ./a.out -s7 -v3 1.bin takk@deb9:~/tmp$ ls -l 1.bin -rw-r--r-- 1 takk takk 7 4月 7 20:22 1.bin takk@deb9:~/tmp$
数列をバイナリにしてみます。1~16までの値が詰まったバイナリデータとなります。
takk@deb9:~/tmp$ rm *.bin takk@deb9:~/tmp$ for i in `seq 16`;do ./a.out -s$i -v$i a.bin b.bin;done takk@deb9:~/tmp$ ls -l *.bin -rw-r--r-- 1 takk takk 16 4月 7 20:27 a.bin -rw-r--r-- 1 takk takk 16 4月 7 20:27 b.bin takk@deb9:~/tmp$ od -tx1 -Ax a.bin 000000 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 000010 takk@deb9:~/tmp$ cmp a.bin b.bin takk@deb9:~/tmp$
コメント