lC言語 サンプル (ダンプ) '97. .  
l.お知らせ 内容 LINK FILE   HTML Win PC Unix MS-DOS C C++ Mfc Java 
.C言語_ 3 フォ-マットコ-ド 6 演算子 9 FOR  集合デ-タ  目的別
1 表示してみる 4 変数と定数 7 条件判断 10 WHIILE  ポインタ     
2 エスケ-プ コ-ド 5 デ-タ入力 8 分岐   未使用  関数   ★ 
 用法  文章のコピー  参考ページ 
 (サンプル)...   乱数  ダンプ  その他( 基本  応用 ) 

旧バージョンの MS-DOS に付属していた DUMP コマンドと同じ機能です。

表示できるファイルサイズの制限はありません。
大きなファイルは、直接表示するよりも、リダイレクトコマンド >> を使ってテキストファイルに書込むと見易くなります。

/***** DUMP2.c ダンププログラム *****/
/* ファイルをダンプします。( データを 16進数の数字で表示します。) */
/* ダンプするファイルの指定方法。                                 */
/*  1.起動時に、コマンドラインで指定します。                    */
/*  2.起動後に、メッセージに従って指定します。                  */
/* 扱えるファイルのサイズは unlong unsigned long int の範囲です。 */
/* 16 バイトずつ読み出して処理するので、実際上の制限はありません。*/
/* ( ソース 1.5MB → ダンプ 7MB まで確認。)                       */

/* 実行例 */
/* 000000 30 31 32 33 34 ...(省略)... 44 45 46  0123456789ABCDEF  */
/* 000010 0D 0A 8F 49 82 E8                     ..終り            */
/*  [0x000016]  22 バイト                                         */
/* ※ 右側の参考文字列は、シフトJISのみ正常に表示されます。   */
/*     JISなどでは、意味不明の文字列に変換されます。           */

/* ダンプしたファイルは テキストですから、 編集可能です。         */
/* ダンプしたファイルは、PATCH2 で元の形式のファイルに戻せます。  */


#include       /* printf       */
#include      /* fopen        */
#include          /* fileno       */
#include         /* farmalloc    */
#include      /* getcwd       */
#include      /* strcpy       */
#define unlong unsigned long int /* 変数の型名が長すぎるので別名を使用 */


