wxWidgetsでファイル処理を行うクラスは多いためどれを使えばよいか迷うところです。よく使いそうなクラス3つを例に上げます。
wxFile, wxFileInputStream
RAWデバイスを扱う用途のクラスで、システムコール系APIを内部で呼ぶ(例:open,read,write)。
そのため単にファイルを処理したいだけだとバッファリングしないためパフォーマンスは若干悪い。
wxFFile, wxFFileInputStream
C言語のstdioライブラリを内部で使用する(fopen,fwrite,fread)。それによりバッファリングされるため、処理対象がファイルならwxFileを使うよりこちらを使用する方がパフォーマンスがよい。
wxTextInputStream
テキスト処理に特化したストリーム系クラス。wxWidgetsのファイル処理クラスで行単位で処理できるReadLile()関数をもつのはこのクラスのみ。
実際のファイルのopenやread処理はwxFFile経由で行うため、コンストラクタにwxFFileを要求するオーバーライドがある。(もうひとつのコンストラクタはファイルパスを引数とし、コンストラクタ内でwxFFileインスタンスを生成しています)
ファイル処理ではバイナリファイルとして処理したい場合はwxFFileクラス、テキストと処理したい場合はwxFFileを生成しその後wxTextInputStreamクラスを生成して処理するとよいでしょう。
私としてはwxFileとwxFFileの違いがクラス名から分からなかったので名前つけが悪いような気がします。(Buffer何々とか名前のクラスもあり、余計に分かりにくい感じがします。)
以下のサンプル中でwxLogNullクラスのインスタンスを生成していますが、これはwxWidgetsのクラス内でエラーや警告が発生したとき(例:ファイルがなくてファイルオープンに失敗)にコマンドラインならstderrに、GUIプログラムならメッセージボックスを出してくれるため(怒)、それの発生をスキップさせるために必要です。(Loggingクラスについては後日紹介しようと考えています。)
class MyApp : public wxApp
{
public:
virtual bool OnInit();
virtual int OnExit();
// システムコールを用いた処理をします。
// 例) open, read, write, ...
// そのため行単位の処理はAPIとして持ちません。
void TestwxFile(const wxString &path);
// C言語のstdioライブラリを用いて処理します。
// 例) fopen, fread, fwrite
void TestwxFFile(const wxString &path);
// wxFFileに行単位で処理するReadLine()を追加したものです。
void TestwxTextInputStream(const wxString &path);
};
IMPLEMENT_APP(MyApp)
bool MyApp::OnInit()
{
wxString path = wxT("in.txt");
printf("start wxFile\ns");
TestwxFile(path);
printf("\n");
printf("start wxFFile\n");
TestwxFFile(path);
printf("\n");
printf("start wxTextInputStream\n");
TestwxTextInputStream(path);
printf("\n");
return false;
}
int MyApp::OnExit()
{
return true;
}
/*************************************************
* wxFileクラスを用いたファイルIO.
*************************************************/
void MyApp::TestwxFile(const wxString &path)
{
wxFile wxf;
wxLogNull lognull;
bool b = wxf.Open(path.c_str(), wxFile::read);
if(false == b){
printf("error open file\n");
return;
}
else{
printf("success open file\n");
}
wxByte buffer[8192];
size_t len = 0;
for(;;){
len = wxf.Read(buffer, sizeof(buffer));
if((size_t)wxInvalidOffset == len){
printf("error Read()\n");
break;
}
else if(0 == len){
printf("success read\n");
break;
}
}
wxf.Close();
}
/*************************************************
* wxFFileクラスを用いたファイルIO.
*************************************************/
void MyApp::TestwxFFile(const wxString &path)
{
bool b;
wxByte buffer[8192];
size_t len = 0;
wxFFile wxf;
wxLogNull lognull;
// バイナリとして処理します。
b = wxf.Open(path, wxT("rb"));
if(false == b){
printf("error open file\n");
return;
}
else{
printf("success open file\n");
}
for(;;){
len = wxf.Read(buffer, sizeof(buffer));
if((size_t)wxInvalidOffset == len){
printf("error Read()\n");
break;
}
else if(0 == len){
printf("success read\n");
break;
}
}
wxf.Close();
}
/*************************************************
* wxTextInputStream クラスを用いたファイルIO.
* 行単位で処理できるクラスです。
*************************************************/
void MyApp::TestwxTextInputStream(const wxString &path)
{
wxFFile wxf;
wxFFileInputStream fs(wxf);
wxLogNull lognull;
if(false == wxf.Open(path.c_str(), wxT("r"))){
printf("error open file\n");
return;
}
else{
printf("success open file\n");
wxTextInputStream textstream( fs );
wxString line;
while(!fs.Eof()){
line = textstream.ReadLine();
#if 1 == wxUSE_UNICODE
printf("unicode %s\n", (const char*)line.utf8_str());
#else
printf("ansi %s\n", line.c_str());
#endif
}
printf("success read file\n");
}
wxf.Close();
}