文字化けを防止するためには??

解決


AS  2014-04-12 02:36:41  No: 46235

こんにちは。
いつもお世話になっております。
よろしくお願いします。

richEditに文字を表示するときに文字化けが結構目につきます。
できれば、これを完全に消したいと思い、ネットを検索しました。
最初に,richEditのFONTの文字セットを確認しました。
次にansiの文字をすべて消しました。

次に、
  StrL: TStringList;
  s: string;
では、StrLもSもAnsistring文字変数になるとの記述を見つけて、
XE2やXE5でもそうなのか、もうすべてUniCodeになっているのではと思って
質問することにしました。

どうなんでしょうか??


igy  2014-04-12 04:23:20  No: 46236

>richEditに文字を表示するときに文字化けが結構目につきます。

文字化けが発生するような手順、または、ソースなどを
ここに挙げてみるのは、いかがですか?


AS  2014-04-12 09:23:06  No: 46237

igyさん、よろしくお願いします。

実は先に質問したソート、これをするのは文字化けの修正した結果を並び替えるためなんです。

StrL: TStringList;

これを使いますので、文字化けの原因を使っているのかと思って、質問してます。

文字変数はすべて、s: string;  で宣言していますし??

どうなんでしょうか??  Unicodeに対応してないのでしょうか??

やっていることは、文字データを作成  並び替えて保存。

もう一度呼び込んで、richeditに表示。

この時に、文字化けが結構目立ちます。

4000行のうち、数十行で出てますね。

昨日は、1行毎に目で見ながら確認修正しましたが、

次にしたら、またいくつも文字化けが見つかるんですよ。

まあ、データ構造が壊れたのを見つけるプログラムを組んでいますから、

今までは、少々の文字化けは許してきましたが、

今回のXE5への移行はプログラムの修正が無いので、取り組んでみようかと思ってます。

ソートしなければ文字化けによるデータ構造の破壊が出ないかどうか、

数日見てみようと思っています。


igy  2014-04-12 17:31:57  No: 46238

問題の切り分けをするために、どの時点でデータが“文字化け”しているのか、
確認してみるのは、いかがですか?


AS  2014-04-12 20:03:35  No: 46239

igyさん、ありがとうございます。

昨夜から、読み込み・保存を4回して、1行データ構造が壊れました。
続いて、読み込み・ソート・保存を1回すると、さらに1行データ構造が壊れました。
さらに、読み込み・ソート・保存を1回すると、さらに1行データ構造が壊れました。

ソートを行うと、文字化けの原因になるようですね。

ソートのprocedureの中でどこが悪いのか、調べてみます。


igy  2014-04-12 20:24:43  No: 46240

>ソートを行うと、文字化けの原因になるようですね。

とのことですが、

>昨夜から、読み込み・保存を4回して、1行データ構造が壊れました。

の記述からは、ソートが行われていない気もしますが・・・

また、

>4回して、1行データ構造が壊れました。

とありますが、“壊れる”条件とかは、ありますか?(特定の文字列が含まれるときのみ・・とか)


AS  2014-04-12 22:10:26  No: 46241

すみません。

その後の計測ではStrL.sort;  は関係ないようです。

計測途中ですが、報告まで。


AS  2014-04-13 01:35:58  No: 46242

下の3つの使用法について計測しました。
同じデータを別に保存しておいて、各計測のたびに初期化しました。

1)StrL.sort;  を使用したもの。
読み込み、ソートして保存、使用、壊れた行数を測るを10回行いました。
3回目に1行壊れて、10回目でも1行だけでした。
ほかのデータと異なったので、読み込み・ソート・保存を10回行って、1回使用。
その後、壊れた行数を測定すると5行でした。

2)第2項目を優先するためにデータを修正した後ソートしてもの
読み込み、データ修正、ソートして保存、使用、壊れた行数を測るを10回行いました。
3回目に1行壊れて、8回目にさらに2行壊れて、10回目にさらに2行壊れて
計5行壊れました。

