Entries

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

fgetsかfgetwsか

タグ: VS2005

VC8でShift JIS(マルチバイト文字列)のファイルをUnicode(ワイド文字列)に変換しながら読み込む方法として、

  • fgetws()でUnicodeに変換しながら読む
  • fgets()で読んでMultiByteToWideChar()でUnicodeに変換する

のどちらが速いか。

試しに、手元にあった29207行946459バイトのMS-IME用辞書ファイル(Shift JISのテキストファイル)の読み込み速度を、Pentium 4 3.6GHzのWindows XP PCで比較してみた。

#include <windows.h>
#include <stdio.h>
#include <locale.h>
#include <iostream>

void test()
{
    ::setlocale(LC_ALL, "japanese");

    // MS-IME用辞書ファイルを開く    
    FILE* fp = ::fopen("msime.txt", "rt");
    if (! fp)
    {
        std::cerr << "ひらけない(´・ω・`)" << std::endl;
        return;
    }
    
    DWORD start;
    int line;
    // 交互に5回試す
    for (int i = 0; i < 5; i++)
    {
        wchar_t wbuff[256] = { 0 };
        const size_t wbufflen = sizeof(wbuff) / sizeof(*wbuff);
    
        // fgetws()でUnicodeに変換しながら読む
        ::fseek(fp, 0, SEEK_SET);
        start = ::GetTickCount();
        for (line = 0; ::fgetws(wbuff, wbufflen, fp); line++)
        {
            // 1行254文字以下(改行コード混み)を想定
            if (wbuff[wbufflen - 2] != 0)
            {
                std::cerr << "ながい('・ω・`)" << std::endl;
                break;
            }
        }
        std::cout << "fgetws " << line << "lines " << ::GetTickCount() - start << "ms" << std::endl;
    
        // fgets()で読んでMultiByteToWideChar()でUnicodeに変換する
        ::fseek(fp, 0, SEEK_SET);
        start = ::GetTickCount();
        char buff[wbufflen * 2] = { 0 };
        const size_t bufflen = sizeof(buff) / sizeof(*buff);
        for (line = 0; ::fgets(buff, bufflen, fp); line++)
        {
            // 1行510バイト以下(改行コード混み)を想定
            if (buff[bufflen - 2] != 0)
            {
                std::cerr << "ながい('・ω・`)" << std::endl;
                break;
            }
    
            // CP932で最大510バイトをUnicode最大255文字にマップ
            if (::MultiByteToWideChar(932, MB_PRECOMPOSED, buff, -1, wbuff, wbufflen) == 0)
            {
                std::cerr << "おかしい('・ω・`)" << std::endl;
                break;
            }
        }
        std::cout << "fgets  " << line << "lines " << ::GetTickCount() - start << "ms" << std::endl;
    }
    
    ::fclose(fp);
}

void main()
{
    test();
}
fgetws 29207lines 125ms
fgets  29207lines 15ms
fgetws 29207lines 94ms
fgets  29207lines 16ms
fgetws 29207lines 93ms
fgets  29207lines 16ms
fgetws 29207lines 94ms
fgets  29207lines 15ms
fgetws 29207lines 78ms
fgets  29207lines 16ms

差はおよそ6倍。
fgetws()は「マルチバイト文字列用のバッファを用意する必要がない」とか「マルチバイト文字の泣き別れを気にしなくて済む」という点で楽をできるが、その分コストは高めである。

Appendix

記事リスト

2010年07月の記事

タグ

Blog内検索

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。