• ベストアンサー

Windowsファイルのサイズの問題

ネットでWindowsのファイルのサイズを計算するサンプルをみています。 ひとつのサンプルをみても、わからないですので、知っている方に質問したいです。 サンプルは WFDはWIN32_FIND_DATA構造体の変数で、 DWORD dwHigh = WFD.nFileSizeHigh; DWORD dwLow = WFD.nFileSizeLow; __int64 nSize; int nLen; char szTemp[MAX_PATH]; char* p; int nCnt; nSize = dwHigh; nSize = (nSize << 32) + 1023; nSize += dwLow; nSize = (nSize >> 10); //KB単位にする いくつの問題があります。 ●ファイルのサイズは、どうしてこんなに計算するの?  どう計算するの? ●(nSize << 32) とnSize >> 10 はなにをやっているの? よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • chie65535
  • ベストアンサー率43% (8514/19356)
回答No.4

>nSize = dwHigh; >nSize = (nSize << 32) + 1023; >nSize += dwLow; >nSize = (nSize >> 10); //KB単位にする >●ファイルのサイズは、どうしてこんなに計算するの? > どう計算するの? 判りやすく書くと nSize = dwHigh; nSize = (nSize << 32); nSize += dwLow; と nSize += 1023; nSize = (nSize >> 10); //KB単位にする です。 前半はnSizeの上位32ビットにdwHighを、下位32ビットにdwLowを入れています。 nSize = dwHigh; まず、nSizeにdwHighを入れます。この状態でnSizeの下位32ビットにdwHighが居ます。 nSize = (nSize << 32); 本来、dwHighは上位32ビットに居て欲しいので、nSizeを左に32ビットシフトし、それをnSizeに入れます。この状態でnSizeの上位32ビットにdwHighが居ます。下位32ビットは0になっています。 nSize += dwLow; nSizeにdwLowを足せば、上位32ビットはそのまま。下位32ビットにdwLowが入ります。この状態でnSizeの上位32ビットにdwHighが居ます。下位32ビットにdwLowが居ます。 これで、nSizeには、64ビットのファイルサイズが入りました。 後半は、ファイルサイズを「キロバイト単位」にしています。 nSize += 1023; nSizeに1023を足して、端数を切り上げる準備をしています。 0→1023 1~1024→1024~2047 1025~2048→2048~3095 のようになります。 nSize = (nSize >> 10); //KB単位にする nSizeを右に10ビットシフトすると、1024で割った事になります。 0→1023→0キロバイト 1~1024→1024~2047→1キロバイト 1025~2048→2048~3095→2キロバイト のようになります。 >●(nSize << 32) とnSize >> 10 はなにをやっているの? 上の説明でもう判りますね。

その他の回答 (3)

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.3

たとえば右シフトは 16の右シフトを考えると 16は 2進で1 0000と表現します 16 >> 1 を実行すると 1000(8) つまり1/2 16 >> 2 ならば 0100(4) つまり1/4 16 >> 3 ならば 0010(2) つまり1/8 16 >> 4 ならば 0001(1) つまり1/16 ということになります つまり >> は 2のn乗で除算することになります

noname#208124
noname#208124
回答No.2

こればっかりはCPUの中では全て2進数だということとビット演算を勉強して貰わないとあまりにも長くなるので長くなるので参考リンクを ファイルサイズが負数になることも、現行のWindowsでは最上位の符号ビットが1になってしまうようなファイルサイズも「まだ」扱うことはないので算術シフトか論理シフトかは今は問題になりません 割り算もシフトも余りは切り捨てです ちょうど1024の倍数にならない場合の余りは1~1023 余りに+1023をすれば1024~2046、それに対しての÷1024は必ず1になるのでその分切り上げとして扱えます ちょうど1024の倍数の時は+1023は端数にしかなれないので答えは変わりません

参考URL:
http://kccn.konan-u.ac.jp/information/cs/cyber03/cy3_shc.htm
noname#208124
noname#208124
回答No.1

