バイナリデータのファイルを扱う上での最適な方法は?

このQ&Aのポイント
  • バイナリデータのファイルを扱う上で、wchar_t を基本にプログラムを書き換えようとしていますが、_wfopen と CreateFile のどちらが扱いやすいか検討しています。
  • バイナリファイルを扱いやすくするために、_wfopen と CreateFile を比較しています。
  • 古い形式のファイルを扱っているが、バイナリファイルを扱う上での最適な方法について相談しています。_wfopen と CreateFile のどちらが適しているか教えてください。
回答を見る
  • ベストアンサー

バイナリデータのファイル

FILE *stream1; if( (stream1 = fopen( argv[2], "rb" )) == NULL ) printf( "Can not open plane text file.\n"); /////////////////////////////////////////////////////////////////// // 平文 fseek(stream1, 0, SEEK_END); long filelen = ftell(stream1); fseek(stream1,0,0); int head = sizeof(long); mesLength = filelen + head; int baseByte = kk / 8 + ((kk % 8)?1:0); // 鍵バイト長 int mesByte = baseByte - 1; // 処理単位バイト数(暗号化ではbyte減らしておく) //暗号化 if(mesLength <= mesByte*20){//63が暗号化の作業サイズ *20= bufp = (char*)new(char[filelen +1+ int(kk/8 + 2)+head]); if(bufp == NULL){ cout << "No Memory" <<"\n"; cout.flush(); return(-1); } // 平文 *(long *)bufp = filelen; int i = head; do{ c = fgetc(stream1); bufp[i]=c; i=i+1; }while(c!=EOF); bufp[i-1]=NULL; for(int j=0; j<(kk/8+2); j++){ bufp[j+i] = NULL; } mesLength = i-1; // 平文長(バイト) + head 上のように、古い形でファイルを扱っています。 wchar_t を基本にプログラムを書き換えようとしていますが、 ファイルの扱いで、上記の部分と似たような扱いがしやすいのは、 _wfopen CreateFile の、どちらでしょうか? バイナリファイルが扱いやすいもの、8ビットごとの操作が可能なものを探しています。 それとも、あきらめて古いままのほうが良いのでしょうか? よろしくご指導下さい。

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

  • ベストアンサー
  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.4

その暗号化のアルゴリズムがわからなけば、なんとも言えません。 バイナリーデータを暗号化するものなら、charだろうとwchar_tだろうと、同じこと。 ・バイト列と解釈して暗号化 ・復号したバイト列をcharなりwchar_tなりと解釈 文字コードに依存した方法(A→B,B→Cと1文字ずつ順番にローテーションとか)なら 案1) wchar_t→Shift_JISに変換し、それを暗号化/ 復号したら、shift_JIS→wchar_tに変換 案2) wchar_t用にアルゴリズムを作り直す 以下、気付いた点 > int(kk/8 + 2) いくつ出てますが、何度も出てくるものなら、変数やマクロにして「名前」をつけましょう。 名前もなく、コメントも無いので、この式は何の値をあらわしているかがわかりません 似た値に baseByte, memByteがありますが ・kkが8で割きれるとき int(kk/8 + 2) == baseByte+2 == memByte+3 ・kkが8で割きれないとき int(kk/8 + 2) == baseByte+1 == memByte+2 となり、一致しません。 あと、kkがintなら、この外のintは不要です。 というか、ExcelやBasicにあるint関数と、このintとは意味が違います。 > if(mesLength <= mesByte*20){//63が暗号化の作業サイズ *20= これに対する } (閉じ括弧)はどこですか? もし、このずーーーっと下にあるなら、ちょっと長過ぎです。 機能毎に処理を分けて、設計をやりなおしましょう > bufp = (char*)new(char[filelen +1+ int(kk/8 + 2)+head]); > if(bufp == NULL){ 一瞬、なにかと思いました。 Cの標準関数にあるmallocと、C++のnew演算子は違います。 ・new演算子は、指定した型(へのポインタ)になります。 new char[filelen +1+ int(kk/8 + 2)+head] はchar * 型なので、char *にキャストする意味がまったくありません。 ・newが失敗したとき、NULLが返るとは限りません。 たしか、Visual C++6のころまではNULLになっていましたが、それ以降なら下記にしたがっているはずです http://www.kijineko.co.jp/tech/superstitions/return-null-if-new-failed.html > do{ 略 定番の書き方をすれば、こうでしょう。Cの参考書を読めばよく出ています。。 while ( (c = fgetc(stream1) != EOF ) { bufp[i]=c; i=i+1; }; bufp[i]=0; i=i+1; bufp[i]に不要なEOFを代入して、後で0の戻す、なんて無駄をしないですみます。 さらに言えば、ファイルサイズはわかっていて、必要なサイズの領域も確保しているのだから、こんな「プログラム」を作らずとも、freadで一発です。

uyama33
質問者

お礼

ありがとうございました。 とても参考になりました。

その他の回答 (3)

  • wormhole
  • ベストアンサー率28% (1619/5653)
回答No.3

>理由は、シフトジスからユニコードにしたほうが将来便利かなと思ったのです。 >いまのところメリットなしです。 扱うのがバイナリデータならShift_JISもunicodeも(直接は)関係ないので、そのままでよいのではないでしょうか。 またwchar_tは、unicodeというわけではないです。 >bufp[i-1]=NULL; bufpの型がchar *ならNULLを使うのは間違い NULLはNULLポインターであってNUL文字ではないです。

uyama33
質問者

お礼

アドバイスありがとうございます。

回答No.2

> 理由は、シフトジスからユニコードにしたほうが将来便利かなと思ったのです。 対象はバイナリ・ファイルですよね? テキストじゃないですよね? だったら意味ないんじゃないですか?

uyama33
質問者

お礼

中心は暗号化したデータでバイナリファイルです。 アドバイスありがとうございます。

回答No.1

> wchar_t を基本にプログラムを書き換えようとしていますが、 その目的は? メリットは? なぜ wchar_tベースに書き換えるんですか?

uyama33
質問者

お礼

ありがとうございます。 理由は、シフトジスからユニコードにしたほうが将来便利かなと思ったのです。 いまのところメリットなしです。 バイナリデータとファイルの関連では、大きなサイズのデータの変換が必要となりそうで 悩んでいます。 wchar_t を使おうとすると細かい操作が難しいので困っています。

関連するQ&A

  • ファイル中のデータの読むとき・・・・

    こんにちは。ファイルにあるテキストデータを用意してそれを読み込んでいって、処理をするというプログラム書いてるんですけど、たとえば 大まかな構造として、 int fncCheck(char*pch,char item) { int count=0; int i=0; for(i=0;i<strlen(pch);i++) {if(pch[i]==item) { count++; } } return count; } int main() { FILE *fin,*fout;  //ここでいろいろ宣言 if((fin=fopen("Thermoplasmaacidophilum ","r"))==NULL) { cout<<"No files exist in current directory!\n"; exit(-1); } if((fout=fopen("Thermoplasmaacidophilum _out","wb"))==NULL) { cout<<"Output file can't open!\n"; exit(-1); } if((fin=fopen("Thermoplasmaacidophilum ","r"))!=NULL) { fwrite(SMF_header,14,1,fout); fwrite(SMF_firsttrack,36,1,fout); fwrite(SMF_track,13,1,fout); do {    //ここにdoに関する処理 } while(numread==100); while(c=fscanf(fin,"%c",c)!=EOF) {   //ここに処理をずらずら } printf("There are %d bases!!\n",n); fclose(fin); fclose(fout); } return 0; } ・・・のように書くと、一つ目のdo-while文は実行されるんですが、二つ目のwhile文が実行されません。一回目でファイルのデータを最後まで読んでるので、元にもどってもう一回やってくれないんでしょうか?初心者なものでそこらへんがよくわかんないんですが・・。どなたか助けてください。

  • バイナリファイルでランダムアクセスを行う

    初心者です。宜しくお願いします。 下記 text.bin にランダムアクセスするサンプルコードで一部理解できない箇所があります。 下から5行目のfreadの一つ目の引数 &num です。なぜ5のポインタなのか初心者にわかりやすく解説頂けないでしょうか? 宜しくお願い致します。 ■text.bin 80 60 22 50 75 ■サンプルコード #include <stdio.h> #define NUM 5 int main(void) { FILE *fp; int num; int i; fp = fopen("/Users/Documents/test1.bin", "rb"); if (fp == NULL) { printf("ファイルをオープンできませんでした。\n"); return 1; } printf("何番目のデータを読み込みますか?(1~5)\n"); scanf("%d", &i); fseek(fp, (i-1)*sizeof(int), SEEK_SET); fread(&num, sizeof(int), 1, fp); printf("%d番目のデータは%dです。\n", i, num); printf("<#message#>"); fclose(fp); return 0; }

  • C++のポインタの動作を教えてください

    ちょっと長いですが、ある部分の動作がわかりません そこを詳しく教えてください。 void queue::store(int i)の//リスト末尾に置くっていうところからで なぜ、if(tail)tail->next=item; tail=item; こう書くのかわからないです。 tail->next=itemの次にtail=itemを実行すると、tail->nextの内容も変わるのでは?と思っているのですがどうなっているのかわからないのでお願いします。 説明が下手ですがすみませんが教えてください。 //仮想関数の実例 #include <iostream> #include <cstdlib> #include <cctype> using namespace std; class list{ public: list *head; //リスト先頭へのポインタ list *tail; //リスと末尾へのポインタ list *next; //次項目へのポインタ int num; //格納される値 list(){ head=tail=next=NULL; } virtual void store(int i)=0; virtual int retrieve()=0; }; //キュー型リストの作成 class queue:public list{ public: void store(int i); int retrieve(); }; void queue::store(int i) { list *item; item=new queue; if(!item){ cout << "メモリ割り当てエラー" << endl; exit(1); } item->num=i; //リスト末尾に置く if(tail)tail->next=item; tail=item; item->next=NULL; if(!head)head=tail; } int queue::retrieve() { int i; list *p; if(!head){ cout << "リストは空です" << endl; return 0; } //リスト先頭から取り除く i=head->num; p=head; head=head->next; delete p; return i; } //スタック型リストの作成 class stack:public list{ public: void store(int i); int retrieve(); }; void stack::store(int i) { list *item; item=new stack; if(!item){ cout << "メモリ割り当てエラー" << endl; exit(1); } item->num=i; //スタックのような操作になるよう、リスト最前部におく if(head)item->next=head; head=item; if(!tail)tail=head; } int stack::retrieve() { int i; list *p; if(!head){ cout << "リストは空です" << endl; return 0; } //リスト先頭から取り除く i=head->num; p=head; head=head->next; delete p; return i; } class sorted:public list{ public: void store(int i); int retrieve(); }; void sorted::store(int i) { list *item; list *p,*p2; item=new sorted; if(!item){ cout << "メモリ割り当てエラー" << endl; exit(1); } item->num=i; //次項目のおき場所を見つける p=head; p2=NULL; while(p){ //中へ if(p->num>i){ item->next=p; if(p2)p2->next=item; //先頭要素ではない if(p==head)head=item; //新しい先頭要素 break; } p2=p; p=p->next; } if(!p){ //終わりへ if(tail)tail->next=item; tail=item; item->next=NULL; } if(!head)//先頭要素 head=item; } int sorted::retrieve() { int i; list *p; if(!head){ cout << "リストは空です" << endl; return 0; } //リスト先頭から取り除く i=head->num; p=head; head=head->next; delete p; return i; } int main() { list *p; //キューのデモ queue q_ob; p=&q_ob; //キューをさす p->store(1); p->store(2); p->store(3); cout << "キュー:"; cout << p->retrieve(); cout << p->retrieve(); cout << p->retrieve(); cout << endl; //スタックのデモ stack s_ob; p=&s_ob; //スタックをさす p->store(1); p->store(2); p->store(3); cout << "スタック:"; cout << p->retrieve(); cout << p->retrieve(); cout << p->retrieve(); cout << endl; //ソート済みリストのデモ sorted sorted_ob; p=&sorted_ob; p->store(4); p->store(1); p->store(3); p->store(9); p->store(5); cout << "ソ\ート:"; cout << p->retrieve(); cout << p->retrieve(); cout << p->retrieve(); cout << p->retrieve(); cout << p->retrieve(); cout << endl; return 0; }

  • バイナリファイルの読み込み(C言語)

    raw(音楽ファイル)データを配列rawに読み込みたいのですが,バイナリファイルの読み込み方がわかりません. サンプルで以下のようなソース(途中略)があるのですが, ・なぜrawの型としてshortを使っているのか ・データ数の半分(file_size = ftell(fp) / 2)しか読み込んでいない ・fgetc(fp) << 8 あたりの意味がわからないので教えて下さい. -------------------------------------------------------- short *raw; if((fp=fopen(argv[1], "rb")) == NULL){ fprintf(stderr, "can't open %s.\n", argv[1]); exit(1); } fseek(fp, 0, SEEK_END); file_size = ftell(fp) / 2; fseek(fp, 0, SEEK_SET); raw = (short *)malloc((size_t)(file_size * sizeof(short))); if(raw == NULL){ fprintf(stderr, "malloc error\n"); exit(1); } for(i=0;i<file_size;i++) raw[i] = (short)((fgetc(fp) << 8) | fgetc(fp)); -----------------------------------------------------

  • バイナリ読み込み時のデータ受け渡しについて

    質問させていただきます。 XMLファイルを圧縮後にバイナリ読み込みし、long*に設定してそれを4バイトのlong配列に格納したいと考えています。 ファイルを読み込む際にはデータ数が解らないので、ループを回したいと思っています。 以下に一部記載します。 これでpBinaryには正常にバイナリデータが入るのでしょうか? わかる方がいれば教えてください。 ****************************************** FILE *pFile = NULL; pFile = fopen("XMLFile.xml", "rb"); int iRet = 0; int iSize = 0; bool bRet = false; long *pBinary = new long; while(bRet != true) { /* 4バイトずつ読み込みpBinaryに設定する */ fread(pBinary, sizeof(4), 1, pFile); if(iRet != 1) { bRet = true; } else { iSize++; } }

  • C言語 バイナリデータのサイズの調べ方

    windows7 64bitでcygwinを使用しています。 32bitを1つの組として、いくつかの組で構成されたバイナリデータがあります。 このバイナリデータにいくつの組があるのか調べるため、以下のようなソースを記述したのですが、うまくいきません。 どこを修正すればよろしいでしょうか。 御教授願います。 int main() { long long int i; long long int hex[1]; long long int aaaa; int bb; int ret; FILE * fp; i = 1; bb = 1; for(;;){ fp = fopen("kimi.dat", "r"); bb = fread(&hex[1],4,i,fp); aaaa = i; i = aaaa + 1; ret = fclose(fp); if (bb != aaaa) { printf("%lld\n",aaaa); printf("%lld\n",i); printf("%d\n",bb); exit(1); } } } gcc -std=c99でコンパイルしました。 結果は 1431440333 1431440334 1 のように表示されました。 データファイルは900MB以上あります。

  • バイナリデーター内の文字を検索

    現在、以下のようなプログラムでバイナリファイルを読込んでいるのですが、そのデーターの中にある文字列の位置を検索したいのですが何かよい方法は無いでしょうか、for ~ next で廻すと一応はできますが、もう少し簡単な方法を探しています。 -------- Dim xBIN() As Byte Dim lngFileLenB As Long lngFileLenB = FileLen("バイナリ.BIN") Open "バイナリ.BIN" For Binary As #1 Get #1, , xBIN ' For i = 0 To lngFileLenB If IJP_DAT1(i) = CLng("&H" & "20") Then stop end if next i ---------- よろしくお願いします。

  • C言語 バイナリファイルをfloatにしたいのですが…

    16進数で表示すると以下のようなバイナリファイルがあります。 42 b9 e0 a4 3b df ea c0 3a 70 eb dc 37 7c f4 8c これを4バイトずつfloatに入れて出したいのですが、 本当はこのように出したいのですが、 [0][92.93875] [1][0.0068334043] [2][9.190419E-4] [3][1.50773085E-5] このような値がでてしまいます [0][-9.745835E-17] [1][-7.339750E+00] [2][-5.301601E+17] [3][-3.766891E-31] ソースはこれです。 #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { FILE *fp; long size, n; float *buf; int i = 0; if (argc != 2) return 1; /* FILE OPEN */ fp = fopen(argv[1], "rb"); if (fp == NULL) return 1; /* FILE SIZE */ fseek(fp, 0, SEEK_END); size = ftell(fp); rewind(fp); printf("FILE SIZE %ld\n", size); /* FILE READ */ buf = malloc(size); if (buf == NULL) return 1; n = fread(buf, 1, size, fp); /* FILE PRINT */ for(i=0;i<10;i++) { printf("[%d][%E]\n", i, buf[i]); } return 0; } 本日一日調べましたが良くわかりませんでした。 開発環境は以下の内容です。 $ uname -a Linux fedoracore6 2.6.20-1.2962.fc6 #1 SMP Tue Jun 19 19:27:14 EDT 2007 i686 athlon i386 GNU/Linux $ gcc --version gcc (GCC) 4.1.2 20070626 (Red Hat 4.1.2-13) Copyright (C) 2006 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 何かお知恵を拝借出来ないものでしょうか?? よろしくお願い致しますm(_ _)m

  • C++ for文からwhile文への変換方法

    まずは単刀直入にこのプログラムをご覧ください。 int two[6][10]; for(int j=0; j<net; j++){ for(int i=0; i<10; i++){ input_file >> two[j][i]; if(two[j][i]==0) break; } } for(int j=0; j<net; j++){ for(int i=0; i<10; i++){ cout << two[j][i] << " "; if(two[j][i]==0) break; } cout << endl; } このfor文をwhile文に置き換えて表示させるやりかたがよくわかりません。 今ゼミの課題でC++のプログラムに取り組んでおり、ファイル内の数字の配列を読み込んでそれを画面に表示させるプログラムを作ってるのですが、この部分がよくわからず苦戦しています。 ちなみに表示させる数字は以下の通りです。 9 11 8 0 1 10 6 0 8 2 4 10 0 5 8 7 2 0 1 3 10 4 0 2 4 12 0 どなたかご教授よろしくお願いします<(_ _)>

  • バイナリデータをテキストファイルに出力したい

    以下のソースファイル(test.c) が、 バイナリデータをテキストファイルに するものらしいのですが、 ファイル名(例えば bi.dat)を指定する方法が わかりません。 C++は勉強し始めたばかりで 詳しくありません。 よろしくお願い致します #include <stdio.h> int main( int argc, char *argv[]) { FILE *fpIn; FILE *fpOut; short snData; if( argc < 2) { printf("ファイル名を入れてください。"); return -1; } fpIn = fopen( "argv[1]" , "rb"); if( fpIn == NULL) { printf("入力ファイル %s を開けませんでした。", argv[1]); return -2; } fpOut = fopen( "output.txt", "w"); if( fpOut == NULL) { printf("出力ファイル output.txt を開けませんでした。"); fclose(fpIn); return -3; } while( fread( &snData, sizeof(short), 1, fpIn) == 1) { fprintf( fpOut, "%d\n", snData); }; fclose(fpIn); fclose(fpOut); return 0; }

専門家に質問してみよう