みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

複数ファイルを1つにまとめる コード添削願い

複数のファイルを1つのファイルにまとめようとがんばっています。

リストボックスを用意し、ファイル一覧をつくり、
そこからアドレスを取得して、まとめていくという手順です。
ただ、最後のWriteFile関数の部分で、書き込みが出来ずエラーが返ります。
なぜかが分かりません。
ご教授お願いします。

Dim num As Long
Dim buf As BytePtr
Dim hFile As HANDLE
Dim n As Long
Dim LastFileSize As Long

num=SendDlgItemMessage(hMainWnd,ListBox1,LB_GETCOUNT,0,0)

For n=0 to num-1 Step 1
'ファイル名を取得
Dim name As BytePtr
Dim len As Long
Dim s As String
Dim path As String
Dim FileSize As Long
Dim dwAccessByte As DWord

len=SendDlgItemMessage(hMainWnd,ListBox1,LB_GETTEXTLEN,n,0)+1
name=malloc(len)
SendDlgItemMessage(hMainWnd,ListBox1,LB_GETTEXT,n,name)

s=MakeStr(name)
free(name)

'ファイルパスを連結し、読み込む
path=str+"\"+s

'ファイルハンドルの作成
hFile=CreateFile(path,GENERIC_READ,FILE_SHARE_READ or FILE_SHARE_WRITE,ByVal 0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0)
If hFile=INVALID_HANDLE_VALUE Then
MessageBox(hMainWnd,Ex"ファイルハンドル作成時にエラーが発生しました!","Error File Number Is "+Str$(n)+" .",MB_OK or MB_ICONWARNING)
Exit Sub
End If

'ファイルのサイズの取得
FileSize=GetFileSize(hFile,0)
LastFileSize=LastFileSize+FileSize

'領域確保
If n=0 Then
buf=malloc(FileSize+1)
Else
buf=realloc(buf,FileSize+1)
End If

'ファイルの読み込み
If ReadFile(hFile,buf,FileSize,VarPtr(dwAccessByte),ByVal 0)=0 Then
MessageBox(hMainWnd,"ファイル読み込み時にエラーが発生しました!!","Error "+Str$(n),MB_OK or MB_ICONWARNING)
MessageBox(hMainWnd,Ex"FileSize="+Str$(FileSize)+Ex"\r\ndwAccessByte="+Str$(dwAccessByte),"",MB_OK or MB_ICONWARNING)
End If

'ファイル名とサイズを記録
Open dir+"\FileInfo.txt" For Append As #1
Print #1,s+"="+Str$(FileSize)
Close #1

CloseHandle(hFile)
Next

hFile=CreateFile(dir+"\game.test",GENERIC_WRITE,0,ByVal 0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0)
If hFile=INVALID_HANDLE_VALUE Then
MessageBox(hMainWnd,Ex"ファイルハンドル作成時にエラーが発生しました!","Error File Number Is At Last",MB_OK or MB_ICONWARNING)
Exit Sub
End If

If WriteFile(hFile,buf,LastFileSize,VarPtr(dwAccessByte),ByVal 0)=FALSE Then
MessageBox(hMainWnd,"ファイル作成時にエラーが発生しました!!","Last Error",MB_OK or MB_ICONWARNING)
MessageBox(hMainWnd,Str$(LastFileSize)+","+Str$(dwAccessByte),0,0)
End If

CloseHandle(hFile)
free(buf)

MessageBox(hMainWnd,"処理終了","End",MB_OK or MB_ICONINFORMATION)

投稿日時 - 2009-12-30 18:14:59

QNo.5557491

困ってます

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

やりたいことと 書かれているコードの整合性が取れていないように思います

