Как использовать ICU BreakIterator с текстовым файлом Unicode в C ++ - PullRequest
4 голосов
/ 10 февраля 2012

У меня проблемы с использованием ICI BreakIterator для всего кхмерского (камбоджийского) текстового файла UTF-8, чтобы разбить слова на разрывы строк (кхмерский не имеет пробелов между словами, такими как тайский).

Я использовал предоставленный мне образец и изменил его для чтения текстового файла построчно, но проблема в том, что если в строке есть только одно слово, BreakIterator не работает должным образом, так как он настроен на попытаться найти как минимум 3 слова подряд (это необходимо для кхмеров, а без него BreakIterator не так точен).

Может кто-нибудь помочь мне понять, как преодолеть эту проблему? Я думал, что проще всего было бы прочитать весь текстовый файл в буфер, но я не могу заставить его работать должным образом.

Вот весь код, который у меня сейчас есть, который разбивает слова из текстового файла построчно:

/*
Written by George Rhoten, and SBBIC to test how word segmentation works.
Code inspired by the break ICU sample.

Here is an example to run this code in Ubuntu.

./a.out input.txt output.txt

Encode input.txt as UTF-8.
The output text is UTF-8.
*/

#include <string>
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <unicode/brkiter.h>
#include <unicode/ucnv.h>
#include <stdlib.h>

#define ZW_SPACE "\xE2\x80\x8B"

void printUnicodeString(const UnicodeString &s) {
    int32_t len = s.length() * U8_MAX_LENGTH + 1;
    char *charBuf = new char[len];
    len = s.extract(0, s.length(), charBuf, len, NULL);
    charBuf[len] = 0;
    printf("%s", charBuf);
    delete charBuf;
}

int main(int argc, char **argv) {   


    //Please provide an input file name as well as an output file name (ex. ./a.out input.txt output.txt)

    //Cannot find the input file you specified ("$input"). Please provide an input file name as well as an output file name (ex. ./a.out input.txt output.txt)

    //Cannot write to output file.  Please check folder permissions.

    std::ifstream input(argv[1]);
    //std::ifstream input("read.txt");
    std::string line;
    std::ofstream o(argv[2]);    
    //std::ofstream o("output.txt");


    //If input file cannot be found ERROR
    if (!input) {
        std::cout<<"Cannot find the input file you specified ("<<argv[1]<<").\nPlease provide an input file name as well as an output file name\n(example: ./a.out input.txt output.txt)"<<std::endl;
        goto stop;  
    }
    //If output file cannot be created ERROR
    if (!o) {
        std::cout<<"Cannot write to output file ("<<argv[2]<<").\nPlease check folder permissions."<<std::endl;
        goto stop;  

    }
    //If no input file is given on command line ERROR
    if(argv[1]==0) {
        std::cout<<"Please provide an input file name as well as an output file name\n(example: ./a.out input.txt output.txt)"<<std::endl;
        goto stop;
    }
    //If no output file is given on command line ERROR
    if(argv[2]==0) {
        std::cout<<"Please provide output file name as well as an input file name\n(example: ./a.out input.txt output.txt)"<<std::endl;
        goto stop;
    }


    while(std::getline(input,line)) {


//Convert standard string to icu UnicodeString

    UnicodeString Nathan = UnicodeString::fromUTF8(StringPiece(line.c_str()));


/* Creating and using text boundaries */
    ucnv_setDefaultName("UTF-8");
    UnicodeString stringToExamine(Nathan);
    if (argc > 1) {
        // Override the default charset.
        stringToExamine = UnicodeString(Nathan);
        if (stringToExamine.charAt(0) == 0xFEFF) {
            // Remove the BOM
            stringToExamine = UnicodeString(stringToExamine, 1);
        }
    }
    //printUnicodeString(stringToExamine);
    //puts("");

    //print each sentence in forward and reverse order
    UErrorCode status = U_ZERO_ERROR;
    BreakIterator* boundary = BreakIterator::createLineInstance(NULL, status);
    if (U_FAILURE(status)) {
        printf("Failed to create sentence break iterator. status = %s", 
            u_errorName(status));
        exit(1);
    }

    //print each word in order
    boundary->setText(stringToExamine);
    int32_t start = boundary->first();
    int32_t end = boundary->next();
    while (end != BreakIterator::DONE) {
        if (start != 0) {
            printf(ZW_SPACE);

         //output ZWSpace to output file(output.txt)
            o << ZW_SPACE;


            //filestr<<ZW_SPACE;
            //filestr.close();



        }
        //Set variable NathanOut to current word and print to console
        UnicodeString NathanOut = UnicodeString(stringToExamine, start, end-start);
        printUnicodeString(NathanOut);



        //Convert UnicodeString to normal string
            std::string cs;
            NathanOut.toUTF8String(cs);
     //Output the string to file(output.txt)
            o << cs;


            //print output to console
            printUnicodeString(NathanOut);


        start = end;
        end = boundary->next();
    }

    delete boundary;



    }//end of while

    stop:
    return 0;
}
...