サーバー上のファイル文字列所得の文字化け

解決


ラッキー池田  2010-04-27 01:56:06  No: 38352  IP: 192.*.*.*

以前別の案件で以下のソースでサーバー上のファイルの中身(半角英数の文字列)を取得することに成功し使用していました、今回別の案件で使用したところ文字列の最後尾に変な文字化けが表示されてしまいます、
改行が化けているのかと思ったのですが改行ではないようです。

以前のファイルはサーバーでphpで書き出したものです
今回のファイルはWIN上のファイルだったのでそれが原因かと思い、同じようにサーバーで書き出しにしましたが結果は同じでした
文字コードも一通りは試してみましたがダメでした。

文字列最後尾の文字化けを治す方法を教えてください、宜しくお願いします。




const{追加}
  URL ='http://test.com/test.txt';


  //接続の確立
  hSession :=InternetOpen(nil, INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
  try
  if Assigned(hSession) then
  begin
    //URLのハンドルを取得
    hReqUrl :=InternetOpenUrl(hSession,PChar(url), nil, 0,INTERNET_FLAG_RELOAD, 0);
    try
    if Assigned(hReqUrl) then
    begin
      while true do begin
       //URLハンドルを元にBufferに読み込む(ファイル最後まで繰り返す)
       InternetReadFile(hReqUrl, @Buffer, Sizeof(Buffer), ReadCount);
       //ファイルの最後までいったら抜ける
       if ReadCount = 0 then Break;
       HtmlStr :=HtmlStr + string(Buffer);
      end;
        //HtmlStr確認用のアレ
        //ShowMessage(HtmlStr);
    Label1.Caption := HtmlStr;

    try
    WebBrowser1.Navigate(HtmlStr);
    except

    end;

    HtmlStr := '';
    end;
    finally
      InternetCloseHandle(hReqUrl);
    end;
  end;
  finally
    InternetCloseHandle(hSession);
  end;

編集 削除
tor  2010-04-27 03:33:03  No: 38353  IP: 192.*.*.*

> 改行が化けているのかと思ったのですが改行ではないようです
改行でないなら何なのか、(LabelやShowMessageの目視ではなく)
実際に文字コードを確認したのでしょうか?

まあ原因はおそらくココ
> InternetReadFile(hReqUrl, @Buffer, Sizeof(Buffer), ReadCount);
...
>HtmlStr :=HtmlStr + string(Buffer);
ReadCountには実際に読み込めたデータサイズが入ってくるのではないですか?
だとしたらBufferを全部足すのではなく、読み込めた分だけ切り出さないといけません。

編集 削除
ラッキー池田  2010-04-27 16:22:17  No: 38354  IP: 192.*.*.*

tor様アドバイスありがとう御座います。

>>
改行でないなら何なのか、(LabelやShowMessageの目視ではなく)
実際に文字コードを確認したのでしょうか?

いいえ、確認しておりません、というよりも
確認方法がわからない状態です、申し訳ありません。



>>
ReadCountには実際に読み込めたデータサイズが入ってくるのではないですか?
だとしたらBufferを全部足すのではなく、読み込めた分だけ切り出さないといけません。

そうですね、ただ、読み込めた部分という表現は私には正しい文字と文字化けの区別がデーター的にどういう違いがあるのか解らないので方法がわからないです、


お手数ですが、もう少し具体的な方法をお示しいただければ幸いです。

編集 削除
tor  2010-04-27 17:20:24  No: 38355  IP: 192.*.*.*

> 確認方法がわからない状態です、申し訳ありません。
たとえば Ord(HtmlStr[Length(HtmlStr)]) という式で、
HtmlStrの最後の文字のコードが取り出せます。
最低限、この調子で1文字ずつ調べていくということはできます。

しかし、Delphiにはデバッガという強力な機能がついています。
1. HtmlStrを代入している行で、F5を押してブレークポイントを設定
2. F9でプログラムを実行
3. ブレークポイントで実行が止まったら、HtmlStrを右クリックして「インスペクト」または「評価/変更」を選ぶ
(使っているバージョンで多少操作は違うかもしれませんが)このやり方で変数の中身を自在に覗いたり、変更したりできます。

さて本題。
たとえば、ReadCountが10だったら「Bufferに10文字入れといたよ」ということですから、先頭から10文字だけ取り出さなくてはいけません。
今はReadCountを無視してBufferの中身を全部取り出しているから、後ろに余計なゴミが付いているのだと思います。
HtmlStr := HtmlStr + Copy(Buffer, 1, ReadCount);

編集 削除
ラッキー池田  2010-04-27 18:20:06  No: 38356  IP: 192.*.*.*

tor様

ご丁寧にありがとうございます。
ファイルの末尾  以降になにかゴミがついているなんて予想していませんでした、これで解決できました。

しかし、何がくっついていたんでしょうか・・・・・

編集 削除
tor  2010-04-27 19:04:20  No: 38357  IP: 192.*.*.*

> しかし、何がくっついていたんでしょうか・・・・・
せっかくなのでデバッガで追って中身を調べてみると勉強になると思いますよ。
まあ、おそらくBufferに残っていた内容でしょうね。

話を簡単にするためにBufferのサイズを8とし、
また読み込むデータは "Alphabet12" という10文字だとします。

最初のInternetReadFileの呼び出しではBufferに収まる分だけ、つまり"Alphabet"という8文字が読めます。
この時、Bufferの中身は次のようになります。ここまではいいですよね。
> Alphabet

次の読み出しでは、残った2文字が読み込まれます。
InternetReadFileは、読めた分だけBufferに書き込んで「2文字読めたよ」と通知します。
2文字しか書いていないから、残りの6文字分は前の内容が残ったままです。
つまり、Bufferの中身は次のようになっています。
> 12phabet

Bufferをそのまま追加したら "Alphabet12phabet" となってしまいますよね。これが余分なゴミの正体です。

編集 削除
ラッキー池田  2010-04-27 20:35:21  No: 38358  IP: 192.*.*.*

なるほど、大変よくわかりました。

試しに以下のものを入れてみたら初期のソースでも正しく動きました

  //初期化
  Buffer :='';
  HtmlStr := '';

そういうことだったんですね・・・

編集 削除