Как проанализировать цифровые символы кандзи с помощью ICU?

К сожалению, очень сложно предоставить отзыв о вашем коде без тонны дополнительной информации, но, надеюсь, мои комментарии будут полезны.

В общем, иметь несколько потоков, читающих и пишущих из одного и того же файла, - действительно плохая идея. Я не могу больше согласиться с @ Hovercraft-Full-Of-Eels, который рекомендует, чтобы у вас была нить 1 для чтения / записи, а другие нити просто добавляли обновления в общую BlockingQueue.

Но это сказал, что вот некоторые комментарии.

Если setAndReplace () объявлен как static + синхронизированный, исходные данные реквизита сохраняются.

Правильно, это останавливает ужасное состояние гонки в вашем коде, когда 2 потока могут пытаться записать в выходной файл одновременно. Или может быть так, что 1 поток начинает запись , а другой поток читает пустой файл, что приводит к потере данных.

Если JVM уничтожена / прервана (после вызова FileOutputStream), тогда предыдущие данные будут удалены.

Я не совсем понимаю эту часть, но в вашем коде должны быть хорошие предложения try / finally, чтобы убедиться, что файлы закрываются надлежащим образом после завершения JVM. Если JVM жестко уничтожена, файл может быть открыт, но еще не записан (в зависимости от времени). В этом случае я бы порекомендовал вам записать во временный файл и переименовать в свой файл свойств, который является атомарным. Тогда вы можете пропустить обновление, если JVM уничтожена, но файл никогда не будет перезаписан и будет пустым.

Если я удалю статические и синхронизированные модификаторы из setAndReplace () и вызову setAndReplace () 5000 раз, старые данные все еще сохранятся (почему?)

Понятия не имею. Зависит от условий гонки. Может, тебе просто везет.

Когда я пытаюсь изменить файл props с помощью ExecutorService (иногда я получаю доступ к setAndReplacePropValue () через ExecutorService в моей программе), содержимое файла сохраняется до тех пор, пока не будет задержки после FileOutputStream. Если я добавлю задержку, и задержка будет> значением «тайм-аута», установленным в future.get () (так, чтобы генерировалось прерванное исключение), данные НЕ сохраняются. Это остается верным, даже если я добавлю статические + синхронизированные ключевые слова в метод.

Я не могу ответить на этот вопрос, не увидев конкретный код.

Это было бы хорошей идеей, если бы у вас был фиксированный пул потоков с 1 потоком, тогда каждый из потоков, которые хотят обновить значение, просто отправил бы объект поля / значения в пул потоков. Это примерно то, о чем говорил @ Hovercraft-Full-Of-Eels.

Надеюсь, это поможет.

7
задан Comic Sans MS Lover 5 May 2012 в 01:12
поделиться

4 ответа

Меня вдохновил ваш вопрос решить эту проблему с помощью Python .

Если вы не найдете решения C ++, оно не должно быть слишком сложным для приспособить это к C ++.

1
ответ дан 7 December 2019 в 01:26
поделиться

Я создал небольшой модуль Perl, чтобы сделать это некоторое время назад. он может конвертировать арабский <=> японский, и хотя я не тестировал его полностью, я думаю, что он довольно всеобъемлющий. не стесняйтесь улучшать его.

 
package kanjiArabic;
use strict;
use warnings;
our $VERSION = "1.00";
use utf8;

our %big = (
    十 => 10,百 => 100,千 => 1000,
    );
our %bigger = (
    万 => 10000,億 => 100000000,
    兆 => 1000000000000,京 => 10000000000000000,
    垓 => 100000000000000000000,
    );
#precompile regexes                                                                                                          
our $qr = qr/[0-9]/;
our $bigqr = qr/[十百千]/;
our $biggerqr = qr/[万億兆京垓]/;

