バイトの80〜FFを文字に変換するには?

解決


ちょこぽ  2003-04-07 08:34:59  No: 77587

こんばんは。
「バイナリエディタみたいに左にバイト、右側にそれに対応する文字」
を表示したいのですが、
  Open f_name For Binary As #1
  Do While Not EOF(1)
    Get #1, , byttmp
    byts = byts & Chr(byttmp)
  Loop
  Close
という風にしてみても、どうしても80(128)〜FF(255)の文字が7Fの文字と同じになってしまいます・・・
自分の検索方法が悪いのだと思いますが、いろいろと調べてみてもなかなか見つからないので困っています。

どうかよろしくお願いします。


魔界の仮面弁士  2003-04-07 19:30:03  No: 77588

>   byts = byts & Chr(byttmp)
Chr関数とChrB関数とChrW関数の違いに注意してみてください。


ちょこぽ  2003-04-07 22:35:32  No: 77589

魔界の仮面弁士さん、回答ありがとうございます。

>Chr関数とChrB関数とChrW関数の違いに注意してみてください。
MSDNとかで見てみたのですが、いまいち違い(使い方)がよくわかりません・・・
試しにChrBでやってみると漢字と?のみに、ChrWでやってみるとChrと全く同じになりました。

  Open f_name For Binary As #1
  Do While Not EOF(1)
    Get #1, , byttmp
    If byttmp >= &H81 And byttmp <= &H9F And Not EOF(1) _
              Or byttmp >= &HE0 And byttmp <= &HFC And Not EOF(1) Then
      Get #1, , byttmp2
        byts = byts & Chr("&H" & Hex(byttmp) & Hex(byttmp2))
    Else
      byts = byts & Chr(byttmp)
    End If
  Loop
  Close

こういう感じにしてみたら結構元のファイルと似た感じになったのですがまだ
byttmp2=00のときとかに飛ばされるなどがあるようです・・・


もじお  2003-04-07 23:57:46  No: 77590

Getで取得したのはバイナリ値なので、表示用の文字コードに直せば
良いのかも・・。
同じバイナリデータでも、ASCII、S-Jis、EUC、Unicode等で表示される文字が違うので  StrConv あたりを調べてみるのがいいかも。


ちょこぽ  2003-04-08 00:29:44  No: 77591

>StrConv あたりを調べてみるのがいいかも。
StrConv関数はこの掲示板の過去のスレッドに出てたので調べてみたのですが、
出来ないような気がします。(もしできるのであれば教えてくださると助かります^^;)
ちなみに変換したいのはShift-Jisです。


魔界の仮面弁士  2003-04-08 02:07:32  No: 77592

> MSDNとかで見てみたのですが、いまいち違い(使い方)がよくわかりません・・・

Chr関数:
  Shift_JIS(日本語版の場合)の文字コードを受け、対応する1文字(2バイト)のUnicode文字を返します。
  この関数を呼び出すと、Shift_JIS→Unicodeへの変換作業が発生しますので、対応していない
  文字を指定するとで、データが化ける可能性があります。

ChrW関数
  Unicodeのコード値を受け、対応するUnicode(UTF-16)文字を返します。
  この関数は、文字コードの変換を伴いません。

ChrB関数:
  &H00〜&HFFの範囲のコードを受け、対応する1バイト(1文字ではない)のStringを返します。
  この関数も、文字コードの変換を伴いません。特定の文字コードに関連付けられているわけでは
  無いので、Shift_JISのバイトデータを渡せば、結果もShift_JISになりますし、
  Unicodeのバイトデータを渡せば、結果もUnicodeとなります。

> 試しにChrBでやってみると漢字と?のみに、ChrWでやってみるとChrと全く同じになりました。
それは、どのようにして確認されましたか?
TextBoxなどの「Unicodeに対応していないコントロール」に表示されると、その時点で
Unicode→Shift_JISの変換が発生してしまいますので、データ化けの原因となりますよ。

中身を確認するのであれば、AscB関数などを利用するようにしてみてください。


ちょこぽ  2003-04-08 02:46:56  No: 77593

えっと・・・
読み込んだバイナリファイル(jpgのファイルを使ってます)はShift_JISなのでしょうか?
(バイナリは最近やり始めたばかりなので全然詳しくないです・・・)

いろいろといじっていたところ&H80以上のときに2バイトくっつけて変換すると全角がでるとかが分かってきたので

    Get #1, , byttmp
    If byttmp >= &H81 And byttmp <= &H9F And Not EOF(1) _
              Or byttmp >= &HE0 And byttmp <= &HFC And Not EOF(1) Then
      Get #1, , byttmp2
        byts = byts & Chr("&H" & Hex(byttmp) & Hex(byttmp2))
    Else
      byts = byts & Chr(byttmp)
    End If
というようにしたのですがこれはどこがいけないのでしょう?

>> 試しにChrBでやってみると漢字と?のみに、ChrWでやってみるとChrと全く同じになりました。
>それは、どのようにして確認されましたか?

