プロが教える店舗&オフィスのセキュリティ対策術

VBAを使って、
あるバイナリファイルを読み込み
5000バイト~5100バイトの部分だけをカットして
ファイルを出力するプログラムを作りたいと考えています。

Dim buf As String
Dim buf2 As String

Open filepath For Binary As #1

buf = Space(5000)
buf2 = Space(FileLen(filepath(j)) - 5100)

Get #1, , buf
Get #1, 5100, buf2


Close #1


intFileNumber = FreeFile 'ファイルの空き番号を得る

Open Strpath For Binary As intFileNumber


Put intFileNumber, , buf
Put intFileNumber, 5000, buf2


Close intFileNumber '必ず、最後にcloseする必要がある


この方法で作成すると元が64.5kBだったファイルが76.5kBとなり、
元よりも大きなサイズになってしまいます。

恐らく、bufをbyteで定義して
for文で一つずつ回していけばうまくいくのではないかと思うのですが
この方法だと時間がかかってしまいます。
for文を使わずに一度にまとめてファイルを読み込んで
入出力したいのですがどうすれば良いでしょうか?

質問者からの補足コメント

  • ありがとうございます。

    パーフェクトでした。

    あともう一つお聞きしたいのですが

    文字列で「cHRM」、16進数で「6348524D」のバイト位置を検索して調べたいのですが
    どうするのがもっとも高速でしょうか?

    bufをstringとして定義しておいて、
    ファイルを文字列として読み込み
    「cHRM」をInstrで検索する。
    しかしこの方法だと「cHRM」のバイト単位での正確な位置は特定できませんよね?

    となると、
    「6348524D」を一度10進数に変換してから
    教えてくださったbyte型の配列に取り込む方法で
    取り込み
    For文を使って、一つ一つ適合する箇所を探すしかないでしょうか?
    For文は回数が多くなると時間がかかるので
    もっと良い方法があれば教えてください。

    No.1の回答に寄せられた補足コメントです。 補足日時:2015/10/28 19:47
  • そもそもなぜ
    文字列型で読み込んだ時とバイト型で読み込んだ時で
    出力されるファイルサイズが異なるかも教えていただけないでしょうか?

      補足日時:2015/10/28 20:07
  • ありがとうございます。

    一つのファイルは
    数十KB程度なのですが数百とか数千個読み込むのでできる限り高速にしたいと考えています。

    VBAだとForだとできないとしてVBやC言語などは
    Forを使わずに全検索する機能があるのでしょうか?

    あと、Unicodeだと一文字2バイトのはずなので
    ANSI形式で読み込まれているということでしょうか?
    でもUnicode形式をANSIに変換してみるとVBA上で文字を読むことができなくなるので
    Unicodeを使っていると思ったのですが・・・
    なぜでしょうか?

    もうしばらく質問をあげておきますので
    もしご回答があればよろしくお願いいたします。

    No.2の回答に寄せられた補足コメントです。 補足日時:2015/10/28 21:38
  • ありがとうございます。

    コードまで書いて下さり助かりました。

    No.3の回答に寄せられた補足コメントです。 補足日時:2015/10/29 12:34

A 回答 (3件)

> VBAだとForだとできないとしてVBやC言語などは


> Forを使わずに全検索する機能があるのでしょうか?

ファイルに保存されているシーケンシャルなデータを検索するのですから、言語によらず頭から順にチェックしていくしかないはずです。組み込みの検索関数などの機能があって多少の最適化アルゴリズムを使用しているかもしれませんが、結局は同じことではないでしょうか?
あと、速度を気にされるのでしたらVBAよりも、いずれかのコンパイル言語を使用したほうが良いと思います。


> あと、Unicodeだと一文字2バイトのはずなので
> ANSI形式で読み込まれているということでしょうか?

たしかに内部表現ではUnicodeを使用しているかもしれませんが、そもそもファイルをbinaryモードでオープンしている時点で適切なエンコードは行われないと思います。
この回答への補足あり
    • good
    • 0

No.1です。

私もそんなに詳しくないのですが……
検索は、数十KB程度のファイルなら、byte型配列をループで行ってもそんなに時間はかからないのではないでしょうか?
検索対象1文字目だけをチェックしてヒットしたら2~4文字目の確認を行えばよいと思います。

Sub bar()
Dim filename As String
filename = "path\file.bin"
Dim MAXSIZE As Integer
MAXSIZE = FileLen(filename) - 1
Dim buf() As Byte
ReDim buf(MAXSIZE)
Dim index As Integer

Open filename For Binary As #1
Get #1, , buf()
Close #1

index = 0
Do While index <= MAXSIZE - 3
If buf(index) = &H63 Then '1文字目チェック
If buf(index + 1) = &H48 And buf(index + 2) = &H52 And buf(index + 3) = &H4D Then
Exit Do
End If
End If
index = index + 1
Loop
MsgBox index
End Sub



> 文字列型で読み込んだ時とバイト型で読み込んだ時で
> 出力されるファイルサイズが異なるかも教えていただけないでしょうか?

こちらも再現確認したわけではないので憶測ですが、そもそもstring型の1文字は、1byteとは限らないのではないでしょうか?
なので、サイズ計算に齟齬が生じるのではないかと思います。
この回答への補足あり
    • good
    • 0

byte型の配列を使えば良いと思います。



Option Explicit

Sub foo()
Dim buf(5000 - 1) As Byte
Dim buf2() As Byte
Dim infile As String
Dim intFileNumber As Integer
Dim size As Integer

infile = "path\test.bin"
ReDim buf2(FileLen(infile) - 5100)

Open infile For Binary As #1
Get #1, , buf()
Get #1, 5100, buf2()
Close #1


intFileNumber = FreeFile 'ファイルの空き番号を得る

Open "C:\work\excel\out.bin" For Binary As intFileNumber
Put intFileNumber, , buf()
Put intFileNumber, 5000, buf2()
Close intFileNumber '必ず、最後にcloseする必要がある

End Sub
この回答への補足あり
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!