/**◆◆ メイン関数 ◆◆******************************************/
int main(int argc, char *argv[]) /* コマンドラインを使う。 */
{
/***** 変数の宣言 ***********************************************/
char f_buf[125];        /* ファイル名入力バッファ         */
char fname[125], *cs;   /* ファイル名バッファ( \/ 変換用) */
char buf[32];           /* 読み出しバッファ               */
char cd_buf[125], *pcd; /* カレントディレクトリバッファ   */
FILE *fp;               /* ファイルポインタの宣言。       */
int fd;                 /* ファイルハンドル格納用         */
long size;              /* ファイルサイズ格納用           */
char ss[20];            /* 変換バッファ(非表示コードを . で表示) */
unlong i, j, k, z;      /* ループ用の変数                 */
unlong a0, a1;          /* 3 桁表示用                     */
char hc='\0';           /* これは2バイト文字の表示処理に使います*/

fprintf(stderr,"\33[2J"); /* 画面消去 */
/* リダイレクトした場合の為に、出力先はディスプレーにします。 */

/***** ファイル名の決定 ***************************************/
pcd=getcwd(cd_buf, 120); /* カレントディレクトリ取得          */
if( argv[1]==NULL )      /* コマンドラインにファイルの指定がなければ */
{ fprintf(stderr,"現在のディレクトリ = %s\n",pcd);
  fprintf(stderr,"ファイル名 = ");   gets(f_buf);
}
else{ strcpy(f_buf, argv[1]); } /* コマンドラインにファイルの指定があれば */

if( (f_buf[0]=='\\')||(f_buf[1]==':') )	/* 絶対パス指定のとき  */
{ if(f_buf[1]==':')             /* ドライブの指定があるなら、  */
  { strcpy(fname, f_buf); }     /* そのまま使用。              */
  else                          /* \C86 のような指定なら、     */
  { strncpy(fname, pcd, 2);     /* fname=C:                    */
    strcat(fname, f_buf);       /* fname=C: \aa\ABC\txt        */
  }
}
else                            /* 相対パス指定のとき          */
{ strcpy(fname, pcd );          /* fname=カレントディレクトリ  */
  if(fname[3] != 0)             /* C:\ ならそのまま。          */
  strcat(fname, "\\");          /* C:\aa なら、C:\aa\ にする。 */
  strcat(fname, f_buf);         /* C:\aa\ ABC\txt にする。     */
}
/***** ダンプしたいファイル名(とパス)が確定した。***************/
/***** Cでは \ が使えないので、/ に変更します。****************/
strcpy(f_buf, fname);           /* 変更前のファイル名を保存    */
for( cs=fname, i=0; i<125; i++ )/* \ を / に変更する。         */
{  cs=strchr(cs, '\\');
   if(cs == 0) { break; }
   else { *cs='/'; cs++; }
}
/***** fname は、\ が / に変換された。(f_buf はそのまま。) *****/
/***** ダンプしたいファイルをオープンします。*******************/
fp=fopen( fname, "rb" );        /* ファイルをオープン          */
if(fp==NULL)
{ fprintf(stderr,"\n%s\nファイルが見つかりません。\n\n",f_buf);
  return -1;
}
fd=fileno(fp);                  /* ファイルハンドルの読み出し  */
size=filelength(fd);            /* ファイルサイズの読み出し    */
if(size==-1L)
{ fprintf(stderr,"ファイルサイズ読み出し失敗\n\n"); return -1; }


/***◆ ダンプ ◆*************************************************/
/***** ファイルを読み出し、16 バイトずつダンプします。***********/
printf("\n");
z=size;  /* ファイルサイズ = filelength(fd) で読み出した値。    */
k=0;     /* 16 個ずつ表示するデータの、カウンタ                 */
         /* データを 16 個表示する毎に k を+16 します。        */
         /* 全部で何個目かは、j でカウントします。              */
         /* 16 個の内の何個目かは、i でカウントします。         */

while(k < z)
{ fseek( fp, k, 0 );             /* 読み出し位置の設定です。    */
  /* 読み出し位置の基準 : 0=先頭 1=現在位置 2=ファイルの最後  */
  /* この例では、別に1バイト読み出す場合があります。下記★位置 */
  /* その為、16 バイト毎に読み出し位置を指定しています。        */
  fread(buf, 1, 16, fp);         /* buf に、16 バイトを読み出す */
  printf("%06lX  ",k);           /* 読出し順番を 16進 6桁で表示 */

  /* 続けてデータを、16 バイトずつ 16 進表示します。*/
  for(i=0, j=k; i<16; i++, j++)
  { if(j < z)
    { printf("%02X ",buf[i] ); } /* 7と8の間にスペースを追加。*/
    else                         /* 途中でファイルが終りのとき  */
    { printf("   "); }           /*  右端を揃えるためのスペース */
    if( i==7 ) printf(" ");      /* 7と8の間にスペースを追加。*/
  }
/****************************************************************/

printf(" ");
/***************************************************************/
  /* 続けてデータを、16 バイトずつ 文字として表示します。      */
  for(i=0, j=k; i<16; i++, j++)
  { if( hc != 0) /* 前の行末が2バイト文字の半分だったときは、 */
    { ss[0]=' ';    /* 1バイトは表示済みだからスペースを格納  */
      hc=0;         /* 処理したので、hc をクリアします。       */
    }
    else if( j < z ) /* ファイルサイズ以内のとき */
    { if( buf[i] < 0x80 )
      { if( buf[i] < 0x20 )    /* 20 以下の非文字なら、        */
        { ss[i]='.'; }         /*  ss[ ] に . を格納           */
        else                   /* 英数文字なら、               */
        { ss[i]=buf[i]; }      /*  そのまま ss[ ] に格納       */
      }
      else                /* 80→ */
      { if( (buf[i]>0x9F)&&(buf[i]<0xE0) ) /* 半角カナなら、    */
        { ss[i]=buf[i]; }      /*  そのまま ss[ ] に格納        */
        else                   /* 2バイト文字の1バイト目なら、*/
        { ss[i]=buf[i];        /*  まず、1バイトを格納。       */
          i++; j++;            /*    カウンタを +1 する。       */
          if( i<16 )           /*  16 バイト目でなければ、      */
          { ss[i]=buf[i]; }    /*    次の1バイトをそのまま格納 */
          else                 /*  16 バイト目のときは、        */
          { fread(buf, 1, 16, fp); /* buf に、1バイトを読み出す★*/
            ss[i]=buf[0];      /* ss[ ] の最後に追加する。      */
            hc=3;              /* フラグを立てる                */
            /* 次の 16 バイトの先頭で、残り半分を表示しないため */
            /* もし次の行頭で、2バイト文字の残りを表示すると変 */
          }
        }
      }
    }
    else    /* ファイルサイズを越えていたときは、      */
    { ss[i]=0; }    /*  を格納する。                   */
  }
  /*** 文字バッファ ss に、16 バイト分の文字が格納されました。***/

  ss[i]=0;              /* バッファの最後に、\0 を格納           */
  printf("%s\n",ss);    /* 文字として表示します。                */
  k += 16;              /* 処理済みデータ数を 16 個プラスする。  */

  /*** ここで、中断を選択できるように、キー入力を受け付けます。***/
  if( kbhit( ) ) /* キーが押されたなら */
  { if( getch( )==0x1B )            /* Esc キーなら              */
    { fprintf(stderr,"--中断--\n"); /* メッセージを表示して、    */
      exit( 0 );                    /* 終了します。              */
    }
    /* それ以外なら無視します。( Ctrl+C による中断は可。)        */
  } /* 次の 16 バイトのダンプを継続します。*/
}
/** 16 個ずつ、ファイルサイズの最後まで、表示が完了しました。 ****/
/*****************************************************************/

/***** 最後にファイルサイズを表示します。*************************/
printf(" ");            /*** まず行頭に スペースを表示します。****/
/* このスペースは、ダンプデータを処理する場合に、                */
/* データの最後を識別するために使用します。                      */
/* ダンプの表示をするだけなら必要ではありません。                */

/*** まず、16 進表示します。( 例 0x000012B )***/
printf("[0x%06lX]  ",size ); /* 16進6桁表示。空桁には0を表示。  */

/*** 次に、十進表示します。( KB と バイト )***/
/* ファイルサイズ size は、三桁毎に区切って表示することにします。*/
a0=size+51;           /*  51B=0.0498KB ...後で四捨五入する代わり */
a1=(a0)/1024;         /* a1 = a0 をキロバイトに変換              */
a0=a0-a1*1024;        /* a0 = KB 未満の部分。                    */
                      /*  メモ : 整数計算では小数は捨てられます。*/

/***** キロバイト表示します。( 例 12,000KB )****/
/* まず、1000k バイト以上の部分を表示します。  */
if(a1>0)     /* 1KB 以上のときだけ表示します。 */
{ if(a1>1000)
  { printf("%ld,",a1/1000 ); /*   1000kB 以上だけをを表示します。 */
    a1=a1-(a1/1000)*1000;    /*    表示した分を引きます。         */
  }                  /* メモ : 整数計算では、小数は捨てられます。 */
  /* これで、a1 の値は、0〜999 になっています。*/

  /* 次に、1KB〜999KB の部分を表示します。     */
  if(a1>1000)                   /* 1,000 以上が表示済みなら、     */
  { printf("%03ld.",a1 ); }     /*   0を含む3桁表示します。     */
  else                          /* 1,000 未満のときは、           */
  { printf("%3ld.",a1 ); }      /*   普通に3桁表示します。       */

  /* 次に、KB 未満の部分を1桁だけ表示します。                    */
  a1=a0/102;
  printf("%ldKB    ( ",a1);
}

/***** バイト表示します。( 例 12,000,000バイト )*****/
/* まず、1,000,000 バイト以上の部分を表示します。   */
a0=size;
if(a0>1000000)             /* 1,000,000 バイト以上なら、   */
{ a1=a0/1000000;           /* 第7桁以上を取り出します     */
  printf("%3ld,",a1);       /*   3桁表示します。          */
  a0=a0-a1*1000000;        /* 表示した分を引きます。       */
}

/* 次に、残っている 1,000 バイト以上の部分を表示します。   */
if(a0>1000)                /* 1,000 バイト以上なら、       */
{ a1=a0/1000;              /* 第4桁以上を取り出します     */
  if( size>=1000000 )      /* 第7桁以上が表示済みなら、   */
  { printf("%03ld,",a1); }  /*   0を含む3桁表示します。  */
  else                     /* 第7桁以上がなかったときは、 */
  { printf("%3ld,",a1); }   /*   普通に3桁表示します。    */
  a0=a0-a1*1000;           /* 表示した分を引きます。       */
}

/* 次に、残っている 1,000 バイト未満の部分を表示します。   */
  if( size>=1000 )         /* 第四桁以上が表示済みなら、   */
  { printf("%03ld",a0); } /*   0を含む3桁表示します。   */
  else                     /* 第四桁以上がなかったときは、 */
  { printf("%3ld",a0); }   /*   普通に3桁表示します。     */

printf(" バイト");
/* キロバイト表示してあるときは、( を表示してから          */
/* バイトの表示がされているので、) も表示します。          */
if(size > 1024) printf( " )" ); printf("\n");

/***** 終了 ************************************************/
if ( -1==fclose(fp) )
{ fprintf(stderr,"ファイルのクローズに失敗しました。\n\n");
 return -1;
}
fprintf(stderr,"---終了---\n");
return 0;              /* 正常終了                         */

} /*** ← main() の終り。 ***/
このままコンパイルした場合は次のように使用します。
DUMP2.EXE DUMP2.C ... DUMP2.C をダンプ表示します。
DUMP2.EXE DUMP2.C >> TEST.TXT ... DUMP2.C のダンプを TEST.TXT に追加書込みします。


T

  mtoga@sannet.ne.jp   登録日 '96. 6.15
URL : http://www.page.sannet.ne.jp/mtoga/index.html