マイtruncateを作る(その4)

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$ 

まだまだです。

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA