おせわになります。 以下のコードを実行して作られた dat ファイルを テキストエディタで開いた状態が理解できません。 Option Explicit Private Type Person Age As Integer Name As String * 32 End Type Private Sub test() Dim p As Person Open "C:\test.dat" For Random As #1 Len = Len(p) p.Age = 17 p.Name = "太郎" Put #1, 1, p p.Age = 18 p.Name = "花子" Put #1, 2, p Get #1, 1, p Debug.Print p.Age Debug.Print p.Name Get #1, 2, p Debug.Print p.Age Debug.Print p.Name Close #1 '-----イミディエイト----------- ' 17 '太郎 '18 '花子 '-----/イミディエイト---------- End Sub 作成された test.dat をテキストエディタで開くと ------------------------- 17 太郎 18 花子 ------------------------- ↑こうである事を予想していたのですが、 実際は↓こうでした。(メモ帳でひらいて Ctrl+A Ctrl+c ここで Ctrl+v) ------------------------- 太郎  花子 ------------------------- メモ帳でみると 太郎 も 花子 も改行しないのですが、 ここに張り付けると改行が入ってしまいました。 また 17 18 はどこにもありません。 p.Age はどうなってしまったのでしょうか? Putステートメントのヘルプはことさら難解に思えます。 引用: ユーザー定義型の要素を Put ステートメントを使って書き込む場合、 各要素は独立しているかのように書き込まれます。 ただし、各要素の間には何も埋め込まれません。 この箇所だろうか、という場所を書きだしてみましたが、 理解が及びません。 何が起きているのでしょう。 投稿日時: 11/11/30 00:11:13 投稿者: yamaV1.02β 花子の改行はブラウザの折り返しでした。  太郎  花子 投稿日時: 11/11/30 03:32:07 投稿者: Abyss 10進数の「17」= 16進数の「11」 投稿日時: 11/11/30 11:38:52 投稿者: Bon そもそも、バイナリファイルをテキストエディタで開いて 思いどりに成っていなと言うのが間違いなのでは? 投稿日時: 11/11/30 12:49:49 投稿者: へっぽこ やりたいことはこうなのかなーと。 Sub test() 'OutputよりAppendの方がいいのかな? Open "C:\test.dat" For Output As #1 Print #1, "17" Print #1, "太郎" Print #1, "18" Print #1, "花子" Close #1 End Sub ご自身のコードだと何が出力されているのか?…はこういうエディタで開いてみると理解できるかと。 http://www.vector.co.jp/soft/win95/util/se079072.html 投稿日時: 11/11/30 15:46:32 投稿者: ふるふる バイナリファイルなんだからバイナリで確認しないとね。 その上で、テキストの部分をテキストとして読むようにする。 バイナリファイルの読み取りですが、バイナリエディタのソフトがいいですが、 見るだけならエクセル用のツールを作りました。 http://www.moug.net/cgi-bin/softwaredl.cgi?excel+SI2011071301 頻繁にバイナリファイルを扱うならバイナリエディタがお勧めですが、 簡単にファイルの中身を確認したい、というような場合は、こういったツールで十分かと。 投稿日時: 11/11/30 17:53:18 投稿者: WinArrow 予想通りのような形式で出力するのでしたら、 へっぽこ さんのレスになります。 しかし、AgeとNameを1件のデータとして出力するのでしたら、 Print #1,"17太郎" Print #1,"18花子" という記述になります。 出力したファイルをどのように使うかで出力方法が異なってきます。 バイナリーファイルにするのか?単なるテキストファイルにするのかも含めて・・・ 投稿日時: 11/11/30 20:40:57 投稿者: yamaV1.02β 皆さま、書き込みありがとうございます。 ふるふる11/11/30 15:46:32 さんの引用: バイナリファイルなんだからバイナリで確認しないとね。 ファイル モード For Random とはバイナリファイルなのですか。 考えもしませんでした。 他に For Binary ってあるので、これはバイナリファイルなのか、 と想像していましたが、 For Random が何なのか正体不明です。 バイナリエディターというものを「ソフト改竄ツール」 程度の認識しかなく、使った事がありませんが、 せっかくなので ふるふる さんのツールで .dat ファイルを観察してみる事にいたします。 投稿日時: 11/11/30 21:34:23 投稿者: kanabun おじゃまします。 Put#,Get#で文字列の出力、読み出しの際の問題点を見やすくするため、 タイプ文の Name As String * 32 を Name As String * 14 に変更して宣言してみます。 Option Explicit Private Type Person Age As Integer Name As String * 14 End Typeこの > Name As String * 14 というのは、文字列長として14文字ということでしょうか? それとも シフトJIS変換後のバイト数が32バイトということでしょうか? 論より証拠、実際に出力してみることにします。 Sub test2() Dim p As Person Dim Filename As String: Filename = "H:\(Data)\temp13\test.dat" Open Filename For Output As #1 'ファイルサイズを 0 にする Close 1 Open Filename For Random As #1 Len = Len(p) p.Age = 17 p.Name = "太郎Taro" Put #1, 1, p p.Age = 18 p.Name = "山田花子Hanako" Put #1, 3, p '---------------------------------- Binary表示 '11 00 91 BE 98 59 54 61 72 6F 20 20 20 20 20 20 '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '12 00 8E 52 93 63 89 D4 8E 71 48 61 6E 61 6B 6FPut#で出力した結果を バイナリファイルエディタで覗いてみると上のようになっています。 (実際は改行コードは無く、一続きのデータです) Integerデータは2バイト(リトルエンディアンですから、上位バイトが先に来ます)、 文字列はメモリ上のUnicode文字列が ShiftJISに自動変換され、(1)レコード目の "太郎Taro" は ShiftJISで8バイトですから、のこりの6バイト分は スペースで 埋められ 20 が6個、置かれているのが分かります。 第2レコードは出力されていませんから、Chr$(0)が16個ならんでいるだけです。 第3レコードの文字列部分は ShiftJISで "山田花子Hanako"とちょうど定義長と 同じ長さの14バイト文字列で【スペースはありません】。 で、これをGet#で読み込んでみます。 イミディエイト・ウィンドウには スペースがあったばあい確認しにくいので、 スペースを"x"に置き換え表示してみます。 Get #1, 1, p Debug.Print p.Age Debug.Print Replace(p.Name, " ", "x"), Len(p.Name) Get #1, 3, p Debug.Print p.Age Debug.Print Replace(p.Name, " ", "x"), Len(p.Name) Close #1 '-----イミディエイト----------- ' 17 '太郎Taroxxxxxxxx 14 ' 18 '山田花子Hanakoxxxx 14 End Sub イミディエイト・ウィンドウにはこのように表示されます。 第1レコードも、第3レコードも、文字列は「14文字」と表示されますが、 これはスペースを含んでの文字長です。 不思議なのは、ファイルにShiftJISで保存されたときは 第1レコードは「太郎Tarou 」とスペースは6個だったのに、 Get# してみると、スペースが8個になっていることです。 もっと不思議なのは、3番目の「山田花子Hanako」というデータです。 As String * 14 と定義してファイルに格納したので、ファイル内では お尻のスペースは無いはずなのに、 As String * 14 の定義のままで Get#してみると【4個のスペース】がお尻に ついていることです。 投稿日時: 11/12/01 01:12:00 投稿者: kanabun yamaV1.02β さんの引用: 他に For Binary ってあるので、これはバイナリファイルなのか、 と想像していましたが、 For Random が何なのか正体不明です。 For Random 「も」Binaryファイルです。 For Binary とのちがいは、 For Binary なら Get #1, 3, buf ← ここで 3 は3バイト目を意味する のに対し、 For Random のとき Get #1, 3, buf ← この3は3ブロック目(Record 3)を 意味するわけです。 For Output ですと、テキスト・モードですから、 整数データは文字列に変えて、 Print #1, "17","太郎Tarou" Print #1,, Print #1, "17","山田花子Hanako" のような先頭から順に(この場合はTAB区切りで)出力し、 読み込むときも、先頭から順に Input# で項目ごと またはLine Input# で一行ごとに読むことになります。 ランダム・アクセス・モードならば、それこそランダムにレコードにアクセスできます。 また、ランダム・アクセス・モードならば、数値データはそのまま構造体にセットすれば Integerなら2バイト、Longなら4バイト、Doubleなら8バイトでいつもファイルに 格納されます。(ファイルサイズを縮小でき、アクセスが高速になります) 問題は「文字列」データですが、 As String * 14 のように、固定長文字列で定義すると、ファイルにPutする場合は 自動で ShiftJISに変換し、14バイトに収まるように(満たない場合はスペースを パディングして)出力してくれますが、これをGet#で読むと、 > As String * 14 14×2バイト分=28バイト分のメモリ領域を準備し、ファイルから14バイト分 読み込んだShiftJISコードをUnicodeに変換して格納する(ような処理をする) ので、文字列が漢字など「2バイトコード」であるときは、その2バイトコード の分だけ「お尻にスペースがつく」ことになります。 いま Name As String * 5 と宣言してPutした文字列が "Tarou" "太郎a" と2レコードあったとしますと、Put#でファイルには そのとおり「5バイト」 で格納されるわけですが、Get#で読み込むとき、 5×2 = 10バイト分(5文字分)のメモリ領域を確保して、 □□□□□□□□□□ ここにファイルから 5バイト取り出し、それをUnicodeに変換した 文字を埋め込んでいくイメージになります。 ファイルの"Tarou"(5バイト) は Unicodeに変換すると10バイトです。 ■■■■■■■■■■ T a r o u いっぽう、"太郎a"(5バイト)は Unicodeに変換すると 6バイトです。 ■■■■■■□□□□ 太 郎 a お尻の4バイト分は変換される文字が無いので、スペースのまま残ります。 (4バイト余るだけなのに、4文字分のスペースがつくので、この説明では ちょっと不十分ですが、イメージとしては合ってると思います) (説明がへたなので、途中省略して、代替案を示します) 代替案は 構造体内でStringを「固定長でなく不定長で」宣言することです。 Option Explicit Type uPerson Age As Integer Name As String End Type Sub try1() Dim p As uPerson Dim Filename As String: Filename = "H:\(Data)\temp13\Try1.dat" Open Filename For Output As #1 'サイズを0にする Close 1 Debug.Print Len(p) '→p構造体:Total 6バイト '可能性として考えられる文字列の最大バイト長を加算して 1レコードあたりの単位バイト長を '指定してOpenします。↓ Open Filename For Random As #1 Len = Len(p) + 14 ' 6 + 14 = 20バイト宣言 p.Age = 17 p.Name = "太郎Taro" Put #1, 1, p p.Age = 18 p.Name = "山田花子Hanako" Put #1, 3, p p.Age = 20 Put #1, 4, p ’同じ文字列を Record 4番目にもPut する '---------------------------------- Binary表示 ' 6 ← Len(p) 1レコード最少長さ + 14 = 20バイト '11 00 08 00 91 BE 98 59 54 61 72 6F 00 00 00 00 00 00 00 00 '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '12 00 0E 00 8E 52 93 63 89 D4 8E 71 48 61 6E 61 6B 6F 00 00 '14 00 0E 00 8E 52 93 63 89 D4 8E 71 48 61 6E 61 6B 6F 'Get# は 1ページ目と 3ページ目だけGetします。( Randomアクセス ) Get #1, 1, p Debug.Print p.Age Debug.Print Replace(p.Name, " ", "x"), Len(p.Name) Get #1, 3, p Debug.Print p.Age Debug.Print Replace(p.Name, " ", "x"), Len(p.Name) Close #1 End Sub '----------------- イミディエイト・ウィンドウ ' 17 '太郎Taro 6 ' 18 '山田花子Hanako 10 イミディエイト・ウィンドウで読み込み確認している Debug.Print Replace(p.Name, " ", "x"), Len(p.Name)部分の スペースを"x"に置換する処理は実際には不要です。なぜなら、 不定長文字列宣言してファイルにPut#したときは、ファイル内のその文字列の直前に 文字列の実際のバイト長をSaveしてくれてるからです。 投稿日時: 11/12/01 01:24:19 投稿者: kanabun 訂正 「固定長」の反対だから「不定長」なんて表現してしまいました m(_ _)m 通常 「可変長」と云ってますね。 投稿日時: 11/12/01 01:47:50 投稿者: kanabun 補足 Random Accessファイルは データベースそのものです。 可変長文字列データは VARCHAR2(38) などとDefしますが、それは 最大38文字ということで、固定長38文字のように 満たない分がスペースで 埋められることはありません。 また、インデックスファイルを作っておくとアクセスが速いのも ファイルの構造がそうなっているからです。 投稿日時: 11/12/01 08:18:31 投稿者: kanabun すみません。もう一つ訂正です '11 00 91 BE 98 59 54 61 72 6F 20 20 20 20 20 20 '12 00 8E 52 93 63 89 D4 8E 71 48 61 6E 61 6B 6F > バイナリファイルエディタで覗いてみると上のようになっています。 >(実際は改行コードは無く、一続きのデータです) > Integerデータは2バイト(リトルエンディアンですから、上位バイトが先に来ます)                            ↓                            下位バイト 投稿日時: 11/12/01 21:51:52 投稿者: yamaV1.02β >文字列はメモリ上のUnicode文字列が ShiftJISに自動変換され そうだったのですか。 ややこしいのですね。 自動でやられてしまうとは、ショックでした。 ------------------------------------------- kanabun さん、 解説ありがとうございます。 Put ステートメントの使用例 でデータベースを 扱っている事に合点がいきました。 横穴掘ると、疑問がいくらでも出てくる状態です。 収拾つかなくなりそうなので今回は封印いたします。 ありがとうございました。 ようこそ yamaV1.02βさん 会員情報変更 Q&A (詳細検索) サイト内 「VBAエキスパート」資格対策に役立つ 即効テクニック Excel VBAVBA達人への道も一歩から Excel VBA ビギナーズ社会人必見!覚えて仕事でトクをする 仕事に役立つExcel関数 利用者の皆様にお知らせです。 " 12/1 12月の書籍プレゼント受付スタート " 11/28 VBAエキスパートコラム2周年記念キャンペーン " 11/28 即効テクニック、更新しました " 11/24 フリーソフト更新しました 一覧 " エラーチェック3 " ユーザーフォームについて。 " エラーチェック2 " レポート上にあるイメージオブジェクトを表示させたりさせなかったりする方法 " データ開始セル列番号の取得 " 英語表示を和文表示にしたい。 " セルに色を付ける " エラー表示をさせたい " 名前の定義の一括削除(2つのPrint_Areaについて) " 集計クエリについて インプレスジャパンより 役立つ書籍を抽選でプレゼント! Microsoft Officeの使用スキルを証明するMOS試験 運営会社 - お問い合せ - 広告掲載 - 規約 - プライバシーポリシー All rights reserved by Odyssey Communications Inc. Microsoft、Windows、およびMicrosoft Officeは Microsoft Corporationの米国及びその他の国における登録商標です。 また、その他システム名、プログラム名などは、一般に各社の登録商標です。