Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проверить строку: Unicode или нет, как убедиться, что строка не Unicode 
V
    Опции темы
Bose
Дата 7.2.2007, 03:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1458
Регистрация: 5.3.2005
Где: Riga, Latvia

Репутация: 23
Всего: 51



Надо проверить строку(Widestring) и определить содержатся ли там символы, которые могут не отображаться на компах с другими локальными установками. Например: русские буквы, латышские, иероглифы и т.п.

Первая идея была пройтись по байтам строки и проверить каждый второй символ, если он не равен 0, значит - символ расщиренный, а следовательно и строка расширенная(Unicode). 

Немного подумав заменил манипуляции с указателями на проверку значения функции Ord для каждого символа. Сейчас функция выглядит так:

Код

function IsUnicode(const aText: WideString): boolean;
var
  i:integer;
begin

  Result:=False;
  for i:=1 to length(aText) do
    if Ord(aText[i])>255 then 
    begin
      Result := True;
      break;
    end;
end;


Всё в принципе работает. Русские и латышские символы определяются как Unicode, а английские - нет. Западноевропейские сивмолы(áäßøæµ) с такой проверкой в категорию Unicode не попадают. И тут меня стали мучать сомнения. Правильно это или нет. Ведь 255 - это было в DOSe(255 символов кодовой страницы OEM), но в Винде ведь всё по другому. 

Прошу советов. 
1) Как вы считаете будет ли эта функция корректно отделять зёрна от плевел символы читающиеся на компах с любой локалью, от символов корректное отображение которых зависит от текущей локали.
2) если да, то можно ли считать эту проверку корректной Ord(aText[i+1])>255 ?
PM MAIL WWW Skype   Вверх
MetalFan
Дата 7.2.2007, 09:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 62
Всего: 128



вообщето каждый символ WideString - это двухбайтовый Unicode символ. тогда уж сначала бери старший байт и его проверяй.
но зачем изобретать велосипед, если в винде уже его изобрели
The IsTextUnicode function determines whether a buffer is likely to contain a form of Unicode text. The function uses various statistical and deterministic methods to make its determination, under the control of flags passed via lpi. When the function returns, the results of such tests are reported via lpi. 

Код

BOOL IsTextUnicode(
  CONST VOID* pBuffer, // input buffer to be examined
  int cb,                // size of input buffer
  LPINT lpi               // options
);

з.ы. смотрим MSDN


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Bose
Дата 8.2.2007, 03:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1458
Регистрация: 5.3.2005
Где: Riga, Latvia

Репутация: 23
Всего: 51



Цитата(MetalFan @  7.2.2007,  09:33 Найти цитируемый пост)
The IsTextUnicode function determines whether a buffer is likely to contain a form of Unicode text.

Спасибо за совет, но это совсем не то что нужно.  smile 

Возможно я плохо сформулировал:

Итак нужно проверить строку и определить в каком формате её хранить: в Unicode или в Ansi. При этом надо быть уверенным, что на системе с другой локалью все символы Анси отобразятся как надо.

PM MAIL WWW Skype   Вверх
Bose
Дата 8.2.2007, 04:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1458
Регистрация: 5.3.2005
Где: Riga, Latvia

Репутация: 23
Всего: 51



Пока писал ответ, пришло в голову решение. Я изначально задал некорректный вопрос. Надо было определить не то является ли текст юникодным, а все ли символы текста могут отображаться в кодировке ISO-8859-1 (Latin 1)(основная кодировка для всех систем). Как только я понял свою ошибку, сразу же стало ясно как проверять.

Вот исправленный текст, если кому интересно:
Код

function IsTextUnicode(aText:WideString):boolean;
var
  i:cardinal;
begin
  Result:=False;
  for i:=1 to length(aText) do
  begin
    if ((Ord(aText[i])>$7F)and(Ord(aText[i])<$A0))or(Ord(aText[i])>$FF)  then
    begin
      Result := True;
      break;
    end;
  end;
end;


p.s. а функция IsTextUnicode проверяет, являются ли данные в буфере Unicodeной строкой .  (т.е. проверяют порядок байт, закрывающие байты, и прочие мелочи)
PM MAIL WWW Skype   Вверх
Snowy
Дата 8.2.2007, 11:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 192
Всего: 484



Короткий способ: Если строка, конвертнутая в UTF8 равна исходной строке, значит нет национальных символов.
PM MAIL   Вверх
MetalFan
Дата 8.2.2007, 12:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 62
Всего: 128



Цитата(Bose @  8.2.2007,  04:10 Найти цитируемый пост)
p.s. а функция IsTextUnicode проверяет, являются ли данные в буфере Unicodeной строкой .  (т.е. проверяют порядок байт, закрывающие байты, и прочие мелочи) 