文字列型(string)の変数に収容してからPrintで出力してます。
出力されたファイルをバイナリエディタで開いて元のバイナリファイル(jpg)と比較しています。


魔界の仮面弁士  2003-04-08 06:07:58  No: 77594

> 読み込んだバイナリファイル(jpgのファイルを使ってます)はShift_JISなのでしょうか?
Shift_JISでもUnicodeでもありません。そもそも、jpgファイルの中身は
テキストではありませんから、対応する文字コードも無い、という事になるでしょう。

> いろいろといじっていたところ&H80以上のときに2バイトくっつけて変換すると全角がでるとかが分かってきたので

Shift_JISの場合は、&H81〜&H9Fおよび&HE0〜&HEFの範囲の場合に、
直後の1バイト(&H40〜&H7E、&H80〜&HFCの範囲をとります)とあわせて、
2バイトで1文字が表現される仕様になっています。

なお、1バイトで1文字が表現されるのは、以下の範囲です。
&H21〜&H7Eの範囲:いわゆる英数字  (JIS X 0201 ローマ字)
&HA1〜&HDFの範囲:いわゆる半角カナ(JIS X0201 片仮名)
&H00〜&H20、&H80:制御文字(空白やタブや改行などがここに含まれます)

これ以外の未定義値の場合は、Chr関数で変換した際にデータが化ける可能性があります。

> というようにしたのですがこれはどこがいけないのでしょう?
これなら、最初からBinaryモードではなく、Inputモードで開けばよいかと思います。
指定したバイト位置から読み込みたい、という事であれば、

  Dim aaa() As Byte
  ReDim aaa(読み込みたいバイト数 - 1)
  Get #1, 読み込み開始位置, aaa

のようにすれば、Byte配列に、バイトデータを一度に読み込ませる事ができます。
それをさらに、Debug.Print等で文字列化して読みたいのであれば、
  Debug.Print StrConv(aaa, vbUnicode)  '元のファイルがShift_JISテキストだった場合
  Debug.Print CStr(aaa)                '元のファイルがUnicodeテキストだった場合
のようにすればOKです。

もし、Shift_JIS/Unicode以外のテキストファイルを扱いたい場合は、
「ADODB.Streamオブジェクト」という物を使えばOKです。

> 出力されたファイルをバイナリエディタで開いて元のバイナリファイル(jpg)と比較しています。
バイナリファイルを作成する場合は、通常、String型は使えません。
データをByteで保持しておき、それをPut#するのが一般的ですね。


ちょこぽ  2003-04-08 07:04:08  No: 77595

>バイナリファイルを作成する場合は、通常、String型は使えません。
説明が足りませんでしたm(_ _)m
バイナリファイルを開いてそれをバイナリエディタの右側と同じようにするのが目的で
出力したいのはバイナリエディタでいう右側の文字化けしたりしてる部分です。(Putは使わない)
ん〜・・・あまり説明出来てないのかな・・・

>Shift_JISの場合は、&H81〜&H9Fおよび&HE0〜&HEFの範囲の場合に、
>直後の1バイト(&H40〜&H7E、&H80〜&HFCの範囲をとります)とあわせて、
>2バイトで1文字が表現される仕様になっています。
>なお、1バイトで1文字が表現されるのは、以下の範囲です。
>&H21〜&H7Eの範囲:いわゆる英数字  (JIS X 0201 ローマ字)
>&HA1〜&HDFの範囲:いわゆる半角カナ(JIS X0201 片仮名)
>&H00〜&H20、&H80:制御文字(空白やタブや改行などがここに含まれます)
>これ以外の未定義値の場合は、Chr関数で変換した際にデータが化ける可能性があります。

JPGの場合、E0 00という風に並んでるところとかがあるのですが、
この場合、どのようにすればちゃんと変換されるのでしょうか?

http://storm.prohosting.com/wowieqdn/aaa.jpg
このファイルが元のファイル
http://storm.prohosting.com/wowieqdn/temp.txt
変換して出力したファイル

このようになってしまい、バイナリエディタで開いてみると1行目の4、5文字目のE0 00が0Eに変わるなどが起こっているのです。

>Inputで開く
その場合、なぜか途中で読み込みが終わってしまいます(たぶんですがEOFと判断されてしまう)

お手数かけます。


魔界の仮面弁士  2003-04-08 07:38:37  No: 77596

> 出力したいのはバイナリエディタでいう右側の文字化けしたりしてる部分です。
ん? 文字化けしても構わない、という事でしょうか?
やりたい事がよくわからないのですが…。

バイナリファイル(temp.jpg)を読み込んで、
それをどのようなファイルに変換させたいのでしょうか?

> JPGの場合、E0 00という風に並んでるところとかがあるのですが、
> この場合、どのようにすればちゃんと変換されるのでしょうか?
ごめんなさい。そもそも、ちょこぽさんが、E0 00を
「どのようなデータに変換したいのか」がわからないです。

