4GBを超えるファイルの読込 – プログラミング – Home

4GBを超えるファイルの読込
 
通知
すべてクリア

[解決済] 4GBを超えるファイルの読込

固定ページ 1 / 2

ももたろう
 ももたろう
(@ももたろう)
ゲスト
結合: 20年前
投稿: 11
Topic starter  

みなさん

こんにちは。
あるファイル内から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を超えるような大容量ファイルを読込たい場合には
具体的にはどのように記述をしたらよいのでしょうか?
よろしくお願い致します。


引用未解決
トピックタグ
ori
 ori
(@ori)
ゲスト
結合: 20年前
投稿: 3
 

標準ライブラリではどうしようもないので
WinAPIのCreateFile, Read/WriteFile等を使うことになります。


返信引用
デフォルトの名無しさん
 デフォルトの名無しさん
(@デフォルトの名無しさん)
ゲスト
結合: 20年前
投稿: 1
 

> 標準ライブラリではどうしようもないので
> WinAPIのCreateFile, Read/WriteFile等を使うことになります。

え!?標準の範囲でもfseekの現在位置から
相対ジャンプを繰り返す手順でいいと思ったけど。
VC6はそれで動かないの?


返信引用
aetos
(@aetos)
Noble Member
結合: 5年前
投稿: 1480
 

> え!?標準の範囲でもfseekの現在位置から
> 相対ジャンプを繰り返す手順でいいと思ったけど。
> VC6はそれで動かないの?

VC6 ではどうだか知りませんが、VC7 では動きません。
現在の実装では、内部でオフセット値を 32bit で管理していたり、SetFilePointer の
第3引数を NULL で呼んだりしていますので。
7 で動かないのが 6 で動くってのも考えにくいので、たぶん 6 でも動きません。


返信引用
aetos
(@aetos)
Noble Member
結合: 5年前
投稿: 1480
 

ついでに言うと、標準ライブラリでは 2GB を超えるファイルは扱えません。


返信引用
ももたろう
 ももたろう
(@ももたろう)
ゲスト
結合: 20年前
投稿: 11
Topic starter  

みなさま

いろいろとコメントありがとうございます。
コンソールアプリで十分なのですが、WinAPIのCreateFile
, SetFilePointerを使ってダイアログベースかSDIにして
プログラムを作り直してみようと思います。


返信引用
NowNow
 NowNow
(@NowNow)
ゲスト
結合: 20年前
投稿: 27
 

> コンソールアプリで十分なのですが、WinAPIのCreateFile
> , SetFilePointerを使ってダイアログベースかSDIにして
> プログラムを作り直してみようと思います。

コンソールアプリでも、Win32のAPI使えませんでしたっけ?
ファイルアクセス関連のCreateFileとWriteFileを使ってコンソールアプリを書いた記憶
があります。


返信引用
ももたろう
 ももたろう
(@ももたろう)
ゲスト
結合: 20年前
投稿: 11
Topic starter  

NowNowさん、はじめまして

本当ならうれしいのですが...。CreateFileでHADNLE hFile=::CreateFile()
と書くと思うのですが、HADNLE hFileの定義は具体的には、どこで定義したら
よいのでしょうか?


返信引用
Blue
 Blue
(@Blue)
ゲスト
結合: 20年前
投稿: 1467
 

>HADNLE hFileの定義は具体的には、どこで定義したらよいのでしょうか?
ダイアログやSDIでつくったばあいですか?
どこでファイル処理をさせたいのかわかりませんが、ウィンドウを表示したら
その結果が表示されるというならば、OnCreate(SDI)やOnInitDialog(ダイアログ)に記述
するのかな。

#include<windows.h>を宣言すればコンソールアプリでも使えます。>Win32API


返信引用
NowNow
 NowNow
(@NowNow)
ゲスト
結合: 20年前
投稿: 27
 

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ファイルの追加とかは行わなくて上のプログ
ラムであればリンクエラーも発生しませんでした。


返信引用
ももたろう
 ももたろう
(@ももたろう)
ゲスト
結合: 20年前
投稿: 11
Topic starter  

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); //以下データ読込部分

}


返信引用
NowNow
 NowNow
(@NowNow)
ゲスト
結合: 20年前
投稿: 27
 

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
こちらにあります。


返信引用
ももたろう
 ももたろう
(@ももたろう)
ゲスト
結合: 20年前
投稿: 11
Topic starter  

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の様なファイルの場合は、どうすればよいのでしょうか?

よろしくおねがいします。


返信引用
NowNow
 NowNow
(@NowNow)
ゲスト
結合: 20年前
投稿: 27
 

for文でまわしているときのカウンタはどのような変数の型を使っているかわかりません
が、その値が64ビット整数型(LONGLONG)であれば、LARGE_INTEGERのQuadPartに代入す
れば、上位32ビット、下位32ビットを意識せずに代入できます。

li.LowPart = (6442450943)&0x00000000FFFFFFFF;
li.HighPart = ((6442450943)&0xFFFFFFFF00000000) >> 32;

LowPart、HighPartともに32ビットですので、このようにすればよいのではないでしょうか?
ただし、試していません。


返信引用
各無し
 各無し
(@各無し)
ゲスト
結合: 20年前
投稿: 11
 

こんなのもあるよ。
http://www.codeproject.com/file/64-bit_fileio.asp


返信引用
固定ページ 1 / 2

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました