ReadFileとWriteFile関数について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
needsueda

ReadFileとWriteFile関数について

#1

投稿記事 by needsueda » 12年前

 ディスクの読み書きの件で意見を求めるトピックを建てたことで 
CreateFileの話が出ました。
そこで改めてCreateFileやReadFile,WriteFileを、マイクロソフト社のWEBで調べて見ました。
私が普段使っているVC6++とは違いVC++2005以降では
ファイルアクセスの仕方が大幅に変更されていることが判明しました。
前回のトピックが何度探しても判らないし、大事な事なので 新規にトピックを建てることにしました。

 VC++2005のマイクロソフト社の解説に以下の部分が追加されていました。
ReadFile WriteFile
WEB原文通り
・ファイルアクセスは、ボリュームのセクタサイズの整数倍のバイトオフセットの位置で開始しなければなりません。
・ファイルアクセスのバイト数を、ボリュームのセクタサイズの整数倍にしなければなりません。
 たとえば、セクタサイズが 512 バイトの場合、512 バイト、1,024 バイト、2,048 バイトの読み書きはできますが、
 335 バイト、981 バイト、7,171 バイトなどの読み書きはできません。

 ご指摘の通り、私もopenもしくは_openは、CreateFileに自動的置き換えられていると理解して来ましたが
この調査で、どうやらそう簡単に考えてよいものではないらしいことが分かりました。
 以前から_openのハンドル番号とCreateFilのハンドル番号が前者は主に1桁台、後者は2桁台であることに
関心を寄せて来ました。これまでは単に混同しないための配慮かなと思って来たのですが。
(同一ファイルを時間直列でオープン、クローズして実施した際のハンドル番号ですが)

 主な関数群、下記の2系列
_open,_read,_write,_close
CreateFile,ReadFile,WriteFile,CloseHandleについてです。
 
 問題は
VC6++ではファイルアクセスは指定したバイト数でOKであったが
VC++2005以降ファイルアクセスはセクター単位かその整数倍で行われることに変更されたことです。
この変更でディスクアクセスのコーディングが複雑になりました。
今後、ReadFileとWriteFileを使う時は、アタッチメントの役割をする部分を間にはさまなくてはなりません。
それも開発ソフト毎に対応を変える必要があります。
 物理的にディスクアクセスがセクター単位であることは判っていましたから、ファイル設計するときは
なるべくセクター単位と思われる256、512、1024に沿うようにしてきましたが、
そうもできないファイルも多いのが現実です。

 私は当面_openを主に使うことにしますが、皆さんはどうされているのでしょうか。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: ReadFileとWriteFile関数について

#2

投稿記事 by softya(ソフト屋) » 12年前

前回のトピックはコレです。名前で検索できるはずですが。
「ディスクアクセスに関して意見をお願いします。 • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/viewtopic.php?f=3&t=11870

少なくともCreateFileはWindows95時代から存在するので極端には変化していないはずです。
なのでVC++6.0の資料は調べられませんが記述漏れがあったとしても変わってはいないはずです。
それと日本語版は誤訳や間違いが結構あるので必ず英語版でも確認して下さい。

と思って見て見たら次の点を読み飛ばしていませんか?
http://msdn.microsoft.com/ja-jp/library/cc429679.aspx
MSDNより引用:
FILE_FLAG_NO_BUFFERING フラグを指定してファイルを開いた後、そのファイルの作業を行う場合、アプリケーションは次の各要件を満たさなければなりません。

•ファイルアクセスは、ボリュームのセクタサイズの整数倍のバイトオフセットの位置で開始しなければなりません。ボリュームのセクタサイズを判断するには、GetDiskFreeSpace 関数を呼び出します。

•ファイルアクセスのバイト数を、ボリュームのセクタサイズの整数倍にしなければなりません。たとえば、セクタサイズが 512 バイトの場合、512 バイト、1,024 バイト、2,048 バイトの読み書きはできますが、335 バイト、981 バイト、7,171 バイトなどの読み書きはできません。