64ビット整数の上位と下位それぞれ別々に32ビットの変数に入ってるからまとめてあげないとちゃんと使えないから <<32で下位に代入した32ビット分を64ビット整数の上位に移動 >>10は1024で割り算 CPUでは除算よりシフト演算の方が速いから でもまともなコンパイラなら除算で書いても最適化すれば同じコード出すんで普通に書いとけと +1023は切り上げのため こういうコードの時はLARGE_INTEGER使った方が書きやすい

ikutame
質問者

お礼

回答してくれてありがとうございました。 ●<<32で下位に代入した32ビット分を64ビット整数の上位に移動  これについてなんとかイメージできますが、 ●>>10は1024で割り算  これはわからないので、詳しく教えていただけませんか? ●+1023は切り上げのため  これもイメージできないので、説明していただけませんか? よろしくお願いします。

関連するQ&A

  • フルパスのファイル名からフォルダを作成したい。

    フルパスのファイル名を参照し、フォルダが無ければ作成するというプログラムを作成したいのですが、漢字も混在していて、その第2コードが0x5c(\)の場合もあるため、正常に動作しません。 言語 VisualC++6.0 ファイル名(pszPath) c:\test\売上実績表\10月実績表.xls void CFTWnd::MakePath(char* pszPath) { WIN32_FIND_DATA find; HANDLE h; char szTmp[_MAX_PATH]; UINT nLen; UINT i; ZeroMemory(szTmp, _MAX_PATH); nLen = strlen(pszPath); szTmp[0] = pszPath[0]; szTmp[1] = pszPath[1]; szTmp[2] = pszPath[2]; for( i = 3; i < nLen; i++ ) { if( pszPath[i] != '\\' ) { szTmp[i] = pszPath[i]; } else { if( (h = FindFirstFile(szTmp, &find)) != INVALID_HANDLE_VALUE ) { FindClose(h); } else { _mkdir(szTmp); } szTmp[i] = pszPath[i]; } } } 「表」の第2コードが0x5c(\)という事もあり、余計なフォルダが作成されてしまいます。 何か良い方法があったら教えて下さい。 よろしくお願いします。

  • ファイルサイズを変更したい

    visualstudio2010を使用しています。 c言語で書いているのですが、 test.txt ←abcdefg ファイルサイズ1KB Wtest.txt←書き込み用ファイル 上記のようなファイルがあり、バイナリでtest.txtを読み込みWtest.txtに書き込みたいと思っています。 その際に、1KBのtest.txtを5KBになるまでバイナリで「abcdefg」の後に0を代入したいのですがどう書けば良いのかわかりません。 FILE *fp, *fpw; char *fname = "test.txt"; char *fname_w = "Wtest.txt"; unsigned char buf[10000]; int size; fp = fopen( fname, "rb" ); if( fp == NULL ){ printf( "%sファイルが開けません\n", fname ); return -1; } fpw = fopen(fname_w, "wb"); if(fpw == NULL){ printf( "%sファイルが開けません\n", fname_w ); return -1; } size = fread( buf, sizeof( unsigned char ), sizeof (fp), fp ); /*ここに処理を追加したい*/ fwrite( buf, sizeof( unsigned char ), size, fpw);

  • waveファイルの8bitデータの調整

    VS2003.NET/C++でプログラミングをしています。 今、WAVEファイルで音声データを取って、フェードを掛けようと思うのですが、8bitだと上手くいきません。  16bitの場合は、2byte分読み込み、それから小数で割っているんですが、8bitの場合、1byteに左チャネル、2byte目には右チャンネルといった形で格納されているはずなんですがそのようにしても上手くいきません。  上手くいった16bitデータの音量調整を下記に載せておきます。 8bitにするにはどうしたらいいでしょうか? int nMeter; <- 音量を100分割で表す int nSize; <- データのサイズ LPBYTE lpData1; <- 相手の音声 LPBYTE lpData2; <- 音声を加工 // サイズ分を加工 for( int i = 0; i < nSize; i+=2 ) { // 16bit なので 2BYTEずつ確保 char n1 = (char)( lpData1[ i + 0 ] ); char n2 = (char)( lpData1[ i + 1 ] ); // nMeter で音量調整(倍率をかける) int n = (int)( (float)( ( n2 << 8 ) | ( n1 & 0xFF ) ) * (float)( nMeter / 100.0f ) ); // 加工済みデータを保存 lpData2[ i + 0 ] = ( n & 0x00FF ) >> 0; lpData2[ i + 1 ] = ( n & 0xFF00 ) >> 8; } 上手くいってない8bit版は次の通りです int nMeter; <- 音量を100分割で表す int nSize; <- データのサイズ LPBYTE lpData1; <- 相手の音声 LPBYTE lpData2; <- 音声を加工 // サイズ分を加工 for( int i = 0; i < nSize; i+=4 ) { // 16bit なので 2BYTEずつ確保 char n1 = (char)( lpData1[ i + 0 ] ); char n2 = (char)( lpData1[ i + 1 ] ); n1 -= 128; n1 * (int)(bMeter / 100.0); n2 * (int)(bMeter / 100.0); n1 += 128; n2 += 128; // 加工済みデータを保存 lpData2[ i + 0 ] = n1; lpData2[ i + 1 ] = n2; } よろしくお願いします。

  • プログラミングの問題が分かりません。どなたか助けて

    こんな問題が出たのですがまったくもってわかりませんだれか助けてください センサーから入力される符号付き8ビット(char)の入力を一定期間ため込み,値が入力される度に,その平均値を計算し続けるシステムを考える.実装の方法にはいろいろ種類があるが,ここでは,配列をリングバッファとして利用する.リングバッファは,実際にデータを蓄える buffer という名の char 型の配列,最後にサンプル値を代入した位置を示す変数 pos という名の int 型の変数および現在のデータの総和を示す int 型変数 sum を要素に持つ構造体で作成する.リングバッファに値が挿入されるときは,以下の作業を行う. pos を一つ増やす pos がバッファのサイズを超えていたら pos を 0 にする sum から pos の位置のバッファの値を引く リングバッファに挿入したい値を pos の位置のバッファに書く 今挿入した値を sum に足す sum をバッファの長さで割り算して平均値を出力する ここでは,効果的な計算のために,リングバッファのサイズを 128 とする.そのため,変数 pos は 0 から 127 までの値を持つことになる. という問題でこのプログラムを書いてみたいのですがわかりません どなたか教えてくれませんか?

  • ネットで落ちていた「Excelで作ったデータ(CSVファイル)の読み込

    ネットで落ちていた「Excelで作ったデータ(CSVファイル)の読み込みプログラム」をそのままコンパイルして実行しようと思ったのですが、 sample.c: In function 'main': sample2.c:9: warning: return type of 'main' is not 'int' と、表示されてしまいます。 プログラミング初心者なので、どこが間違っているのかわかりません。 回答またはアドバイスの程、よろしくお願いいたします。 ネットで落ちていたプログラムを以下に記載します。 sample2.c #include <stdio.h> #define MAX_ITEM_SIZE 100 #define MAX_LINE_SIZE 1024 char *GetCSVItem(char *wp, char *buff, int size); void main(int argc, char *argv[]) { FILE *fp; char buff[MAX_LINE_SIZE], *wp, item[3][MAX_ITEM_SIZE]; int i1, len; if(argc != 2){ printf("コマンドの入力形式が間違っています.\n"); return; } fp = fopen(argv[1], "r"); if(fp == NULL){ printf("ファイルがオープンできません[%s].\n", argv[1]); return; } for(;;){ if(fgets(buff, MAX_LINE_SIZE, fp) == NULL) break; len = strlen(buff); if(len == 0 || buff[len-1] != '\n'){ if(feof(fp) == 0){ printf("データが不正です[%s].\n", buff); return; } } buff[len-1] = '\0'; wp = buff; if((wp = GetCSVItem(wp, item[0], MAX_ITEM_SIZE)) == NULL){ printf("エラー(1)\n"); break; } if((wp = GetCSVItem(wp, item[1], MAX_ITEM_SIZE)) == NULL){ printf("エラー(2)\n"); break; } if((wp = GetCSVItem(wp, item[2], MAX_ITEM_SIZE)) == NULL){ printf("エラー(3)\n"); break; } if(*wp != '\0'){ printf("エラー(4)\n"); break; } for(i1 = 0; i1 < 3; i1++){ printf("%d:%s\n", i1+1, item[i1]); } } fclose(fp); } char *GetCSVItem(char *wp, char *buff, int size) { int i1; buff[0] = '\0'; while(*wp == ' ' || *wp == '\t') wp++; if(*wp == '\0'){ return(NULL); } for(i1 = 0; i1 < MAX_ITEM_SIZE; i1++, wp++){ if(i1 >= size) return(NULL); buff[i1] = *wp; if(*wp == '\0'){ buff[i1] = '\0'; return(wp); } if(*wp == ','){ wp++; buff[i1] = '\0'; break; } } return(wp); }

  • 間接参照のレベルが異なっています

    単語を昇順でソートするプログラミングでエラーが出て困っている者です。 エラーが出てる箇所のみ抜粋して、あとは省略したものが下記です。 下記の2つの関数の下の方の関数で 間接参照のレベルが'char **'と'char[10][20]'で異なっています read_wordsの型が2の仮引数および実引数と異なります と言うエラーが現れます。main関数内のsortword関数、display_words関数でも同様にエラーが現れます。 これらの原因は何でしょう。また、僕は何がわかってないですか? ここどこを勉強しろ、等のアドバイスでも結構ですのでぜひご指導ください。お願いします。 #include<stdio.h> #include<stdlib.h> #include<string.h> #define LINE_SIZE 20 #define MAX_LINES 10 char line[MAX_LINES][LINE_SIZE]; int num; int read_words(char *fname,char **line,int num)//用意した構造に文字列を格納 { FILE *fp;//ファイルポインタの宣言 int i = 0;//繰り返し変数の初期化 if((fp = fopen(fname,"r")) == NULL)//ファイルがあるかの確認 { printf("ファイルを開けません\n");//ファイルが無い時はエラーメッセージを出す exit(1);//エラー時は強制終了 } fp=fopen(fname,"r"); fscan(fp,"%d",&line); for(i=0;i<MAX_LINES;i++)//1列ずつ文字列を入れる制御構造 { fscanf(fp,"%s",&line[i]);//ファイルから文字列を変数に入力 i++;//繰り返し変数の増加 } num=line[0];//単語数を戻り値とする fclose(fp);//ファイルのクローズ } int main(int argc,char *argv[]) { read_words(argv[1],line,int num); sortword(line,num); display_words(line,num); }

  • ダブルポインタ?

    下記のような関数が存在し、 最終的には mainで宣言した変数 "a" にDataGetでコピーしたデータを mainで再び使用したいのですが、 下記の方法だとmainに何も帰ってきません。 (NULLのまま・・・) 下記の関数を使用しmainに上手くデータを 引き継ぐためにはどうすれば良いのでしょうか? void Mem(int nSize,void **ptr){ char *tmp; tmp = malloc(nSize); *ptr = tmp; } void DataGet(char *aa,char *a){ int nSize = 5; (void)Mem(nSize,(void **)&a); memcpy(a,aa,nSize); return; } void main(){ char aa[20]; char *a = 0x00; memset(aa,0x00,20); memcpy(aa,"test",4); (void)DataGet(aa,a); /* aデータをここから再び使いたい */ }

  • ファイルサイズについて

    ファイルサイズについての質問です。 MOに保存してある友人の作った画像入りの文書(A4が1枚)を見たのですが、画面の動きがにぶかったので、ファイルサイズを確認してみたところ、とても大きかった(23MB)のです。 貼り付ける前の画像サイズなどを確認したら、700KBのものが1枚あったことと、サイズは小さい(32KB)ですが、ホームページビルダーでフレームをつけて加工したものがひとつありました。 残りの画像は7枚で、それぞれが70KB前後です。 そのあと、画像を抜いて、記事と見出しだけ、枠と見出しだけなどに分けて確認してみましたがそれぞれ30KBもありませんでした。 単純計算しても23MBには程遠いので、新規文書を開いて元文書から記事、見出し、画像の順にコピーして貼りつけたところ、思いきり小さく(647KB)なりました。(リサイズした画像は700KBのものだけで、それは125KBになりました) 同じ画像が下に入り込んでいるのかとも思ったのですがそうではなく、何とも不思議な状況になっているのです。 このような質問でおわかりいただけるでしょうか? 説明不足の点などがありましたら申し訳ありません。 どうかよろしくお願いします。

  • FMFファイルの構造を知りたいのですが

    FMFファイルの構造を知りたいのですが (intや型char型などの)どうやって調べればよいのでしょうか?

  • cygwinを使ってcsvファイルを読み込み、出力させようとしています

    cygwinを使ってcsvファイルを読み込み、出力させようとしています。 とりあえず、読み込みのみのプログラムを作成し、 実行させてみたのですが(run ファイル名.csv と入力) 「Error: could not start C:\cygwin\home\ユーザー名ファイル名.csv」 と出力され、読み込みができず、困っています。 プログラム初心者です。 恐縮ですがご回答よろしくお願いします。 以下に、読み込みプログラムとcsvファイルを記載します。 (プログラムは拾い物です。) <プログラム> #include <stdio.h> #define MAX_ITEM_SIZE 100 #define MAX_LINE_SIZE 1024 char *GetCSVItem(char *wp, char *buff, int size); void main(int argc, char *argv[]) { FILE *fp; char buff[MAX_LINE_SIZE], *wp, item[3][MAX_ITEM_SIZE]; int i1, len; if(argc != 2){ printf("comand error nyuuryoku keishiki\n"); return; } fp = fopen(argv[1], "r"); if(fp == NULL){ printf("can not open file[%s].\n", argv[1]); return; } for(;;){ if(fgets(buff, MAX_LINE_SIZE, fp) == NULL) break; len = strlen(buff); if(len == 0 || buff[len-1] != '\n'){ if(feof(fp) == 0){ printf("data error[%s].\n", buff); return; } } buff[len-1] = '\0'; wp = buff; if((wp = GetCSVItem(wp, item[0], MAX_ITEM_SIZE)) == NULL){ printf("error(1)\n"); break; } if((wp = GetCSVItem(wp, item[1], MAX_ITEM_SIZE)) == NULL){ printf("error(2)\n"); break; } if((wp = GetCSVItem(wp, item[2], MAX_ITEM_SIZE)) == NULL){ printf("error(3)\n"); break; } if(*wp != '\0'){ printf("error(4)\n"); break; } for(i1 = 0; i1 < 3; i1++){ printf("%d:%s\n", i1+1, item[i1]); } } fclose(fp); } char *GetCSVItem(char *wp, char *buff, int size) { int i1; buff[0] = '\0'; while(*wp == ' ' || *wp == '\t') wp++; if(*wp == '\0'){ return(NULL); } for(i1 = 0; i1 < MAX_ITEM_SIZE; i1++, wp++){ if(i1 >= size) return(NULL); buff[i1] = *wp; if(*wp == '\0'){ buff[i1] = '\0'; return(wp); } if(*wp == ','){ wp++; buff[i1] = '\0'; break; } } return(wp); } <csvファイル> 1,2,3 11,12,13 21,22,23

専門家に質問してみよう