日本語euc-jp符号化変換——codepage 51932について

4178 ワード

EUC-JPコードは日本語のウェブページ、データベースによく見られる.しかし、GNUのrecodeやiconvを使ったことがあるかもしれませんが、euc-jpで符号化されたファイルが他の符号化フォーマットにうまく変換されず、ローマ数字のような文字にぶつかるとエラーになることがよくあります.これらはすべてeuc-jp規格の拡張に属するため,実際に使用されているがGNUのツールはサポートされていない.
Windowsでは、MultiByteToWideCharとWideCharToMultiByteを使用してeuc-jp符号化されたファイルを変換できます.ここでeuc−jp符号化はcodepage 20932に対応する.ただし、すべての文字セットを上書きすることはできません.全ての拡張文字(NEC選定IBM拡張文字等)を含むeuc-jp符号化はcodepage 51932に対応するが、WindowsのAPIではサポートされていない.IEが使用するMLangのConvertINetStringのような関数だけがcodepage 51932を使用できるそうです.しかし、XP英語版でgccでコンパイルしたプログラムはcp 51932を使用できないことを試したことがあります.
テストコード1:
// gcc -Wall conve.c mlang.dll
#include
#include
#include
#include
#include
#define MAX_BUF 256
extern HRESULT ConvertINetString(LPDWORD, DWORD, DWORD, LPCSTR, LPINT, LPSTR, LPINT);


int main(int argc, char *argv[])
{
    DWORD mode = 0, srcenc, dstenc;
    BYTE src[MAX_BUF], dst[MAX_BUF*2];
    UINT srclen, dstlen;
    FILE *fp, *gp;
    int line = 0;

    srcenc = 65001;
    dstenc = 936;
    if (argc > 1)
        srcenc = atoi(argv[1]);
    if (argc > 2)
        dstenc = atoi(argv[2]);
    printf("From %lu to %lu/n", srcenc, dstenc);

    fp = stdin;
    gp = fopen("log.tmp", "w");
    while (!feof(fp) && fgets(src, MAX_BUF, fp))
    {
        srclen = strlen(src);
        if (srclen > 0 && src[srclen - 1] == '/n')
            --srclen;
        printf("Line %d: ", ++line);
        fprintf(gp, "Line %d: %.*s/n", line, srclen, src);
        fflush(gp);
        switch (ConvertINetString(&mode, srcenc, dstenc, 
                                          src, &srclen, dst, &dstlen))
        {
            case S_OK:
                break;
            case S_FALSE:
                fprintf(stderr, "The specified conversion is not supported on the system./n");
                //exit(1);
                break;
            case E_FAIL:
                fprintf(stderr, "An error occurred./n");
                break;
        }
        printf("%d/n", dstlen);
        printf("%.*s/n", dstlen, dst);
    }

    fclose(gp);

    return 0;
}

テストコード2:
// gcc -Wall test.c -lole32 -luuid
// needs patched mlang-uuid.c to build libuuid
#include
#include
#include
#include
#include
#include
#include
#define MAX_BUF 256

int main(int argc, char *argv[])
{
    IMultiLanguage *p;
    DWORD mode = 0, srcenc, dstenc;
    BYTE src[MAX_BUF], dst[MAX_BUF*2];
    UINT srclen, dstlen;
    FILE *fp;
    int line = 0;

    CoInitialize(NULL);   
    if ( FAILED(CoCreateInstance(&CLSID_CMultiLanguage   ,NULL,
                                 CLSCTX_ALL, &IID_IMultiLanguage2 ,(void**)&p)) )
    {   
        return -1;
    }  

    srcenc = 65001;
    dstenc = 936;
    if (argc > 1)
        srcenc = atoi(argv[1]);
    if (argc > 2)
        dstenc = atoi(argv[2]);
    printf("From %lu to %lu/n", srcenc, dstenc);

    fp = stdin;
    while (!feof(fp) && fgets(src, MAX_BUF, fp))
    {
        srclen = strlen(src);
        if (srclen > 0 && src[srclen - 1] == '/n')
            --srclen;
        printf("Line %d: ", ++line);
        //assert(  p->lpVtbl->ConvertString != NULL);
        switch ( p->lpVtbl->ConvertString(p, &mode, srcenc, dstenc, 
                                          src, &srclen, dst, &dstlen) )
        {
            case S_OK:
                break;
            case S_FALSE:
                fprintf(stderr, "The specified conversion is not supported on the system./n");
                //exit(1);
                break;
            case E_FAIL:
                fprintf(stderr, "An error occurred./n");
                break;
        }
        printf("%d/n", dstlen);
        printf("%.*s/n", dstlen, dst);
    }

    p->lpVtbl->Release(p);
    CoUninitialize();
    return 0;
}

APIの方法ではだめなら、どうすればいいのでしょうか.
解決方法は簡単です.日本人が作ったlibiconvのパッチをかければいいです.アドレス:http://www2d.biglobe.ne.jp/~msyk/software/libiconv-patch.html.その後、完全なeuc−jp符号化としてCP 51932を用いて変換することができる.これはiconvのGBKが不完全で、GB 18030ですべて似ています.