•読み書き操作用のバッファのアドレス(メモリ内のアドレス)を、ボリュームのセクタサイズの整数倍に整列(セクタ整列)させなければなりません。バッファをセクタ整列させる 1 つの方法は、 関数を使ってバッファを割り当てることです。VirtualAlloc 関数が割り当てるメモリは、システムのページサイズの整数倍のアドレスに整列されています。ページサイズとボリュームのセクタサイズは両方とも 2 のべき乗なので、システムのページサイズの整数倍に整列されたメモリは、ボリュームのセクタサイズの整数倍のアドレスにも整列されます。
と言うことで下線部のFILE_FLAG_NO_BUFFERING限定の話だと思います。
日本語版のMSDNサイトの出来が非常に悪いんですけどね。
「ReadFile function (Windows)」 英語版の見やすいこと。
http://msdn.microsoft.com/en-us/library ... s.85).aspx


VC++6.0だろうとVC++2005であろうと最終的に同じCreateFileを呼び出すので動作が違ったら困りますよね。
最初に見た時にVC++2005で作ったアプリがWindows98でも動くのでそんなはずないと思いました。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

Re: ReadFileとWriteFile関数について

#3

投稿記事 by ISLe » 12年前

英語版MSDNサイトはわりとさいきんデザインが大幅リニューアルされたのですが、日本語版はそれに追い付いてないんですよね。
特にWin32 APIあたりは(ずっと前から)ひどいですね。
内容の更新が追い付いてないのはもはや当たり前。
重要なキーワードであるリンク部分が欠けている(タグ化け?)とか、一段落すっぽり抜けているとか。


わたしはVC++4のころから、CreateFile使ってますよ。
needsueda さんが書きました: 私は当面_openを主に使うことにしますが、皆さんはどうされているのでしょうか。
前のスレにも書きましたが、ウィンドウズのアプリならCreateFileかfopenの二択ですね。
_openは選択肢にもならないです。


ところで、わたしはCreateFileが返すハンドルの値なんかよりも、needsuedaさんが_openでファイルを作成するときアクセス許可にどういう値を指定しているのかが気になります。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: ReadFileとWriteFile関数について

#4

投稿記事 by softya(ソフト屋) » 12年前

そういえばトピックを見失うという問題ならmixc++にユーザー登録してもらうとメールなどで更新メールが届く様に設定できるので見失うことが少なくなるかと思います。
ご検討ください。登録はページの右下にあります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

needsueda

Re: ReadFileとWriteFile関数について

#5

投稿記事 by needsueda » 12年前

済みません。どうも早とちりのようです。
VC6++のReadFileとWriteFileには注意事項は記載されていませんでしたが、
CreateFileの項目には記載がありました。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: ReadFileとWriteFile関数について

#6

投稿記事 by softya(ソフト屋) » 12年前

needsueda さんが書きました:済みません。どうも早とちりのようです。
VC6++のReadFileとWriteFileには注意事項は記載されていませんでしたが、
CreateFileの項目には記載がありました。
どういう意味かわかりませんのでもう少し詳しくお願いします。
それと前回トピックと今回トピックのISLeさんの質問に答えて頂けますでしょうか?

【補足】
出来ればこちらもお願いします。
「scanfについて • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/viewtopic.php?f=3&t=11838
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

needsueda

Re: ReadFileとWriteFile関数について

#7

投稿記事 by needsueda » 12年前

VC6++の中にある解説では
VC6++のReadFileとWriteFileには注意事項は記載されていませんでしたが、
CreateFileの項目には記載がありました。
つまり、VC6++の解説の中のReadFileとWriteFileに記載がないことから
セクタ単位に制限される規制はないと判断したのですが、
ご指摘のCreateFileの解説を読んだところ、先の制限事項の記載があったことから
私の見落としが判りました。そう言う意味で「早とちり」と申し上げたのです。
見落としたのは私の過ちですから。
 VC++2005以降の解説ではCreateFileを含めて全てに制限事項が記載されて
いたため返ってCreateFileも同じだろうと決め付けてしまったことも
「早とちり」をさせられた原因かの知れませんが。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: ReadFileとWriteFile関数について

#8

投稿記事 by softya(ソフト屋) » 12年前

えーとCreateFileやReadFileやWriteFileは、FILE_FLAG_NO_BUFFERINGなどを指定しない限り「セクタ単位に制限される規制」はありません。
説明を読んでいるとどんな場合でも制限があると思われている様にしか読み取れてなりません。
どうお考えなのでしょうか?

それと、お願いした「今回トピックのISLeさんの質問に答えて頂けますでしょうか?」は書いて頂けないのでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

閉鎖

“C言語何でも質問掲示板” へ戻る