列挙型をテキストに落とす際Nullが入るのを防ぐには?


ちゃこ  2005-05-11 00:12:07  No: 89749

列挙型をPutステートメントでテキストファイルに落としているのですが、
Type Data
  Head    as string *10
  Detail  as string *10
  Foot    as string *10
end type
のような簡単なものだと大丈夫なのですが、

type PLData
  title    as string
  nData()  as Data
end type

dim allData as plData
(実際はもっと複雑です・・・)
といったように列挙型をネストしていき、最後のallDataをPUTステートメントで
書き出すと各構造体の先頭の項目(この場合はtitleとHead)の頭にNull値が
入ってしまいます。なぜでしょう?

何とかしてこのNullが入らないようにしたいのですが、わかる方よろしくお願いします。

ちなみに環境はWin2000、ExcelVBA2000です。


papa  2005-05-11 04:32:44  No: 89750

nData()  as Data
が配列だからではないですか


魔界の仮面弁士  2005-05-11 06:40:53  No: 89751

用語は正確に書かないと、第三者には伝わりませんよ。(^_^;)

> 列挙型をPutステートメントでテキストファイルに落としているのですが、
> Type Data
列挙型の宣言に使うのは「Enumステートメント」です。
Typeステートメントは「ユーザー定義型」の宣言ですね。

> 最後のallDataをPUTステートメントで
> 書き出すと各構造体の先頭の項目(この場合はtitleとHead)の頭にNull値が
> 入ってしまいます。
具体的な例が無いので、こちらで実験した結果を使って動作を説明します。
動作の詳細は、VBAヘルプのPutステートメントの解説などで確認してください。

'-------
Option Explicit

Private Type Data
  Head    As String * 10
  Detail  As String * 10
  Foot    As String * 10
End Type

Private Type PLData
  Title   As String
  nData() As Data
End Type

Private Sub Test()
    Dim allData As PLData
    ReDim allData.nData(1)
    
    allData.Title = "タイトル"
    allData.nData(0).Head   = String(10, "H")
    allData.nData(0).Detail = String(10, "D")
    allData.nData(0).Foot   = String(10, "F")
    allData.nData(1).Head   = String(10, "h")
    allData.nData(1).Detail = String(10, "d")
    allData.nData(1).Foot   = String(10, "f")

    Dim FNo As Integer
    FNo = FreeFile()
    Open "C:\NewFile.bin" For Binary As #FNo
    Put #FNo, , allData
    Close #FNo
End Sub
'--------

この場合、バイナリの内容はこうなります。

00-01    08,00                          → PLData.Titleのバイト数。今回は「8バイト」。
02-09    83,5E,83,43,83,67,83,8B        → PLData.Titleの内容。今回は "タイトル"。
0A-0B    01,00                          → PLData.nData()配列の次元数。今回は「1次元配列」。
0C-0F    02,00,00,00                    → PLData.nData()配列の(1次元目の)要素数。今回は「要素数=2」。
10-13    00,00,00,00                    → PLData.nData()配列の(1次元目の)下限添字値。今回は「LBound値=0」。
14-1D    48,48,48,48,48,48,48,48,48,48  → "HHHHHHHHHH"
1E-27    44,44,44,44,44,44,44,44,44,44  → "DDDDDDDDDD"
28-31    46,46,46,46,46,46,46,46,46,46  → "FFFFFFFFFF"
32-3B    68,68,68,68,68,68,68,68,68,68  → "hhhhhhhhhh"
3C-45    64,64,64,64,64,64,64,64,64,64  → "dddddddddd"
46-4F    66,66,66,66,66,66,66,66,66,66  → "ffffffffff"


ちゃこ  2005-05-11 18:27:34  No: 89752

>列挙型の宣言に使うのは「Enumステートメント」です。
>Typeステートメントは「ユーザー定義型」の宣言ですね。
ご指摘のとおりでございます。ほんと正しく使わないとどんな勘違いが生まれるか、わかりませんものね。すみません。(^_^;)

動作の詳細はご推測のとおりです。違うといえばユーザー定義型の配列がさらに入り組んでいるくらいでしょうか。

書き込み時の指定でバイナリでもランダムでもやってみました。
分析いただいたように
00-01    08,00  → PLData.Titleのバイト数。今回は「8バイト」。
というのが、エディタでNullと読まれているような気がします。これって、エディタでJISで見たとき、頭数桁空白(もしくはNULL)があって、そのあとに”タイトル"というのが表示されていませんか?(こちらではそうなりました)
その頭数桁を取り除きたいのですが・・・。
何かよい方法はありませんか?


Dental  2005-05-11 19:24:31  No: 89753

> エディタでJISで見たとき
JIS というか、Shift_JIS ですね。

> 頭数桁空白(もしくはNULL)があって
VBA的に言えば、「vbNullChar」に相当する文字ですね。

> その頭数桁を取り除きたいのですが・・・。
そもそも Putステートメントはバイナリ出力のための命令ですから、
テキストのみの出力を目的として使うというのは、
本来の使い方ではないと思います。

そのバイナリがどのように書かれるのかを、十分に把握しているなら
Putでも良いですが、理解せずに使うと、今回のように非可読文字が
混入する原因となってしまうでしょう。

この場合は Print# ステートメントを使って、ユーザー定義型の
各メンバを個別に出力するようにしてみてください。(面倒ですが確実かと)

あるいは、ユーザー定義型ではなくクラスにしておき、そこに
 * Print #でファイルに吐き出すためのメソッド
 * 各メンバを繋げた Byte配列を作成するメソッド
のいずれかを実装するという作り方もありますね。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加