statを使ったファイルサイズの取得方法を覚えたところで、まだまだしょぼい自作truncateのプログラムを改造します。
これが先回作ったtruncateプログラムです。
takk@deb9:~/tmp$ cat -n mytruncate.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,tmp[100]; 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 tmp[len]=ch; 42 } 43 fclose(fp); 44 if(len < size){ 45 fp = fopen(argv[optind],"a"); 46 for(i=len; i<size; i++) 47 fputc(value,fp); 48 fclose(fp); 49 }else if(len > size){ 50 fp = fopen(argv[optind],"w+"); 51 for(i=0; i<size; i++) 52 fputc(tmp[i],fp); 53 fclose(fp); 54 } 55 } 56 } 57 return 0; 58 } 59 takk@deb9:~/tmp$
statを使うためのヘッダを追加
変更前
#include <stdio.h> #include <stdlib.h> #include <unistd.h>
変更後
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> 追加 #include <sys/stat.h> 追加 #include <unistd.h>
statを使うための構造体変数定義追加。
変更前
int main(int argc, char* argv[]) { FILE *fp; int i,len,size=0; int value=0; int ch,tmp[100];
変更後
int main(int argc, char* argv[]) { FILE *fp; int i,len,size=0; int value=0; int ch,tmp[100]; struct stat buf; 追加
fopen~fgetc~floseで全部読み込んでファイルサイズ算出していた部分を、statでファイルサイズ取得するように置き換える。
変更前
}else{ fp = fopen(argv[optind],"r"); for(len=0; (ch=fgetc(fp)) != EOF; len++){ tmp[len]=ch; } fclose(fp);
}else{ stat(argv[optind],&buf); 変更 len =buf.st_size; 変更
ここが問題。
パラメータで指定したサイズがファイルサイズより小さい場合の処理。
前より処理が長くなってしまいます。
変更前
}else if(len > size){ fp = fopen(argv[optind],"w+"); for(i=0; i<size; i++) fputc(tmp[i],fp); fclose(fp); }
変更後
}else if(len > size){ fp = fopen(argv[optind],"r"); 追加 for(len=0; (ch=fgetc(fp)) != EOF; len++){ 追加 tmp[len]=ch; 追加 } 追加 fclose(fp); 追加 fp = fopen(argv[optind],"w+"); for(i=0; i<size; i++) fputc(tmp[i],fp); fclose(fp); }
ファイルを短くする場合に、元データをtmp配列にコピーしてから、上書きしているので、
どうしても読み込み処理が増えてしまいます。次回はこの辺りも改造します。
改造後の全ソースです。
takk@deb9:~/tmp$ cat -n mytruncate.c 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <sys/types.h> 4 #include <sys/stat.h> 5 #include <unistd.h> 6 7 int main(int argc, char* argv[]) 8 { 9 FILE *fp; 10 int i,len,size=0; 11 int value=0; 12 int ch,tmp[100]; 13 struct stat buf; 14 15 while ((ch = getopt(argc, argv, "s:v:")) != -1){ 16 switch (ch) { 17 case 's': 18 size = atoi(optarg); 19 break; 20 case 'v': 21 value = atoi(optarg); 22 break; 23 default: 24 printf("parameter error\n"); 25 return 1; 26 } 27 } 28 29 if(optind >= argc){ 30 printf("parameter error\n"); 31 return 1; 32 } 33 34 for(; optind<argc; optind++){ 35 fp = fopen(argv[optind],"r"); 36 if(fp == NULL){ 37 fp = fopen(argv[optind],"w"); 38 for(i=0; i<size; i++) 39 fputc(value,fp); 40 fclose(fp); 41 }else{ 42 stat(argv[optind],&buf); 43 len =buf.st_size; 44 if(len < size){ 45 fp = fopen(argv[optind],"a"); 46 for(i=len; i<size; i++) 47 fputc(value,fp); 48 fclose(fp); 49 }else if(len > size){ 50 fp = fopen(argv[optind],"r"); 51 for(len=0; (ch=fgetc(fp)) != EOF; len++){ 52 tmp[len]=ch; 53 } 54 fclose(fp); 55 fp = fopen(argv[optind],"w+"); 56 for(i=0; i<size; i++) 57 fputc(tmp[i],fp); 58 fclose(fp); 59 } 60 } 61 } 62 return 0; 63 } 64 takk@deb9:~/tmp$
ビルドして確認。
takk@deb9:~/tmp$ gcc mytruncate.c takk@deb9:~/tmp$ echo HELLO > 1.bin takk@deb9:~/tmp$ ./a.out -s10 1.bin takk@deb9:~/tmp$ wc -c 1.bin 10 1.bin takk@deb9:~/tmp$ ./a.out -s4 1.bin takk@deb9:~/tmp$ wc -c 1.bin 4 1.bin takk@deb9:~/tmp$ od -tx1c 1.bin 0000000 48 45 4c 4c H E L L 0000004 takk@deb9:~/tmp$
まだまだです。
コメント