ну а тебе что надо??? смотри опции функции IsTextUnicode:  smile 
IS_TEXT_UNICODE_ASCII16 The text is Unicode, and contains onlyzero-extended ASCII values/characters. 

или я чото непонимаю  smile 



--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Bose
Дата 8.2.2007, 12:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1458
Регистрация: 5.3.2005
Где: Riga, Latvia

Репутация: 23
Всего: 51



Цитата(Snowy @  8.2.2007,  11:53 Найти цитируемый пост)
Короткий способ: Если строка, конвертнутая в UTF8 равна исходной строке, значит нет национальных символов.

Через UTF8Encode?


Цитата(MetalFan @  8.2.2007,  12:26 Найти цитируемый пост)
ну а тебе что надо??? смотри опции функции IsTextUnicode:   IS_TEXT_UNICODE_ASCII16 The text is Unicode, and contains onlyzero-extended ASCII values/characters. 

Вызов IsTextUnicode с этим флагом, это тоже самое, что проверять каждый второй байт на равенство #0. 
MetalFan, спасибо за помощь, я вчера смотрел эту функцию на деле. Она совсем не подходит.
PM MAIL WWW Skype   Вверх
Snowy
Дата 8.2.2007, 12:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 192
Всего: 484



if UTF8Encode(s) = s then нет_национальных_символов

где s: string;
PM MAIL   Вверх
Bose
Дата 8.2.2007, 13:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1458
Регистрация: 5.3.2005
Где: Riga, Latvia

Репутация: 23
Всего: 51



Цитата(Snowy @  8.2.2007,  12:53 Найти цитируемый пост)
if UTF8Encode(s) = s then нет_национальных_символовгде s: string;

Спасибо за столь подробные разъяснения smile 
PM MAIL WWW Skype   Вверх
MetalFan
Дата 8.2.2007, 14:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 62
Всего: 128



Цитата(Bose @  8.2.2007,  12:43 Найти цитируемый пост)
я вчера смотрел эту функцию на деле. Она совсем не подходит.

плохо видимо смотрел ;)

Цитата(Bose @  8.2.2007,  12:43 Найти цитируемый пост)
проверять каждый второй байт на равенство #0

ты не прав) она будет проверять так, как ты укажешь. в т.ч. так же, как и в приведенном тобой коде.
з.ы. проверка Ord(text[i])>$FF тоже самое по сути делает. т.е. проверяет "второй" байт на <>0;

Это сообщение отредактировал(а) MetalFan - 8.2.2007, 14:37


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Bose
Дата 8.2.2007, 15:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1458
Регистрация: 5.3.2005
Где: Riga, Latvia

Репутация: 23
Всего: 51



Цитата(MetalFan @  8.2.2007,  14:31 Найти цитируемый пост)
ты не прав) она будет проверять так, как ты укажешь. в т.ч. так же, как и в приведенном тобой коде.з.ы. проверка Ord(text[i])>$FF тоже самое по сути делает. т.е. проверяет "второй" байт на <>0;

Хммм... Ну в принципе да. 
Но... Насколько я понимаю, WideString - это ещё не Unicode, разве не так? smile 

Собственно у меня эта функция с последним параметром options:=nil(провряет по всем условиям), работала совершенно невообразимым образом, выдавая False для строки из одного символа и True для всех остальных.  Так что я махнул на неё рукой. С конкретными флагами я не проверял, лень было искать их значения.(в Delphi 7 их нет)

К тому же, как я уже написал выше, я выяснил, что мне нужно было проверять не "Unicode - или нет Unicode", a "всё что не ISO-8859-1 (Latin 1), то Unicode".

PM MAIL WWW Skype   Вверх
MetalFan
Дата 8.2.2007, 16:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 62
Всего: 128



причем тут WideString и Юникод?
в делфи WideString используются для работы с юникод строками. т.е. там на символ по 2 байта, а не 1, как в AnsiString.
если в IsTextUnicode передать в опции "1", что соответствует той опции IS_TEXT_UNICODE_ASCII16, то проверка будет работать практически как та, что тобой приведена выше. но имхо правильное использование IsTextUnicode - более верное решение для  программирования под Win, чем написание собственных проверок, которые могут на самом деле не соответствовать действительности ;)


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Bose
Дата 8.2.2007, 16:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1458
Регистрация: 5.3.2005
Где: Riga, Latvia

Репутация: 23
Всего: 51



Цитата(MetalFan @  8.2.2007,  16:06 Найти цитируемый пост)
 более верное решение для  программирования под Win, чем написание собственных проверок, которые могут на самом деле не соответствовать действительности ;)

Могут, но... в чём именно?  smile 
PM MAIL WWW Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0890 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.