allocで取得した領域を再利用するために reallocを使われているようですが
複数のファイルの内容を bufに溜め込むつもりで使っているのであれば間違っていると思いますよ
最初に読み込んだデータの領域をreallocで破壊してしまうように思います
読み込むファイル数分のbuf(BytePtr)の配列を用意しておいてここに読み込むようにするか
もしくはLastFileSizeでReallocをかけてReadFileに与えるbufを前回読み込んだ位置の次を指示するようにしないとうまくないでしょう
たとえば 初回は bufで与え 25byte読み込んだのであれば
2回目は buf+26 としてやらないと 最初に読んだデータが破壊されます

ただ reallocで再確保した際に 前回そのバッファを変更した内容まで再確保した領域へコピーするかどうかはドキュメント(マニュアル)で確認しましょう
# コピーまでは面倒見てくれないと思いますけど …

WriteFileがFalseを返して失敗したのであれば GetLastError/FormatMessageなどを使って エラーの原因を確認しましょう

投稿日時 - 2010-01-01 04:15:40

このQ&Aは役に立ちましたか?

1人が「このQ&Aが役に立った」と投票しています

回答(3)

ANo.2

その他(プログラミング)に 質問してください。

カテゴリ違いです。


ここは VBとVBA VB.NET などです。

ActiveBASIC は私は知りません。

明記されていないから #1の回答になったのです。

実際にVBでコンパイルするとあちらこちら エラーだらけです。


>>>VBでSendDlgItemMessage は使えません。
>ご自分で別なクラスを作っているならありえますが・・・
>>とありますが、普通に定義してしまえばいいのでは?
>>クラスも何も、
>>Declare Function SendDlgItemMessage Lib "user32" Alias "SendDlgItemMessageA" (hDlg As HWND,nIDDlgItem As Long,Msg As DWord,wParam As DWord,lParam As DWord) As Long
の一行で出来ると思います。

>>VBで使えないとして、
>>SendMessage(GetDlgItem(hMainWnd,ListBox1),LB_GETTEXTLEN,n,0)
>>だと解釈してください。


こういうことがご存知でしたら 自分で修正したらどうですか ここは VBのカテゴリです。

相手に修正を加えて検証をしてください と聞こえてきます。

投稿日時 - 2010-01-01 00:17:59

ANo.1

VBのバージョンは何を尾s使いですか?

Windowsシェル WSHなどで VBS で

Excel VBA

VB6.0 など 書かないとだめです。

もしかして カテゴリ違い!!

コンパイルエラーは自分で ヘルプを見ればわかる範囲のはず。

たとえば len=SendDlgItemMessage(hMainWnd,ListBox1,LB_GETTEXTLEN,n,0)+1

len=

は予約語ですよ。

VBでSendDlgItemMessage は使えません。

ご自分で別なクラスを作っているならありえますが・・・

VC++ などのほかの言語とごちゃまぜ??

質問を明確にしてください.

投稿日時 - 2009-12-31 22:43:16

補足

ああ、そうそう、もうひとつ。

>質問を明確にしてください.
とありますが、コンパイルエラーはありません。
質問の方に記載させていただいたとおり、
『WriteFile関数の部分で、書き込みが出来ずエラーが返ります。』
ということです。
つまり、WriteFileの戻り値でFALSEが返るということです。

ABのバージョンで申し訳ないですが、
4.23.000を使用しています。

投稿日時 - 2009-12-31 23:18:16

お礼

失礼しました。
VB・・・といいますか、ActiveBasicを使っています。
同じBASICでも書き方が違うのですか・・・

しかし、
>VBでSendDlgItemMessage は使えません。
>ご自分で別なクラスを作っているならありえますが・・・
とありますが、普通に定義してしまえばいいのでは?
クラスも何も、
Declare Function SendDlgItemMessage Lib "user32" Alias "SendDlgItemMessageA" (hDlg As HWND,nIDDlgItem As Long,Msg As DWord,wParam As DWord,lParam As DWord) As Long
の一行で出来ると思います。

VBで使えないとして、
SendMessage(GetDlgItem(hMainWnd,ListBox1),LB_GETTEXTLEN,n,0)
だと解釈してください。

よろしくお願いします。

投稿日時 - 2009-12-31 23:16:56

あなたにオススメの質問