VBAを使って、
10MByteのバイナリファイルがあり、
これの1MByte~1.1MByteの領域のデータを書き換えたいとします。
いままでは
Open ファイル名 For Binary As #ファイル番号
でデータを書き換えていたのですが
http://officetanaka.net/excel/vba/file/file08.htm
Random、ランダムアクセスモードというものもあることに気がつきました。
RandomとBinaryモードの違いについて教えてください。
名前から判断すると
Randomモードはファイルの途中からでも読み書きができるのに対し
Binaryモードは最初からしか読み書きができないので
ファイルの途中のデータを書き換えたい場合には
Randomモードの方が高速のような気がするのですが
本当にそうなのでしょうか?
散々調べてみたのですが
違いおよび使い分け方が分からなかったので教えてください。
A 回答 (7件)
- 最新から表示
- 回答順に表示
No.7
- 回答日時:
>もっとも高速なのは最初に大きな配列を生成してから、一度に書き込む方法です。
メソッドを呼び出すのにも時間がかかります。
なので、メソッドの呼び出し回数を減らせば速度はアップします。
>いまデータはHDDに保存されているので
HDDのアクセスが早いので、シーケンシャルでもランダムでも速度差を感じなくなっているのです。
しかし、この考え方がなくなっているわけではありません。
すみません。何かおかしいと最初から読み直したのですが、基本が間違っていました。
1:「TEXTファイル」を「シーケンシャルアクセス」
Append、Input、Output
2:「TEXTファイル」を「ランダムアクセス」
Random
3:「Binaryファイル」を「シーケンシャルアクセス」←「ランダムアクセス」
Binary
>テキストファイルの場合だと最初から呼んでいかないと行やファイルの終端がどこにあるか
そのようなファイルを扱うのが「1:」のパターンです。
テキストファイルでも、1行の長さを固定にして出力すれば、読み込むときに計算で読みたい位置はわかるのでランダムにアクセスできます。これが「2:」のパターンです。
テキストファイル同様、バイナリーファイルでもファイルの構造によって必ずしもランダムアクセスできるわけではありません。そこのところは間違えないようにしてください。
No.6
- 回答日時:
>いまデータはHDDに保存されているので
>バイナリデータを扱う場合には常にランダムアクセスしているのではないでしょうか?
プログラミング言語のレベルで言うと、
「どの位置だったかにかかわらず、前回読んだ次の位置のデータを読め」というのがシーケンシャルアクセスで、
「前回どこを読んだかに関係なく、指定したこの位置のデータを読め」というのがランダムアクセスです。
データが実際にどこにあるのか、HDDなのか、RAMDISKなのか、あるいは磁気テープ上にあるのか、などには無関係です。
No.5
- 回答日時:
昨日のソースがよくなかったので手直ししました。
Dim buffer(3) As Byte
buffer(0) = AscW("A")
buffer(1) = AscW("B")
buffer(2) = AscW("C")
Dim i As Long
'バイナリファイル書き込み
Open outputFileName For Binary As #1
Seek #1, 2000
For i = 0 To UBound(buffer) - 1
Put #1, , buffer(i)
Next
Close #1
>質問2
>最初から読み直して2001バイト目に達してから
勘違いをさせてしまったようです。
実際には「読み直し」はしません。
「位置情報を変更してから」です。
>Put intFileNumber, 2000, xxx
>Put intFileNumber, 2001, yyy
xxx、yyyがByteデータだとすると、
最初の行でxxxを出力すると、位置情報が自動的に2001になります。
なので、2行目で位置情報を指定しなくても正しく出力されます。
例のように、2行目で2001と指定すると位置情報を再度セットしなおして
出力するので非効率と説明しました。
【位置を2000に移動】-【xxxを出力】-【位置を2001に移動】-【yyyを出力】
>Put intFileNumber, 2000, xxx
>Put intFileNumber, , yyy
【位置を2000に移動】-【xxxを出力】-【yyyを出力】
※xxxを出力すると、自動で2001に移動している。
ということです。
最初に記述したサンプルのbufferが500や1000と大きくなればなるほど、
出力のたびに毎回【位置移動】をさせるのと、しないのでは差がでるのはお分かりだと思います。
【補足】
xxx、yyyがIntegerだとすると、Integerは2Byteなので、
2000でxxxを出力すると、位置情報は2002になります。
No.4
- 回答日時:
>質問1
Seekなどで飛ばすだけなら気にならないと思います。
あちこちに移動させて読み書きする(データベースの処理)のようなことでもしない限り問題ないと思います。
>質問2
そのとおりです。
とても非効率になります。
>この方法よりも
>のようにするとして書き込んだ方が高速でしょうか?
高速に処理できます。
>質問3
例えばですが、以下のようにして配列を処理すればどうでしょう?
Dim buffer(3) As Byte
buffer(0) = AscW("A")
buffer(1) = AscW("B")
buffer(2) = AscW("C")
Dim i As Long
'バイナリファイル書き込み
Open outputFileName For Binary As #outputFn
Put #outputFn, 2000, buffer(0)
For i = 1 To UBound(buffer) - 1
Put #outputFn, , buffer(i)
Next
Close #outputFn
No.3
- 回答日時:
ファイルには、「TEXTファイル」と「Binaryファイル」が存在します。
ファイルにアクセス(読み込み・書き込み)するには、シーケンシャルとランダムがあります。
つまり、
1:「TEXTファイル」を「シーケンシャルアクセス」
2:「TEXTファイル」を「ランダムアクセス」
3:「Binaryファイル」を「シーケンシャルアクセス」
4:「Binaryファイル」を「ランダムアクセス」
この4つのパターンが存在します。
しかし、VBAでファイルをOPENする場合のモードには、
Append
Binary
Input
Output
Random
この5つで、同時に複数選択することができません。
なので、
1:「TEXTファイル」を「シーケンシャルアクセス」
Append、Input、Output
2:「TEXTファイル」を「ランダムアクセス」
Random
3:「Binaryファイル」を「シーケンシャルアクセス」
Binary
この、3種類になります。
基本は「シーケンシャルアクセス」で、先頭から順に読み書きしていく形式です。
ランダムアクセスは、ファイルの任意の位置から読み書きする場合に高速にアクセスできる形式ですが、何万件もデータがある場合でなければあまり差はありません。
※シーケンシャルアクセスでも途中から読み書きは可能です。普段扱うファイルならシーケンシャルでも速度が遅くなることがないので、基本はこちらになっています。
>つまりrandomモードはテキストファイルを読み書きするモード
結果的にそうなります。
>例えば4バイトのデータをファイルの途中に書き込もうとしようとすると
>その後にゼロでーたが大量に生成して元のファイルよりも
書き込み方法が間違っているだけだと思います。
No.2
- 回答日時:
Randomは、ファイルの途中から読み書きできる。
その反対がシーケンシャルです。
ただ、省略した場合ランダムです。
Binaryは、開くファイルがバイナリーファイルのときに指定します。
その反対がテキストです。
省略するとテキストです。
つまり、バイナリーファイルを扱うのであればBinaryを指定する必要があります。
テキストファイルの場合、16進数の「1A」が見つかるとファイルの終わり(EOF)と判断します。
バイナリーの場合は、「1A」をEOFとして判断しません。
ですので、バイナリーファイルをテキストモードでOPENすると正常に動作しない場合があります。
No.1
- 回答日時:
Randomモードは、ファイルが固定長のレコードの集まりであるとして、入出力します。
何番目のレコードを読み書きするのかという番号を指定するので、途中の読み書きが出来ます。Randomモードでなくても、Seek文を使えば、ファイルの途中から読み書きできるので、その方が良いと思います。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- その他(データベース) c言語の問題です。これを踏まえてコーディングしたいのでおしえていただきたいです。 3 2023/08/03 09:27
- C言語・C++・C# c言語の問題です 2 2023/07/21 10:51
- PostgreSQL ポストグレにあるExcelファイルを開くには 1 2022/12/13 18:07
- その他(Microsoft Office) Excelのバージョンを2019 から2021へバージョンアップしました。 2 2023/07/21 15:41
- Excel(エクセル) エクセルのVBAについて とあるサイトのコードを参考に、CSVの文字化けを直すVBAを作成しているの 7 2022/11/04 14:15
- タブレット ワンドライブ内のWordファイルの編集について 1 2022/07/01 15:59
- その他(データベース) Excel VBA 転記について 1 2022/04/20 16:55
- その他(プログラミング・Web制作) python 気象データの取得 2 2023/06/20 23:54
- Visual Basic(VBA) Vba 互換モードでのAppActiveについて教えてください 2 2022/06/27 18:47
- その他(プログラミング・Web制作) pythonでクラスで複数のメソッドを利用する方法 2 2022/04/15 04:17
このQ&Aを見た人はこんなQ&Aも見ています
-
外出時に「待たせる妻」vs イライラする「待つ夫」は日本だけ?見習いたい海外事情
夫の家事参加に積極的なイメージのある海外でも、同様の事例はあるのか。結婚カウンセラーの佐竹悦子さんに伺ってみた。
-
Microsoft VBAで2GBを超えるファイルサイズのバイナリデータを読み込みたい。
Visual Basic(VBA)
-
【VBA】テキストファイルを指定行数からの読み込み
Visual Basic(VBA)
-
上下の位置揃えについて
Visual Basic(VBA)
-
-
4
IF関数で空欄(")の時、Nullにしたい
その他(Microsoft Office)
-
5
EXCELのVBAでEOFを誤認識
Visual Basic(VBA)
-
6
VBA バイナリ―から文字列にする方法
Visual Basic(VBA)
-
7
VBAでCSVファイルを途中行まで読んだ後で最初の行から読み直す方法はありますか?
その他(プログラミング・Web制作)
-
8
VBAのWindowオブジェクトとWorkbookオブジェクトの違い
Visual Basic(VBA)
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
BCPユーティリティの使用法_...
-
EXCELのVBAでフォルダ内のファ...
-
VBAでPowerPointからExcelにデ...
-
VB6側からテキストファイルをク...
-
アンケート結果をcsv出力できる...
-
RandomとBinaryモードの違い
-
大量のフォルダからひとつのフ...
-
コマンドプロンプトの「%1」と...
-
コマンドプロンプトのエラーに...
-
binファイルを解凍したいの...
-
stable diffusionのインストー...
-
バッチでテキストファイルから...
-
cygwinインストールでgccが利用...
-
Latexで図番号だけを「図1.1」...
-
バッチコマンドでファイル名の...
-
PCのアプリケーションを別のPC...
-
VBAでワークシートを引数として...
-
echo "abc" >> test.txt で、先...
-
複数のフォルダを開くバッチフ...
-
javaで大量のファイルを読み込...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VBAで新しい日付順にファイルを...
-
VBAでPowerPointからExcelにデ...
-
複数行の文字列を変数として使...
-
BCPユーティリティの使用法_...
-
特定フォルダ内のテキストファ...
-
テキストファイルを直接置換す...
-
VB6側からテキストファイルをク...
-
テキストファイルの行頭に文字...
-
Excel.VBA テキストファイルを...
-
バッチでiniファイルの編集
-
unicode文字列(日本語)のファイ...
-
access vbaでCSVファイルを文...
-
ある文字列を含む行の抽出
-
複数のCSVの指定行だけを残し、...
-
A列をテキストファイル名に、B...
-
fortranでのcsvファイルを出力...
-
ExcelVBAで以下のマクロを作成...
-
RandomとBinaryモードの違い
-
ソースコードの差分がある行番...
-
C#でのファイル編集と上書き保...
おすすめ情報
ありがとうございます。
しかし理解できていないのですが
つまりrandomモードはテキストファイルを読み書きするモードということでしょうか?
それだとfor inputやfor outputとどう違うのでしょうか?
自分でもrandomモードを使ってみたのですが
例えば4バイトのデータをファイルの途中に書き込もうとしようとすると
その後にゼロでーたが大量に生成して元のファイルよりも
大きなサイズのファイルを生成されてしまうのですが
なぜでしょうか?
使い方がよく分からないのですが
教えていただけないでしょうか?
ありがとうございます。
やはりまだ理解できていないのですが
質問1
binaryモードで開くとシーケンシャルで読み書きするということなのですが
数GBある大きなファイルの最後の方を書き換える場合には
時間がかかるのでしょうか?
質問2
Put intFileNumber, 2000, xxx
Put intFileNumber, 2001, yyy
・・・
とやると2000バイト目を書き込んだ後に
最初から読み直して2001バイト目に達してから
書き込んでという操作になるのでしょうか?
この方法よりも
Put intFileNumber, 2000, xxx
Put intFileNumber, , yyy
・・・
のようにするとして書き込んだ方が高速でしょうか?
質問3
ただ、二つ目の方法は書き込むデータがsingleやdoubleなどの非配列であれば
うまくいくのですが、バイト型の配列を書き込もうとするとうまくいきません。
それで一つ目の方法を使う必要があります。
どうすれば二つ目の方法でバイト型配列を使うことができますか?
ありがとうございます。
Put intFileNumber, 2000, xxx
Put intFileNumber, 2001, yyy
・・・
という操作は
Seek intFileNumber, 2000
Put intFileNumber, , xxx
Seek intFileNumber, 2000
Put intFileNumber, , yyy
という操作と同じなのでしょうか?
後者は毎回最初から読み出しているかも知れませんが
前者は順番に書き込んでいるということはありませんか?
ていうかそれが本当か確かめるには計算時間を比較するしかないでしょうか?
ありがとうございます。
何が正しいのか確かめるために、いろいろな書き出し方法の計算速度の比較を行ってみたのですが
いずれも大きな差異は見られませんでした。
もっとも高速なのは最初に大きな配列を生成してから、一度に書き込む方法です。
しかし要素ごとに書き込んでも、毎回アドレスを指定する方法などもほんの5以下程度しか
計算速度に違いは見られませんでした。
それで理由を考えてみたのですが
テキストファイルの場合だと最初から呼んでいかないと行やファイルの終端がどこにあるか分からないので任意の場所にランダムにアクセスすることができないのに対し、
バイナリファイルの場合だとアドレスで指定できるので
そもそもシーケンシャルやランダムといった分類が存在しないのではないでしょうか?
シーケンシャルやランダムといった用語はメモリで使われますが
いまデータはHDDに保存されているので
バイナリデータを扱う場合には常にランダムアクセスしているのではないでしょうか?
自分なりの結論は出ているのですが
検索などして調べてもその辺りが明確に書かれているページなどが見つからなかったので
できればご意見いただけないでしょうか?