Windows Formsのお話です。
WPFでも同じ現象が発生するみたいですが、今回はWindows Formsのサンプルプログラムを交えてご紹介いたします。
ファイルを StreamReader で読み出し、内容を TextBox コントロールの Text プロパティに設定しています。
これで正常に内容をすべて表示できる場合もあれば、表示できない場合も…。
図1、図2 は、同じファイルをそれぞれ Windows 標準のテキストエディタアプリケーション「メモ帳」(notepad.exe) と先程のコードを使用したサンプルプログラムで開いた結果です。
notepad.exe では正常にファイルの内容をすべて表示することができています。しかしサンプルプログラムでは、途中で内容が切れてしまっています。
変な内容のファイルとは、ファイルの途中に終端文字が含まれているファイルです。
終端文字
終端文字とは、バイナリで言うところの0番の文字です。
古くから、C言語などで可変長の文字列バッファの終点位置をデータ受け取り側で知るためなどの目的で利用されておりました。
ちなみにファイルもC#のプログラムから吐き出したのですが、その時のコードはこんな感じ。
System.IO.BinaryWriter クラスを利用しております。
追記
本来、bw.Write(0)では、int型として0が書き込まれてしまいます。
本当は、bw.Write((byte)0) という形で、byte型にキャストするべきなのですが、バイト型で0を1バイトだけ書き込むとnotepad.exeで文字コード判定が壊れてしまうため、意図的にbyte型へのキャストは省略しました。
byte型で書き込みを行いたい場合は、
bw.Write((byte)0)
が正しい形です。
紛らわしい表現となっておりますことお詫び申し上げます。
大体の場合、バイナリファイルなのではないでしょうか。
なぜ、notepad.exeでは正常に開くことができたのでしょうか。
先程のファイルをまずバイナリエディタで開いてみましょう。
終端文字が含まれていることがわかります。
次にこのファイルを notepad.exe で開いてみます。
そして上書き保存…。
そのまま再びバイナリエディタで開いてみましょう。
終端文字だった箇所が空白文字を示す 20 へ置き換えられていることがわかります。
どうやら notepad.exe では、ファイルをテキストボックスに読み出す前に終端文字を空白文字へ置換しているようですね。
notepad.exe でバイナリファイルを開いて上書き保存すればもちろんそのファイルは壊れてしまいます。
それもこういった開いたときの内部的な置換処理があったからなのでしょうね。
終端文字が含まれているファイルをテキストボックスに読み出すためには、終端文字を空白文字などの別の文字へ置換する必要があります。
しかしながら、もちろんそうすればファイルは壊れてしまいます。
ここまで書いておいて変な話ですけど、まず前提として、そういう変なファイルをテキストボックスで扱うのは極力避けましょう…。
WPFでも同じ現象が発生するみたいですが、今回はWindows Formsのサンプルプログラムを交えてご紹介いたします。
テキストボックスの内容が途中で切れる
テキストエディタ機能のあるアプリケーションを作ろうとしているとき、ファイルの内容が最後までテキストボックスに表示されないという現象が発生しました。var sr = new StreamReader(path);
this.mainTextBox.Text = sr.ReadToEnd();
sr.Close();
ファイルを StreamReader で読み出し、内容を TextBox コントロールの Text プロパティに設定しています。
これで正常に内容をすべて表示できる場合もあれば、表示できない場合も…。
図1 notepad.exe で開いた結果
図2 サンプルプログラムで開いた結果
図1、図2 は、同じファイルをそれぞれ Windows 標準のテキストエディタアプリケーション「メモ帳」(notepad.exe) と先程のコードを使用したサンプルプログラムで開いた結果です。
notepad.exe では正常にファイルの内容をすべて表示することができています。しかしサンプルプログラムでは、途中で内容が切れてしまっています。
途中に終端文字を含むファイル
先程の 図1、図2 は、私が意図的に作成した変な内容のファイルを開いた結果でした。変な内容のファイルとは、ファイルの途中に終端文字が含まれているファイルです。
終端文字
終端文字とは、バイナリで言うところの0番の文字です。
古くから、C言語などで可変長の文字列バッファの終点位置をデータ受け取り側で知るためなどの目的で利用されておりました。
ちなみにファイルもC#のプログラムから吐き出したのですが、その時のコードはこんな感じ。
図3 終端文字を途中に含むファイルの出力
System.IO.BinaryWriter クラスを利用しております。
追記
本来、bw.Write(0)では、int型として0が書き込まれてしまいます。
本当は、bw.Write((byte)0) という形で、byte型にキャストするべきなのですが、バイト型で0を1バイトだけ書き込むとnotepad.exeで文字コード判定が壊れてしまうため、意図的にbyte型へのキャストは省略しました。
byte型で書き込みを行いたい場合は、
bw.Write((byte)0)
が正しい形です。
紛らわしい表現となっておりますことお詫び申し上げます。
notepad.exeではどうしているのか
そもそも、終端文字が途中に含まれるファイルというのはかなり特殊です。大体の場合、バイナリファイルなのではないでしょうか。
なぜ、notepad.exeでは正常に開くことができたのでしょうか。
先程のファイルをまずバイナリエディタで開いてみましょう。
図4 バイナリエディタ
終端文字が含まれていることがわかります。
次にこのファイルを notepad.exe で開いてみます。
そして上書き保存…。
そのまま再びバイナリエディタで開いてみましょう。
図5 notepad.exe で上書き保存した結果
終端文字だった箇所が空白文字を示す 20 へ置き換えられていることがわかります。
どうやら notepad.exe では、ファイルをテキストボックスに読み出す前に終端文字を空白文字へ置換しているようですね。
notepad.exe でバイナリファイルを開いて上書き保存すればもちろんそのファイルは壊れてしまいます。
それもこういった開いたときの内部的な置換処理があったからなのでしょうね。
まとめ
ファイルの内容をテキストボックスに読み出す過程で途中で切れてしまう原因の1つとして、「ファイルの途中に終端文字が含まれている」ということがあるようです。終端文字が含まれているファイルをテキストボックスに読み出すためには、終端文字を空白文字などの別の文字へ置換する必要があります。
しかしながら、もちろんそうすればファイルは壊れてしまいます。
ここまで書いておいて変な話ですけど、まず前提として、そういう変なファイルをテキストボックスで扱うのは極力避けましょう…。
コメント