#this routine does most of the real work.
sub kanji2arabic{
    $_ = shift;

    tr/〇一二三四五六七八九/0123456789/;
    #optionally precompile for performance boost                                                                             
    s/(?<=${qr})(${bigqr})/\*${1}/g;
    s/(?<=${bigqr})(${bigqr})/\+${1}/g;
    s/(${bigqr})(?=${qr})/${1}\+/g;
    s/(${bigqr})(?=${bigqr})/${1}\+/g;
    s/(${bigqr})/${big{$1}}/g;

    s/([0-9\+\*]+)/\(${1}\)/g;

    s/(? "〇", 1 => "一", 2 => "二", 3 => "三", 4 => "四",
    5 => "五", 6 => "六", 7 => "七", 8 => "八", 9 => "九",
    );
our %places = (
    1 => 10, 
    2 => 100, 
    3 => 1000, 
    4 => 10000, 
    8 => 100000000, 
    12 => 1000000000000,
    16 => 10000000000000000, 
    20 => 100000000000000000000,
    );
our %abig   = (
    10 => "十", 
    100 => "百", 
    1000 => "千", 
    10000 => "万", 
    100000000 => "億",
    1000000000000 => "兆", 
    10000000000000000 => "京", 
    100000000000000000000 => "垓",
    );
our $MAX = 24; #We only support numbers up to 24 digits!                                                                     


sub arabic2kanji{
    my @number = reverse(split(//,$_[0]));
    my @kanji;
    for(my $i=$#number;$i>=0;$i--){
        if( $i==0 ){push(@kanji,$asmall{$number[$i]});}
        elsif( $i % 4 == 0 ){
            if( $number[$i] !~ m/[01]/ ){
                push(@kanji,$asmall{$number[$i]});
            }
            push(@kanji,$abig{$places{$i}});
    }else{
            my $p = $i % 4;
            if( $number[$i]==0 ){
                next;
            }elsif( $number[$i]==1 ){
                push(@kanji,$abig{$places{$p}});
            }else{
                push(@kanji,$asmall{$number[$i]});
        push(@kanji,$abig{$places{$p}});
            }
    }
    }
    return join("",@kanji);
}


sub eval_k2a{
    #feed me utf-8!                                                                                                          
    if($_[0] !~ m/^[〇一二三四五六七八九十百千万億兆京垓]+$/){
        print "Error: ".$_[0].
              " not a Kanji number.\n" if defined($_[1])&&$_[1]==1;
        return -1;
    }
    my $expression = kanji2arabic($_[0]);
    print $expression."\n" if defined($_[1])&&$_[1]==1;
    return eval($expression);
}



1;

Затем вы вызываете его из другого сценария, например,


#!/usr/bin/perl -w
use strict;
use warnings;
use Encode;
use kanjiArabic;

my $kanji = kanjiArabic::arabic2kanji($ARGV[0]);
print "Kanji: ".encode("utf8",$kanji)."\n";
my $arabic =  kanjiArabic::eval_k2a($kanji);
print "Back to arabic...\n";
print "Arabic: ".$arabic."\n";

, и используете этот сценарий, например,


kettle:~/k2a$ ./k2a.pl 5000215
Kanji: 五百万二百十五
Back to arabic...
Arabic: 5000215

.

3
ответ дан 7 December 2019 в 01:26
поделиться

Вы можете использовать модуль формата чисел на основе правил ICU (RBNF) rbnf.h (C ++) или для C в unum.h с параметром UNUM_SPELLOUT, оба с локалью "ja" для Японский. Atryom исправляет ваш код для C ++: новый RuleBasedNumberFormat (URBNF_SPELLOUT, jaLocale, status);

6
ответ дан 7 December 2019 в 01:26
поделиться

На самом деле это довольно сложно, особенно если вы начнете смотреть на заметные кандзи для очень больших чисел .

В Perl есть очень полная реализация в Lingua :: JA :: Numbers . Его исходный код может вдохновить вас, если вы захотите перенести его на C ++.

0
ответ дан 7 December 2019 в 01:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: