こんにちは。
いつもお世話になっております。
よろしくお願いします。
richEditに文字を表示するときに文字化けが結構目につきます。
できれば、これを完全に消したいと思い、ネットを検索しました。
最初に,richEditのFONTの文字セットを確認しました。
次にansiの文字をすべて消しました。
次に、
StrL: TStringList;
s: string;
では、StrLもSもAnsistring文字変数になるとの記述を見つけて、
XE2やXE5でもそうなのか、もうすべてUniCodeになっているのではと思って
質問することにしました。
どうなんでしょうか??
>richEditに文字を表示するときに文字化けが結構目につきます。
文字化けが発生するような手順、または、ソースなどを
ここに挙げてみるのは、いかがですか?
igyさん、よろしくお願いします。
実は先に質問したソート、これをするのは文字化けの修正した結果を並び替えるためなんです。
StrL: TStringList;
これを使いますので、文字化けの原因を使っているのかと思って、質問してます。
文字変数はすべて、s: string; で宣言していますし??
どうなんでしょうか?? Unicodeに対応してないのでしょうか??
やっていることは、文字データを作成 並び替えて保存。
もう一度呼び込んで、richeditに表示。
この時に、文字化けが結構目立ちます。
4000行のうち、数十行で出てますね。
昨日は、1行毎に目で見ながら確認修正しましたが、
次にしたら、またいくつも文字化けが見つかるんですよ。
まあ、データ構造が壊れたのを見つけるプログラムを組んでいますから、
今までは、少々の文字化けは許してきましたが、
今回のXE5への移行はプログラムの修正が無いので、取り組んでみようかと思ってます。
ソートしなければ文字化けによるデータ構造の破壊が出ないかどうか、
数日見てみようと思っています。
問題の切り分けをするために、どの時点でデータが“文字化け”しているのか、
確認してみるのは、いかがですか?
igyさん、ありがとうございます。
昨夜から、読み込み・保存を4回して、1行データ構造が壊れました。
続いて、読み込み・ソート・保存を1回すると、さらに1行データ構造が壊れました。
さらに、読み込み・ソート・保存を1回すると、さらに1行データ構造が壊れました。
ソートを行うと、文字化けの原因になるようですね。
ソートのprocedureの中でどこが悪いのか、調べてみます。
>ソートを行うと、文字化けの原因になるようですね。
とのことですが、
>昨夜から、読み込み・保存を4回して、1行データ構造が壊れました。
の記述からは、ソートが行われていない気もしますが・・・
また、
>4回して、1行データ構造が壊れました。
とありますが、“壊れる”条件とかは、ありますか?(特定の文字列が含まれるときのみ・・とか)
すみません。
その後の計測ではStrL.sort; は関係ないようです。
計測途中ですが、報告まで。
下の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つですべて共通ですから、これらのどれかが問題で
あると思います。
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方法をご存知の方、教えてくださいませ。
このデータが、読み込み・保存で文字化けを起こすかどうかを
調べるプログラムを組んでみようかと思ってます。
>文字化けしないsave方法をご存知の方、教えてくださいませ。
文字化けを再現できるプログラムを、ここに提示すれば、
どなたかに原因等を特定、または回避方法を教えてもらえるかもしれませんね・・・
> RichEdit1.Lines.SaveToFile(FileName2);
>も使ってみましたが、完全におかしくなりますよね。
保存したファイルをテキストエディタ(メモ帳等)で開くと,
下のリンクの 図2 や 図3 のようになると言うことですか ?
もし,そうだとしたら,それは正常ですね.
そうならないと,多くの人が,Delphi を使用している世界中の人が困ります.多分.
つまり,それは「文字化け」ではありません.
http://mrxray.on.coocan.jp/Delphi/plSamples/673_RichEdit_Stream.htm#fig2
jgy さんが何回も書いているように,具体的にテストできるコードがない限り,
誰にも分からないと思いますよ.
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);
は文字化けではないということは理解できました。
わざわざ、ありがとうございました。
プログラムができました。
RichEdit1.Lines.LoadfromFile(FileName2);
これで読み込んだら即文字化けが出てます。
1回の読み書きで、文字化け13行
10回で、82行
50回で、384行でした。
RichEdit1.Lines.LoadfromFile(FileName2);
以外のload方法を探します。
試しに、
A,0001,リンゴ,1000,20000
の行が10万行あるテキストファイルを
RichEditのLines.LoadFromFileで読み込むと、確かに
“リンゴ”の一部がおかしくなりますね・・・
ちなみに、TRichEditじゃなく、TMemoを使うのでは、だめですか?
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に保存できるように改造できませんか??
どちらかができたら、解決にします。
よろしくお願いします。
>Tmemoでは4000行は読み込めなかったのでは??
Delphi XE2 のヘルプで、TMemoを見ると、
>Win 9x では、このコントロールで処理できるテキストは 64 KB までに制限されています。
と記載されています。
TMemoのLines.LoadFromFileで5万行以上のファイルを試してみると、問題なく読み込めるようです。
(Delphi XE2, Windows 7)
>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 さん.テストしてみました.
Mr.XRAYさん。動作確認しました。
こちらでも、文字化けは、起こりませんでした。
ただ、保存のほうで、
> //Shift-JISで保存される
> RichEdit1.Lines.SaveToFile(SaveFilePath);
は、UTF16(BOM)で保存されている気がします。
(Delphi XE2, Windows 7)
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方法」として記載をお願いします。
以前は利用させていただきました。
ありがとうございました。
失礼しました.
提示したコードでは,メモリリークが発生しますね.
修正コードです.
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;
igyさん,失礼しました.
レスが付いているのに気付きませんでした.
>は、UTF16(BOM)で保存されている気がします。
>(Delphi XE2, Windows 7)
確かに,そういうコードになっていますね.ハハハッ.
適当にエンコードする,というこでご容赦ください.
コメント文は間違いということですね.いつもの誤字脱字の類です m(__)m
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に置き換えようかと思ってます。
ありがとうございました。
とりあえず、メモ帳のようなものをmemoに置き換えました。
で、2842,11KBまでは読み込みますね。
読み込むのに時間はかかりますが。
これの倍を読み込まそうとしたら、時間がかかって読み込めなさそう??
richeditはもういらないですね。
読み込みました。
時間がかかって実用的ではありませんが。
ツイート | ![]() |