3)読み込んでまた保存しただけ
読み込み、保存、使用、壊れた行数を測るを10回行いました。
3回目に1行壊れて、8回目にさらに2行壊れて、10回目にさらに2行壊れて
計5行壊れました。

上で壊れた行は順番も含めて、すべて同じでした。

この3つの計測から、ソートそのものは、文字化けには関係ないと思います。
読み込み、保存は上の3つですべて共通ですから、これらのどれかが問題で
あると思います。


AS  2014-04-13 08:49:56  No: 46243

igyさん、
壊れる条件とは特定できませんが、
’・’が壊れているのは目に付きますね。

読み込みは、
  RichEdit1.Lines.LoadfromFile(FileName2);
を使っています。

今使っている保存方法はこれです。

  StrL := TStringList.Create;
  try
    StrL.text:=RichEdit1.lines.text;
    StrL.SaveToFile(FileName2);
  finally
    StrL.Free;
  end;

以前は、
   RichEdit1.Lines.SaveToFile(FileName2);
も使ってみましたが、完全におかしくなりますよね。

文字化けしないsave方法をご存知の方、教えてくださいませ。

このデータが、読み込み・保存で文字化けを起こすかどうかを
調べるプログラムを組んでみようかと思ってます。


igy  2014-04-13 09:41:42  No: 46244

>文字化けしないsave方法をご存知の方、教えてくださいませ。

文字化けを再現できるプログラムを、ここに提示すれば、
どなたかに原因等を特定、または回避方法を教えてもらえるかもしれませんね・・・


Mr.XRAY  2014-04-13 09:58:28  No: 46245

>   RichEdit1.Lines.SaveToFile(FileName2);
>も使ってみましたが、完全におかしくなりますよね。

保存したファイルをテキストエディタ(メモ帳等)で開くと,
下のリンクの 図2 や 図3 のようになると言うことですか ?

もし,そうだとしたら,それは正常ですね.
そうならないと,多くの人が,Delphi を使用している世界中の人が困ります.多分.
つまり,それは「文字化け」ではありません.

http://mrxray.on.coocan.jp/Delphi/plSamples/673_RichEdit_Stream.htm#fig2

jgy さんが何回も書いているように,具体的にテストできるコードがない限り,
誰にも分からないと思いますよ.


AS  2014-04-13 18:34:46  No: 46246

igyさん、Mr.XRAYさん、ありがとうございます。

文字化けを再現できるプログラムは、今までの経過から考えて、

読み込みは、
   RichEdit1.Lines.LoadfromFile(FileName2);

保存方法は、
   StrL := TStringList.Create;
   try
     StrL.text:=RichEdit1.lines.text;
     StrL.SaveToFile(FileName2);
   finally
     StrL.Free;
   end;

これを繰り返すことだと思います。
今、これを実証するためのプログラムを作っています。

はっきり言って保存で文字化けを起こすというのは考えにくいので、
’,’区切りの私のデータ構造が悪いのではとの疑いが??

'A,0001,リンゴ,1000,20000'

ようにしていて、リンゴが文字化けを起こすんですよね。
何か悪いところはありませんか。

Mr,XRAYさん、
RichEdit1.Lines.SaveToFile(FileName2);
は文字化けではないということは理解できました。
わざわざ、ありがとうございました。


AS  2014-04-13 22:10:48  No: 46247

プログラムができました。  

RichEdit1.Lines.LoadfromFile(FileName2);

これで読み込んだら即文字化けが出てます。

1回の読み書きで、文字化け13行
10回で、82行
50回で、384行でした。

RichEdit1.Lines.LoadfromFile(FileName2);
以外のload方法を探します。


igy  2014-04-14 02:10:21  No: 46248

試しに、

A,0001,リンゴ,1000,20000

の行が10万行あるテキストファイルを
RichEditのLines.LoadFromFileで読み込むと、確かに
“リンゴ”の一部がおかしくなりますね・・・


igy  2014-04-14 02:25:06  No: 46249

ちなみに、TRichEditじゃなく、TMemoを使うのでは、だめですか?


AS  2014-04-14 03:32:57  No: 46250

igyさん、ありがとうございました。
私の計測が間違いではないことが確認されて、うれしいです。
Tmemoでは4000行は読み込めなかったのでは??
しかし、10万行というのはすごいですね。

上では、load方法を探すと書きましたが、その方法がわからないので、
新しいloadprocedureを自作して使用したところ、
50回save&loadをしても、文字化けは0になりました。

procedure TForm1.Load(Filename:string);
var
  SS,InBuff:string;
  F:textfile;
  j,i:integer;
begin
  if not FileExists(FileName) then
  begin
    showmessage(FileName+'が見つかりません');
    exit;
  end ;
  AssignFile(F, FileName); Reset(F);
  i:=0;  ss:='';
  repeat
    inc(i); readln(F,InBuff);
    SS:=SS+Inbuff+#$0A;
  until eof(f);
  CloseFile(F);

  RichEdit1.Lines.Clear;
  RichEdit1.Lines.Add(SS);
end;

このプログラムは汎用性がないので、
文字化けを起こさないloadプログラムを紹介してくださいませ。
あるいは、richedit2や3に保存できるように改造できませんか??

どちらかができたら、解決にします。
よろしくお願いします。


igy  2014-04-14 03:46:35  No: 46251

>Tmemoでは4000行は読み込めなかったのでは??

Delphi XE2 のヘルプで、TMemoを見ると、

>Win 9x では、このコントロールで処理できるテキストは 64 KB までに制限されています。

と記載されています。

TMemoのLines.LoadFromFileで5万行以上のファイルを試してみると、問題なく読み込めるようです。
(Delphi XE2, Windows 7)


Mr.XRAY  2014-04-14 05:48:18  No: 46252

>RichEditのLines.LoadFromFileで読み込むと、確かに
>“リンゴ”の一部がおかしくなりますね・・・

igy さん.テストしてみました.
TStringList に一揆に読み込んでから,TRichEdit.Text に代入する方法です.
こちらの方が高速です.
確認したところ,文字化けはないようです.

手順は以下の通りです.
動作確認は,Windows 7 U64(SP1) + Delphi XE, XE2 Pro です.

(1) 新規プロジェクトを作成
(2) フォームに TRichEdit を 1 つ.TButton を 3 つ配置
(3) ボタンクリックのイベント等を作成

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, ComCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    RichEdit1: TRichEdit;
    Button2: TButton;
    Button3: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private 宣言 }
    SaveFilePath : String;
    TestText     : String;
    LinesCnt     : Integer;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//=============================================================================
//  フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  //Clearしてフォントを指定しないと設計時の書式が適用される
  RichEdit1.Lines.Clear;
  RichEdit1.Font.Name := 'MS ゴシック';
  //プレーンテキストのみ扱う
  RichEdit1.PlainText  := True;
  //スクロールバーを表示
  RichEdit1.ScrollBars := ssBoth;

  //ファイル名.念のため絶対パスにしておく
  SaveFilePath := ExpandFileName('000.txt');
  //テスト用文字列
  TestText := 'A,0001,リンゴ,1000,20000';

  //作成する行数
  LinesCnt  := 100000;
end;

//=============================================================================
//  テスト用テキストファイルの作成
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  SWriter : TStreamWriter;
  i       : Integer;
begin
  //保存するファイル
  //そのまま保存するとUTF-8Nになるので,エンコードしてShift-JISで保存
  SWriter := TStreamWriter.Create(SaveFilePath, False, TEncoding.GetEncoding(932));
  try
    for i := 0 to LinesCnt - 1 do begin
      SWriter.WriteLine(TestText);
      Application.ProcessMessages;
    end;
  finally
    SWriter.Close;
    SWriter.Free;
  end;
  Application.MessageBox('作成しました', '情報');
end;

//=============================================================================
//  保存したテキストファイルを読み出して表示
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
  SL : TStringList;
begin
  RichEdit1.Lines.Clear;

  SL := TStringList.Create;
  try
    SL.LoadFromFile(SaveFilePath);
    RichEdit1.Text := SL.Text;
    Application.MessageBox('読み込みました', '情報');
  finally
    FreeAndNil(SL);
  end;
end;

//=============================================================================
//  RichEditのテキストを保存
//=============================================================================
procedure TForm1.Button3Click(Sender: TObject);
begin
  if RichEdit1.Lines.Count > 0 then begin
    //Shift-JISで保存される
    RichEdit1.Lines.SaveToFile(SaveFilePath);
    Application.MessageBox('保存しました', '情報');
  end else begin
    Application.MessageBox('テキストがありせん', '情報');
  end;
end;

end.

元の質問をされた方へ.
こういうのを「テスト可能なコード」と言います.


igy  2014-04-14 07:30:05  No: 46253

>igy さん.テストしてみました.

Mr.XRAYさん。動作確認しました。
こちらでも、文字化けは、起こりませんでした。

ただ、保存のほうで、

>    //Shift-JISで保存される
>    RichEdit1.Lines.SaveToFile(SaveFilePath);

は、UTF16(BOM)で保存されている気がします。
(Delphi XE2, Windows 7)


AS  2014-04-14 08:00:31  No: 46254

igyさん
ありがとうございました。

Mr.XRAYさん  
   RichEdit1.Lines.Clear;
   SL := TStringList.Create;
   try
     SL.LoadFromFile(SaveFilePath);
     RichEdit1.Text := SL.Text;
   finally
     FreeAndNil(SL);
   end;

を、文字化けを調べるプログラムに組み込んで、100回Load&saveを行ってみましたが、
文字化けはありませんでした。
HPのほうにも「文字化けを起こさないLoad方法」として記載をお願いします。
以前は利用させていただきました。
ありがとうございました。


Mr.XRAY  2014-04-14 08:26:26  No: 46255

失礼しました.
提示したコードでは,メモリリークが発生しますね.
修正コードです.

procedure TForm1.Button1Click(Sender: TObject);
var
  SWriter : TStreamWriter;
  Enc     : TEncoding;
  i       : Integer;
begin
  //保存するファイル
  //そのまま保存するとUTF-8Nになるので,エンコードしてShift-JISで保存
  Enc := TEncoding.GetEncoding(932);
  SWriter := TStreamWriter.Create(SaveFilePath, False, Enc);
  try
    for i := 0 to LinesCnt - 1 do begin
      SWriter.WriteLine(TestText);
      Application.ProcessMessages;
    end;
  finally
    SWriter.Close;
    SWriter.Free;
    Enc.Free;
  end;
  Application.MessageBox('作成しました', '情報');
end;


Mr.XRAY  2014-04-15 16:44:01  No: 46256

igyさん,失礼しました.
レスが付いているのに気付きませんでした.

>は、UTF16(BOM)で保存されている気がします。
>(Delphi XE2, Windows 7)

確かに,そういうコードになっていますね.ハハハッ.
適当にエンコードする,というこでご容赦ください.
コメント文は間違いということですね.いつもの誤字脱字の類です m(__)m


AS  2014-04-16 17:51:40  No: 46257

igyさんへ

プログラムの修正が終わった後、richeditのあるところに、
   
    RichEdit1.Lines.Clear;
    SL := TStringList.Create;
    try
      SL.LoadFromFile(SaveFilePath);
      RichEdit1.Text := SL.Text;
    finally
      FreeAndNil(SL);
    end;

をいちいち書かねばならないので、ちょっと不細工なかなと
思い、memoを試すことにしました。
108Kbiteを十分読み込みますし、文字化けを調べるプログラムでも、
100回Load&saveしても、文字化けは起こりませんでしたし、
richeditをすべてmemoに置き換えようかと思ってます。

ありがとうございました。


AS  2014-04-17 18:38:30  No: 46258

とりあえず、メモ帳のようなものをmemoに置き換えました。

で、2842,11KBまでは読み込みますね。

読み込むのに時間はかかりますが。

これの倍を読み込まそうとしたら、時間がかかって読み込めなさそう??

richeditはもういらないですね。


AS  2014-04-17 18:40:42  No: 46259

読み込みました。

時間がかかって実用的ではありませんが。


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

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






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