dポイントプレゼントキャンペーン実施中!

Message ID を書き溜めたファイルを作っています。

ヤフーメールの場合は、Message ID を比べてダウンロードするか否かを決定しています。
でも、比較が遅いように感じます。

どんなアルゴリズムがお勧めでしょうか?

よろしくお願いいたします。


いまは、次のようにして調べています。

int CSQMailBoxTreeView::isloaded(char* gszT)
{
char lbuf[256];

if( (popdatfp = fopen(".\\mailbox\\popdata.dat","r+")) == NULL ){
popdatfp = fopen(".\\mailbox\\popdata.dat","w+");
}
while(fgets(lbuf,256, popdatfp) != NULL ){
if(strlen(lbuf) == 0){
break;
}
if(strstr(lbuf, gszT) != NULL ){
fclose(popdatfp);
return 1;
}
}
fputs(gszT, popdatfp);
fputs("\r\n", popdatfp);
fclose(popdatfp);
return 0;
}

A 回答 (2件)

質問文に書かれている方法だと1つ調べる毎に、


fopen() 1回
fclose() 1回
fgets() 最悪のケースでpopdata.datに登録されてるメッセージIDの件数分+1回
を呼び出すことになります。
仮にpopdata.datが空の状態で10件の重複のないメッセージIDを調べると
fopen() 10回
fclose() 10回
fgets() 55回(1~10の合計)
となります。
なので調べたメッセージIDが増えれば増えるほど急激に遅くなるのは当然かと。

早くするには、
・#1の方のいわれてるようにメモリ上で検索する
・データベース(dbmとか)を使用する
・メッセージIDをファイル名としてファイルを作りその有無で調べる(あまり早くならないかも)
などがあるかと思います。

ところで
>fputs("\r\n", popdatfp);
の \r は必要ですか?
Windowsだと"\r\n"はファイル上では \r\r\n になると思いますが。

この回答への補足

fputs("\r\n", popdatfp);
の \r は必要ですか?
Windowsだと"\r\n"はファイル上では \r\r\n になると思いますが。

そのとおりです。

あまりにも遅いので、データベースの sqlite を使うことにしました。


int CSQMailBoxTreeView::isloaded(char* gszT)
{
int rc = 0;
CSQMailBoxDoc* pDoc = GetDocument();

rc = pDoc->GetNumbyMessID(gszT);

if( rc != 0){
return 1;
}else{
pDoc->AddNewMessID(gszT);
return 0;
}
}

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

補足日時:2013/08/20 06:39
    • good
    • 0

オープンソースのメールソフトのソースでも見た方がいいんじゃないですかねぇ…とか思いますが。



>int CSQMailBoxTreeView::isloaded(char* gszT)

引数で渡されるのがサーバから取得したMessage-IDで、
ファイルから読み込んでいるのが受信済みのMessage-IDが列挙されているんですか?
『関数呼び出される度にそのファイルの内容は全く違うモノに変わる』のなら都度都度読み込むしかないでしょう。
変更されない(あるいは前回の分が追加されるだけ)なら、いちいちファイルから読み込まないでメモリ上に読み込んでおいたらどうですか?
# って追加されるパターンでしたな。
クラスのメンバにポインタ追加して、適当なタイミング(コンストラクタとか)でメモリに読み込んでおいて、追加する時はメモリ上で追加(realloc()なりで領域拡張すればいいでしょう)、適当なタイミング(デストラクタか追加された時)でファイルに書き出す…って感じですかね。
改行込みでまるっとメモリに読み込んでおいてstrstr()で検索する。という方法だって取れるでしょう。
ファイルの先頭と最後に空行を1行入れる。というのを許容するなら、引数で受け取った文字列の前後に改行追加した状態でstrstr()してもいいでしょうし。

ちなみに私はリスト構造で保持してますね。
# こういう検索する場合はリンク構造はイマイチ不利ですけど…まぁ、メモリ上に全部置いているんで。
# 大量のメールで試したコトは無いですしねぇ。(gmailを直近30日で読み込む…って時には結構時間掛かってましたかねぇ…。SSLが重いのかどうかまでは確認していませんけど)
# そっち方面で遅いって使用者からのレポート来たコトもない…ですね。(使用者何人居るのか不明ですけど)

この回答への補足

ありがとうございます。

いまは、ヤフーメールで883個のメールが溜まっています。

現在、620個くらい取り出しました。

補足日時:2013/08/19 14:38
    • good
    • 0
この回答へのお礼

ファイルの中身がソートされていれば、
速くできますね。

ランダムアクセスが出来ればよさそうですね。

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

お礼日時:2013/08/19 14:54

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!