アプリ版:「スタンプのみでお礼する」機能のリリースについて

VBAで、通常は文字列はInputを使って読み込むのですが
Binary形式で読み込んだらどうなるかについて調べてみました。

例えば、D:\text.txtのファイルに
123456789ABあ
という内容が書き込まれているとします。
このテキストデータを以下のようにして文字列数を指定した上で読み込むと

Sub Sample2()
Dim buf() As String
ReDim buf(0)
buf(0) = Space(10)
Open "D:\text.txt" For Binary As #1
Get #1, , buf(0)
Close #1
End Sub

最初の10文字である
123456789Aを読み込むことができます。

一方で、文字列数を指定せずに配列に直接読み込もうとすると

Sub Sample1()
Dim buf() As String
ReDim buf(0)
Open "D:\text.txt" For Binary As #1
'Seek #1, 9
Get #1, , buf
Close #1
'MsgBox buf 'ABCを返します
End Sub

なぜか最初の2文字をスキップして
最後の10文字である
3456789ABあ
が読み込まれます。

なぜ最初の二文字が読み込めなかったのでしょうか?

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

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

    長さとは何の長さのことでしょうか?
    ファイルサイズではないし、文字列サイズでもないし、一体なんでしょうか?

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

    ファイルサイズの計算の仕方は理解できました。

    テキストファイルをバイナリデータと読み込もうとしているから
    最初に二桁をファイルサイズとして認識してしまっているのだと思いますが
    このことってどこかのページか書籍に書かれていますか?

    散々検索して調べたのですが見つかりませんでした。

    二桁だけだとファイルサイズに上限ができてしまうことになります、
    これよりももっと大きなサイズのファイルにはどのようにして扱うのでしょうか?

    というかどういう時にファイルの頭二桁をサイズにして使用されるのでしょうか?

    No.4の回答に寄せられた補足コメントです。 補足日時:2015/11/01 22:32
  • ありがとうございます。

    2^16-1=65535という上限

    ということなのですがなぜ-1する必要があるのでしょうか?
    -1はどこから来た数値なのでしょうか?

    No.5の回答に寄せられた補足コメントです。 補足日時:2015/11/02 18:24

A 回答 (7件)

> ということなのですがなぜ-1する必要があるのでしょうか?


二進数の1111111111111111が十進でいくつかを計算するのに、2^15+2^14+・・・+2^2+2^1+2^0と計算するのが面倒なので、1を足せば10000000000000000になるので、2^16と簡単に計算できます。ここからさっきの1を引きます。十進数2桁の最大数値が99なのと比較して考えてみてください。
    • good
    • 0

文字列型変数の先頭に文字列の長さが書かれているのは、言語の実装の慣習的なものもあります。



これがCだと文字列型というかchar型の配列で扱われますが、長さを書かない代わりに終端マークとして0x00を付加します。なのでCでは文字列の中に0x00自身を入れることはできません。その一方でVBのように長さを先頭に書く実装になっている言語では、入れられるデータ値に制限がない代わりに常に長さを示す値を入れておくメモリを余分に消費する…とも考えられます。

もう今となってはGB単位でメモリを積んでいるのが当たり前なので、ここで1バイト2バイトけちった程度では全く大勢に影響しませんけど、これら言語が生まれた当時はメモリ空間が全体でも64KBしかなかった頃だったりするので、とにかくどうやって省メモリ化するかは至上命題であったという背景があります。
    • good
    • 0

> 散々検索して調べたのですが見つかりませんでした。



VBA付属のヘルプは見ない主義なのでしょうか?Getステートメントの説明に書いてあるのですが。

> 二桁だけだとファイルサイズに上限ができてしまうことになります

レコードサイズだと、先の回答に書いたのですが。ファイルサイズではないです。
レコードサイズには、2^16-1=65535という上限が出来ます。
この回答への補足あり
    • good
    • 0

> 2だけ小さいですがなぜでしょうか?


うっかりしてました。「レコード=長さを表す2バイト+データ本体」で、レコード長=12849なので、データ長は12847になります。

> 12から&H3231が計算される理由もよく分からないのですが

"1" の文字コード &H31、"2" の文字コード &H32 です。 参考: https://ja.wikipedia.org/wiki/ASCII
順番は、先頭か下位桁で後ろが上位桁なので(参考:リトルエンディアン)、&H3132じゃなくて &H3231 になります。
この回答への補足あり
    • good
    • 0

> 長さとは何の長さのことでしょうか?


> ファイルサイズではないし、文字列サイズでもないし、一体なんでしょうか?

レコードサイズですね。Getの処理単位です。文字列変数に読み込んだ場合は、文字列サイズがそうなります。
buf(0)に読み込んだ後では、buf(0)の文字列長が、"12" つまり &H3231 つまり 12849 になるはずです。msgbox len(buf(0)) して確認してみてください。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。


Lenで調べてみると12847になりました。
2だけ小さいですがなぜでしょうか?

12から&H3231が計算される理由もよく分からないのですが
どういう計算をしているのでしょうか?

検索してもかかりませんでしたが
どこのページに書かれてありますでしょうか?

お礼日時:2015/11/01 17:48

先頭2バイトは、長さを示すデータとみなされます。

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

https://msdn.microsoft.com/ja-JP/JA/library/offi …
にいろんな例が書いてあります。
    • good
    • 0

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