# 変換規則さえ教えていただければ、適切な回答ができるかと思いますが…。

> バイナリエディタで開いてみると1行目の4、5文字目のE0 00が0Eに変わるなどが起こっているのです。
バイナリエディタで見て、全く同じデータとして出力したいのなら、
ChrもChrBも関係なく、Get #で受け取ったByteデータを、
そのまま単純に Put #で吐きだしてやれば済むかと思います。

ただしそれは、元のファイルと1バイトの違いも無い、全く同じ
データという事ですから、「FileCopy」で十分かと思いますけれど。。。

>> Inputで開く
Inputモードで開く、と書いたのは、読み込み元のファイルが、
可読文字列データのみで構成されたバイナリファイル、つまり、
テキストファイルであった場合の話です。テキスト以外のデータが
含まれているファイル(jpgファイルなど)の場合は、
やはりBinaryモードで開く必要があります。

> その場合、なぜか途中で読み込みが終わってしまいます(たぶんですがEOFと判断されてしまう)
おそらく、途中にEOF文字(&H1A)が含まれていたのでしょうね。


ちょこぽ  2003-04-08 08:11:39  No: 77597

なんか自分でもわからなくなってきてしまった・・・(汗
これについてはもうちょっと理解してからきちっと質問したいと思いますm(_ _)m

それと、もうひとつわからないところがあるのですが(こっちはちゃんと説明できるはず・・・)

http://madia.world.coocan.jp/cgi-bin/VBBBS2/wwwlng.cgi?print+200210/02100021.txt
この過去ログの方にInetコントロールでCGIにPOSTというのがあったのですが、
Inetコントロールでは画像などを送るのは不可能なのでしょうか?
もしいけるのならその時はバイナリをどう変換したのかが知りたいです。
お願いします。


ちょこぽ  2003-04-08 08:35:10  No: 77598

ちょっと説明の追加・・・
InetコントロールのPOSTの場合ですが、横取り丸というツールでログを見ているとこれは文字列型で送っているように思えるので
バイナリファイル(画像など)のバイトをどのように変換すれば良いか、ということです。


魔界の仮面弁士  2003-04-08 08:49:17  No: 77599

> この過去ログの方にInetコントロールでCGIにPOSTというのがあったのですが、
そのログ中でも触れられていたように、Inetはテキストデータのみが送信できます。

> Inetコントロールでは画像などを送るのは不可能なのでしょうか?
一応、不可能ではないでしょうね。
VB側では、バイナリデータをテキストデータに変換してから送出し、
cgi側では、そのテキストデータをバイナリに復元すれば良いのですから。

ただ、それは面倒なので、バイナリデータを直接送出できる、
Winsockを利用された方が、便利だとは思いますけれどね。
# httpサーバーではなく、ftpサーバーであれば、Inetでも
# バイナリファイルを送れるのですけれどね…。

> もしいけるのならその時はバイナリをどう変換したのかが知りたいです
例えば、送信するデータ量が倍になってしまいますが、
  &H82 &HBF &H82 &HE5 &H82 &HB1 &H82 &HDA
という8バイトのデータを送る代わりに、それを
  "82BF82E582B182DA"
という16進数値にして送る、という方法があります。

そしてサーバー側では、受け取ったそのデータを、
先頭から2文字ずつ切り出していき、"82" → &H82 のように
バイト値に復元していくわけです。

# バイナリデータを、復元可能なテキストにする方法は、
# 「Ish」や「URLEncode」など、他にも幾つかあります。


魔界の仮面弁士  2003-04-08 09:00:55  No: 77600

> 横取り丸というツールでログを見ているとこれは文字列型で送っているように思えるので

表示上、テキストに見えているというだけでしょう。
実際にはバイナリデータがやりとりされています。

横取り丸では、バイナリデータをEditコントロール(VBでいうTextBox)に
表示させているので、表示不可能な文字は、別な文字に置き換えて表示されています。


ちょこぽ  2003-04-08 22:21:13  No: 77601

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

>バイナリデータを直接送出できる、Winsockを利用された方が、便利だとは思いますけれどね。

winsockでやってみようと思います。
一応いろいろ参考にしながら作ってみたのですが、
どうもうまく動きません・・・
一応送れてるようなのですが、CGIに書き込めてなく、
サーバーからの反応はヘッダーっぽい部分だけです。

http://storm.prohosting.com/wowieqdn/aaa.zip

自家鯖を立ててCGIを実行しています。
CGIのフォームのname等は横取り丸のログからコピペしてるので間違いないはずです。


ちょこぽ  2003-04-09 04:41:24  No: 77602

>どうもうまく動きません・・・
vbCrLfの数を調節したらちゃんとPOSTできました^^

長い間親切にお答えくださってありがとうございましたm(_ _)m


ちょこぽ  2003-04-09 04:41:43  No: 77603

解決ボタン・・・


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

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






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