Как получить количество символов (в отличие от количества байтов) текста в Delphi?

У меня есть приложение Delphi 7, где я работаю со строками ANSI, и мне нужно подсчитать их количество символов (в отличие от количества байтов). Я всегда знаю кодировку (и, следовательно, кодовую страницу), связанную со строкой.

Итак, зная Charset (кодовую страницу), я сейчас использую MultiByteToWideChar чтобы получить количество символов. Это полезно, когда Charset является одной из китайских, корейских или японских кодировок, где большинство символов имеют длину 2 байта, и просто с помощью Length Функция не даст мне то, что я хочу.

Тем не менее, он все еще считает составные символы как два символа, и мне нужно, чтобы они считались как один. Теперь, некоторые составные символы имеют предварительно составленные версии в Юникоде, они будут правильно считаться как один символ, так как MB_PRECOMPOSED используется по умолчанию. Но многие символы просто не существуют как предварительно составленные, например символы на иврите, арабском, тайском и т. Д., И они считаются двумя.

Таким образом, вопрос на самом деле: как считать составные символы как отдельные символы? Я не против преобразования строк ANSI в широкие строки для подсчета количества символов, я уже делаю это с MultiByteToWideChar тем не мение.

1 ответ

Вы можете посчитать кодовые точки Unicode следующим образом:

function CodePointCount(P: PWideChar): Integer;
var
  Count: Integer;
begin
  Count := 0;
  while Word(P^)<>0 do
  begin
    if (Word(P^)>=$D800) and (Word(P^)<=$DFFF) then
      // part of surrogate pair
      inc(Count)
    else 
      inc(Count, 2);
    inc(P);
  end;  
  Result := Count div 2;
end;

Это касается вопроса, который вы не упомянули. А именно, что UTF-16 является кодировкой переменной ширины.

Однако это не скажет вам количество глифов, представленных строкой UTF-16. Это потому, что некоторые кодовые точки представляют комбинированные символы. Эти комбинирующие символы объединяются со своими соседями, образуя единый эквивалентный символ. Итак, несколько кодов, один глиф. Более подробную информацию можно найти здесь: http://en.wikipedia.org/wiki/Unicode_equivalence

Это более сложная проблема. Чтобы решить эту проблему, ваш код должен полностью понимать значение каждой кодовой точки Unicode. Это комбинирующий персонаж? Как это сочетается? На самом деле вам нужна выделенная библиотека Unicode. Например, ICU.

Еще одно предложение, которое у меня есть, - отказаться от использования кодовых страниц ANSI. Если вы действительно заботитесь о интернационализации, то вам нужно использовать Unicode.

Другие вопросы по тегам