みなさん
こんにちは。
あるファイル内からfseekを用いて中身のデータを取り出すプログラムを
Visual C++ 6.0、コンソールアプリケーションで作りました。
fseekだと読み出せるファイルの大きさは、offsetバイト(long型)で
決まってしまい、2GB程度のファイルまでしか指定出来ません。4GBを超える
ファイルで同様の操作をしたいと思っています。
プログラムとしては
if((fp=fopen(fname_in,rb))==NULL)
{
fprintf(stderr, Input File Open Error!\n);
exit(0);
}
else
printf(Open input file %s\n,fname_in);
}
fseek(fp, HEADER_SIZE, SEEK_SET);
fread(data, sizeof(RAW_Data_info), 1, fin); //以下データ読込部分
HEADER_SIZEが、4GBを超えるような大容量ファイルを読込たい場合には
具体的にはどのように記述をしたらよいのでしょうか?
よろしくお願い致します。
標準ライブラリではどうしようもないので
WinAPIのCreateFile, Read/WriteFile等を使うことになります。
> 標準ライブラリではどうしようもないので
> WinAPIのCreateFile, Read/WriteFile等を使うことになります。
え!?標準の範囲でもfseekの現在位置から
相対ジャンプを繰り返す手順でいいと思ったけど。
VC6はそれで動かないの?
> え!?標準の範囲でもfseekの現在位置から
> 相対ジャンプを繰り返す手順でいいと思ったけど。
> VC6はそれで動かないの?
VC6 ではどうだか知りませんが、VC7 では動きません。
現在の実装では、内部でオフセット値を 32bit で管理していたり、SetFilePointer の
第3引数を NULL で呼んだりしていますので。
7 で動かないのが 6 で動くってのも考えにくいので、たぶん 6 でも動きません。
ついでに言うと、標準ライブラリでは 2GB を超えるファイルは扱えません。
みなさま
いろいろとコメントありがとうございます。
コンソールアプリで十分なのですが、WinAPIのCreateFile
, SetFilePointerを使ってダイアログベースかSDIにして
プログラムを作り直してみようと思います。
> コンソールアプリで十分なのですが、WinAPIのCreateFile
> , SetFilePointerを使ってダイアログベースかSDIにして
> プログラムを作り直してみようと思います。
コンソールアプリでも、Win32のAPI使えませんでしたっけ?
ファイルアクセス関連のCreateFileとWriteFileを使ってコンソールアプリを書いた記憶
があります。
NowNowさん、はじめまして
本当ならうれしいのですが...。CreateFileでHADNLE hFile=::CreateFile()
と書くと思うのですが、HADNLE hFileの定義は具体的には、どこで定義したら
よいのでしょうか?
>HADNLE hFileの定義は具体的には、どこで定義したらよいのでしょうか?
ダイアログやSDIでつくったばあいですか?
どこでファイル処理をさせたいのかわかりませんが、ウィンドウを表示したら
その結果が表示されるというならば、OnCreate(SDI)やOnInitDialog(ダイアログ)に記述
するのかな。
#include<windows.h>を宣言すればコンソールアプリでも使えます。>Win32API
VC6でコンソールアプリで作成してみました。
#include <stdio.h>
#include <windows.h>
int main(void)
{
char data[] = {1,2,3,4};
HANDLE hFile = CreateFile(Test.dat, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
puts(CreateFile Error);
return 0;
}
DWORD write = 0;
WriteFile(hFile, data, 4, &write, NULL);
CloseHandle(hFile);
puts(end);
return 0;
}
これで、コンソール画面にはendと表示され、Test.datファイルにはバイナリエディタで
見ると01 02 03 04と格納されたファイルが作成されていました。
BlueさんのResにもありますが、#include <windows.h>を追加すればOKのはずです。
VC6のコンソールアプリの標準設定では、libファイルの追加とかは行わなくて上のプログ
ラムであればリンクエラーも発生しませんでした。
NowNowさん、Blueさん
ありがとうございます。NowNowさん、ソースまでご教示頂きありがとうございます。
NowNowさんのご教示の前にわたしもとりあえず、現存のプログラムを変更しつつ、
コンパイルが通る、通らないをみながらやってみました。SetFilePointerExの
ところで引っかかってしまい、ヘルプで何でだろうかと考えているところです。
//TEST_pro.cpp
#include <stdio.h>
#include TEST_pro.h
#include <windows.h>
HANDLE hfile; //どこが適当かわからなかったので、こんなところにかいてしまいました。
int main(void)
{
if((fp=fopen(fname_in,rb))==NULL)
{
fprintf(stderr, Input File Open Error!\n);
exit(0);
}
else
{
hfile=::CreateFile(fname_in, GENERIC_READ, FILE_SHARE_READ, NULL, PEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
printf(Open input file %s\n,fname_in);
}
}
//fseek(fp, HEADER_SIZE, SEEK_SET);
// SetFilePointerEx(hfile,HEADER_SIZE, NULL, FILE_BEGIN); ->このときは、C2440エ
ラー
SetFilePointerEx(hfile, 3221225471, NULL, FILE_BEGIN); ->このときは、CC2664エ
ラー
fread(data, sizeof(RAW_Data_info), 1, fin); //以下データ読込部分
}
SetFilePointerExの第二引数はLARGE_INTEGERです。
LARGE_INTEGER li;
li.LowPart = 0xBFFFFFFF;
li.HighPart = 0;
SetFilePointerEx(hfile, &li, NULL, FILE_BEGIN);
試していませんが、こんな感じで動作するのではないでしょうか?
LARGE_INTEGERの詳細は、
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winprog/winprog/large_integer_str.asp
こちらにあります。
NowNowさん、みなさん、ありがとうございます。
SetFilePointerEx(hfile, li, NULL, FILE_BEGIN);
にしてうまくいきました。申し訳ないのですが、もう少しご教示ください。
実は、liは変数でしてfor文で回して大きな値にしていきます。
//li.LowPart = 0xBFFFFFFF;
//li.HighPart = 0;
から
li.LowPart = (6442450943)&0x00000000FFFFFFFF;
li.HighPart = (6442450943)&0xFFFF00000000;
のように変更し、4GB(li.LowPart = 4294967295)までのファイルは、デバック
モードで値が入るのを確認して、大丈夫そうだと解りました。ところが、例えば
6GB程度、値として6442450943、を入れた際、
li.LowPart = 2147483647;
li.HighPart = 0;
となってしまいました。&の取り方をいろいろと変えてみたのですが、うまくいき
ませんでした。6,8,10GBの様なファイルの場合は、どうすればよいのでしょうか?
よろしくおねがいします。
for文でまわしているときのカウンタはどのような変数の型を使っているかわかりません
が、その値が64ビット整数型(LONGLONG)であれば、LARGE_INTEGERのQuadPartに代入す
れば、上位32ビット、下位32ビットを意識せずに代入できます。
li.LowPart = (6442450943)&0x00000000FFFFFFFF;
li.HighPart = ((6442450943)&0xFFFFFFFF00000000) >> 32;
LowPart、HighPartともに32ビットですので、このようにすればよいのではないでしょうか?
ただし、試していません。