【解決方法】C++ での Unicode ファイルの解析

プログラミングQA

[ad_1]

こんにちは、コードに Unicode サポートを追加するのに本当に問題があります。ASCII コードは完全に機能していますが、中国語と韓国語の文字を入力すると壊れてしまいます。 Web でサンプル コードまたはガイドを検索しようとしましたが、十分な適切な情報がないため、既に作業していて修正を手伝ってくれる人を探しています。 私には単純なタスクがあります
– Unicode (UTF16) テキストファイルを入力
– 行ごとにスキャンしてから、トークンに解析します
– 区切り文字を使用して、必要なトークンをフィルタリングし、残りを無視します
– これらのトークンを構造体のような配列に保存し、それに対していくつかの文字列比較を行います。

私はWindowsプラットフォームとCode::blockエディターをmingwで使用しています
以下のコードの一部を貼り付けています。どんな助けでも大歓迎です。サンプルコードを教えていただければ幸いです。
——————————————–

#include <iostream>
#include <windows.h>
#include <string.h>
#include <algorithm>
#include <cstring>
#include <fstream>
const int MAX_CHARS_PER_LINE = 4072;  
const int MAX_TOKENS_PER_LINE = 1;      
const wchar_t* const DELIMITER = L"\"";

class IntegrityCheck
{
    public:
        std::wstring Profile_Container[5000][4];
        void Profile_PRD_Parser();
};

 void IntegrityCheck::Profile_PRD_Parser()
{

std::wstring skip (L".exe");
std::wstring databoxtemp[1][1];
int a=-1;

// create a file-reading object
wifstream fin.open("profiles.prd");  //open a file
wofstream fout("out.txt");  // this dumps the parsing ouput 

// read each line of the file
while (!fin.eof())
{
    // read an entire line into memory
    wchar_t buf[MAX_CHARS_PER_LINE];

    fin.getline(buf, MAX_CHARS_PER_LINE);

    // parse the line into blank-delimited tokens
    int n = 0; // a for-loop index

    // array to store memory addresses of the tokens in buf
    const wchar_t* token[MAX_TOKENS_PER_LINE] = {}; // initialize to 0

    // parse the line
    token[0] = wcstok(buf, DELIMITER); // first token

    if (token[0]) // zero if line is blank
    {

        for (n = 0; n < MAX_TOKENS_PER_LINE; n++)   // setting n=0 as we want to ignore the first token
        {
            token[n] = wcstok(0, DELIMITER); // subsequent tokens

            if (!token[n]) break; // no more tokens

            std::wstring str2 =token[n];

            std::size_t found = str2.find(str);  //substring comparison

            if (found!=std::string::npos)   // if its exe then it writes in Dxout for same app name on new line
            {
                a++;
                Profile_Container[a][0]=token[n];
                std::transform(Profile_Container[a][2].begin(), Profile_Container[a][2].end(), Profile_Container[a][2].begin(), ::tolower);  //convert all data to lower 

                fout<<Profile_Container[a][0]<<"\t"<<Profile_Container[a][1]<<"\t"<<Profile_Container[a][2]<<"\n"; //write to file
            }

        }
    }

}

fout.close();
fin.close();
}

int main()
{
IntegrityCheck p1;
p1.Profile_PRD_Parser();
}     

解決策 1

デバッガーとコード サンプル ファイルでコードを実行する必要があります。

私はこの場所であなたのコードを変更します:

C#
// read an entire line into memory
    wchar_t buf[MAX_CHARS_PER_LINE] = {0};
C#
 //first we done before
for (n = 1; n < MAX_TOKENS_PER_LINE; n++) 

解決策 2

多くの場合、utf16 への切り替えは適切ではありません。 utf8 を使用することは、多くの理由でより良い選択であることがよくあります。 これは一部の東洋言語の場合に少し多くのメモリを消費する可能性がある表現ですが、他のプラットフォーム (UNIX など) への移植や、通常の char ポインターを使用するレガシー コード (元のコードなど) との統合を検討する場合、通常は utf8 の方がはるかに望ましいです。 )。 utf8 を使用すると、元のコードが魅力的に機能します。 多くの場合、元の ascii パーサーとテキスト プロセッサは utf8 データを問題なく処理します。

すべてのテキスト処理ロジックを移植する代わりに、すべてのコードが utf8 で動作することを決定し、他のすべてのエンコーディング用にインポーター (外部エンコーディングから utf8 へのコンバーター) とエクスポーター (utf8 から外部エンコーディングへのコンバーター) を作成します。 あなたの場合、これは、読み込み用の utf16 から utf8 へのコンバーターと、保存用の utf8 から utf16 へのコンバーターを意味します。 ファイルを utf8 形式で正しく取得することをお勧めします。その後、変換する必要はありません。 utf ファイルは *MAY* で始まることに注意してください 部品表[^] ただし、これは必須ではありません。一部のスマート テキスト エディター (Notepad++ など) は、BOM がなくてもエンコーディングを検出できることがよくありますが、ファイルをバイナリで読み取る場合は、ローダー コードで BOM を処理 (検出/チェックしてからスキップ) する必要がある場合があります。モード。

解決策 3

Code::Blocks (非公開バージョン) を使用しているため、
Microsoft Windows (非公開バージョン) を使用しているため、および
おそらくGCC(非公開バージョン)でMinGW(非公開バージョン)を使用しているため、
これで問題ありません。次に、作業している Unicode を確認するのにおそらく次の情報が役立つでしょう。

あなたが言っていないことがたくさんあるので、私は私の答えを拡大します。 これらのことをすでに知っているなら、それは素晴らしいことです。

あなたの例では見られなかったので、これをコードの先頭に追加することをお勧めします。

#define _UNICODE
#UNICODE を定義

utf-16 は (ある程度) 機能するため、utf-8 に切り替える必要はありません。 Windowsオペレーティングシステムが独自の処理でutf-16を使用している場合でも、utf-16は非常に制限されているというのが私の意見です。 Windows には、オペレーティング システムのロード時にロードできるコード ページが多数あり、これらは utf-16 の制限を拡張するのに役立つようですが、それでも私は utf-8 を好みます。 これが utf-16 の使用を選択した場合はそのまま使用できますが、一部の高度な Unicode 記号は正しく表示されない可能性があります。

さらに細かい調整をしても構わない場合: (すでに知っているかもしれないいくつかの提案です。)

Code::Blocks のコマンド ライン インターフェイス設定を使用しているようです。 以下を参照してください。

utf-16 のままにしたい場合は、Settings / Editor / Encoding settings / UTF-8 (それでよろしい場合) または UTF-16LE (Windows の場合) (または Macintosh の場合 BE) をお勧めします。

また、プロジェクト / プロパティ / ビルド ターゲット / デバッグ (およびリリースも) / プラットフォーム / すべて

また、プロジェクト / プロパティ / ビルド ターゲット / デバッグ (およびリリースも) / タイプ / GUI アプリケーション (グラフィカル ユーザー インターフェイスでプログラムを作成する場合) またはコンソール アプリケーション (コンソール インターフェイスが必要な場合)

GUI アプリケーションからグラフィカル出力と CLI 出力の両方を生成できるため、CLI ではなく GUI を使用したことに基づいてアドバイスを提供します。

__________

そして、これは非常に大きなことです。コードに Unicode の読み取りと書き込みが含まれている場合、Microsoft は C++11 や C++17 でさえうまく機能しません。 そのために、WriteFile() などを使用しています。

尋ねていただきありがとうございます。

よくあることですが、この回答が当てはまる場合は、同意をクリックして星で評価してください。

[ad_2]

コメント

タイトルとURLをコピーしました