Непечатаемые символы (как различить?)

Модератор: Модераторы разделов

Аватара пользователя
devilr
Сообщения: 3440
ОС: Mandriva => Gentoo (~amd64)

Непечатаемые символы

Сообщение devilr »

Доброго времени суток!
Есть система логирования, на вход которой приходит строка из обычных символов. Но, иногда туда попадают всякие спецсимволы, нулевые символы и прочее, которые нормально напечатать не удастся, но хотелось бы их всё же видеть в логе (хотя бы в виде HEX)
На просторах интернета нарыл конструкцию

Код: Выделить всё

        QString data = входная строка;
        bool containsNonASCII = data.contains(QRegularExpression(QStringLiteral("[^\\x{0000}-\\x{007F}]")));
        if(containsNonASCII == false)
        {
        	// тут обычный текст
        }
        else
        {
		// HEX
        }
Но нормально не работает. Кто знаком с регулярками, подскажите, пожалуйста, как это можно сделать корректно?
Мудрость приходит с возрастом.
Иногда возраст приходит один.
Digital Art
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 19798
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Непечатаемые символы

Сообщение Bizdelnick »

Печатаемые символы начинаются с 0x20, а Вы проверяете с 0x0. То есть оно работает, как заявлено: проверяет наличие не-ASCII символов, Вы же хотите другого.
Я бы попробовал такую регулярку: [^[:print:]]. Хотя я не знаю, что там в Qt за движок (PCRE или какой-то свой?), и поддерживает ли он классы символов POSIX.
А можно без регулярок пробежаться по строке и проверить категории символов.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
devilr
Сообщения: 3440
ОС: Mandriva => Gentoo (~amd64)

Re: Непечатаемые символы

Сообщение devilr »

Bizdelnick писал:
25.01.2023 12:55
Печатаемые символы начинаются с 0x20, а Вы проверяете с 0x0. То есть оно работает, как заявлено: проверяет наличие не-ASCII символов, Вы же хотите другого.
Почему другого? Символы ASCII то все печатаемы, вроде.

Вашу регулярку сейчас проверю, сообщу.
Мудрость приходит с возрастом.
Иногда возраст приходит один.
Digital Art
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 19798
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Непечатаемые символы

Сообщение Bizdelnick »

devilr писал:
25.01.2023 13:38
Символы ASCII то все печатаемы, вроде.
Bizdelnick писал:
25.01.2023 12:55
Печатаемые символы начинаются с 0x20
До 0x1F — управляющие. Про 0x0 сами писали уже, он тоже в ASCII входит.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
devilr
Сообщения: 3440
ОС: Mandriva => Gentoo (~amd64)

Re: Непечатаемые символы

Сообщение devilr »

Регулярка не работает. Надо как то хитрее.
Добавлено (13:55):
Там ещё проблема может быть, что "символ" - это далеко не всегда один байт.
Мудрость приходит с возрастом.
Иногда возраст приходит один.
Digital Art
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 19798
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Непечатаемые символы

Сообщение Bizdelnick »

devilr писал:
25.01.2023 13:54
Регулярка не работает.
Очень подробное описание проблемы.
devilr писал:
25.01.2023 13:54
Надо как то хитрее.
Bizdelnick писал:
25.01.2023 12:55
можно без регулярок пробежаться по строке и проверить категории символов.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
devilr
Сообщения: 3440
ОС: Mandriva => Gentoo (~amd64)

Re: Непечатаемые символы

Сообщение devilr »

Bizdelnick писал:
25.01.2023 13:59
Очень подробное описание проблемы.
Я просто заменил свою регулярку на вашу. И подал на вход две строки - бинарную и текстовую. Ваша регулярка их не различает. Как и моя.
С "пробеганием" будут проблемы - символы бывают как 2-х байтовыми, так и 1 байтовыми. Я "категорию" уже раньше проверял - не работает оно нормально.
Мудрость приходит с возрастом.
Иногда возраст приходит один.
Digital Art
Спасибо сказали:
Аватара пользователя
ormorph
Сообщения: 2236
ОС: Gentoo

Re: Непечатаемые символы

Сообщение ormorph »

devilr
Я сейчас далеко от компа, но могу сразу сказать, что ваша регулярка не будет работать. Первое в условии в квадратных скобках вы зачем то вписали символ начала строки ^, его уже нужно вынести. И вообще не думаю что вам вообще этот символ нужен, так как будет тогда искать строки которые начинаются с символа не ASCII, а вам нужно если текст просто содержит не текстовые символы...
Подробнее читать qregexp
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 19798
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Непечатаемые символы

Сообщение Bizdelnick »

devilr писал:
25.01.2023 14:06
С "пробеганием" будут проблемы - символы бывают как 2-х байтовыми, так и 1 байтовыми.
Я думал, QString состоит из QChar. То есть Вы уже корректно преобразовали поток байтов из входной кодировки. Если Вы этого не сделали, то, конечно, ничего работать не будет.
ormorph писал(а):
25.01.2023 14:55
в условии в квадратных скобках вы зачем то вписали символ начала строки ^
В начале класса символов ^ означает инверсию, тут нет ошибки.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
ormorph
Сообщения: 2236
ОС: Gentoo

Re: Непечатаемые символы

Сообщение ormorph »

Bizdelnick писал:
25.01.2023 15:22
В начале класса символов ^ означает инверсию, тут нет ошибки.
Хм тогда там скорее всего пропускаются символы(байты) начиная с нулевого адреса до 0x20.
Добавлено (17:17):
А не, пересмотрел, там соответствует символам unicode. Сама таблица посмотреть тут, но тогда тут косяк, цифры начинаются с 0x0030. Нужно как следует штудировать таблицу на спец символы. Нужно начиная с пробела 0x0020, а далее смотреть какие ещё есть нехорошие адреса. Раз уж цель только видимые символы иметь.
Только символ ^ не совсем инверсия, он означает, что угодно, только не то, что в квадратных скобках, в случае инверсии адреса были бы несколько другими, но если это выражение рассматривать как предикат, то это отрицание. Надо рассматривать как множество.
Спасибо сказали:
Аватара пользователя
devilr
Сообщения: 3440
ОС: Mandriva => Gentoo (~amd64)

Re: Непечатаемые символы

Сообщение devilr »

ormorph писал(а):
25.01.2023 14:55
Я сейчас далеко от компа, но могу сразу сказать, что ваша регулярка не будет работать.
Она не моя, я просто нашёл её в интернете. Да и не понимаю я регулярки, если честно.

А сама тема старая - нужно просто распечатать строку. Либо "как есть" или в виде HEX. И там даже может быть это и строка вовсе - просто поток байтов. И я разумное решение проблемы ищу очень давно - пока без толку.
Уточнение к исходной задаче - там нет смеси бинарных данных и текстовых. Либо HEX, либо BIN.
Мудрость приходит с возрастом.
Иногда возраст приходит один.
Digital Art
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 19798
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Непечатаемые символы

Сообщение Bizdelnick »

devilr писал:
25.01.2023 20:14
там даже может быть это и строка вовсе - просто поток байтов
Так каким образом Вы его запихиваете в QString? Почему у Вас не QByteArray, если там неведомо что?
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
devilr
Сообщения: 3440
ОС: Mandriva => Gentoo (~amd64)

Re: Непечатаемые символы

Сообщение devilr »

Bizdelnick писал:
25.01.2023 20:38
Почему у Вас не QByteArray, если там неведомо что?
Там и так QByteArray. Просто, если начинаешь говорить за QByteArray - разговор уходит прям сразу не туда. Просто опыт. :)
К тому же QString и QByteArray преобразовываются друг в друга элементарно.
Последний раз редактировалось devilr 25.01.2023 21:40, всего редактировалось 1 раз.
Мудрость приходит с возрастом.
Иногда возраст приходит один.
Digital Art
Спасибо сказали:
Аватара пользователя
ormorph
Сообщения: 2236
ОС: Gentoo

Re: Непечатаемые символы

Сообщение ormorph »

Символы Юникода это двух-байтовые слова, т. е. диапазон 0x0000-0xFFFF, это и есть множество, если из этого диапазона отнять диапазон что у вас в условии без знака ^, то получится, новый диапазон, эквивалентный вашему условию со знаком ^. Это то что делает ваше условие, его можно заменить другим. Соответственно если посмотреть на таблицу, что ссылку я вам дал, у вас символы в диапазоне от 0x0000-0x001f, которые не включаются в новое множество адресов. Т. е. Регулярка должна включать несколько вариантов условий через или, чтобы сформировать конечное множество.
Спасибо сказали:
Аватара пользователя
devilr
Сообщения: 3440
ОС: Mandriva => Gentoo (~amd64)

Re: Непечатаемые символы

Сообщение devilr »

ormorph я Вашу мысль не понимаю. Там просто строка, массив байт, который нужно распечатать в читаемом виде. Или в виде HEX, если это бинарные данные. И не факт, что эта строка будет именно классический Юникод.
Нужно просто это как то распознать.
Мудрость приходит с возрастом.
Иногда возраст приходит один.
Digital Art
Спасибо сказали:
Аватара пользователя
ormorph
Сообщения: 2236
ОС: Gentoo

Re: Непечатаемые символы

Сообщение ormorph »

devilr писал:
25.01.2023 21:38
ormorph я Вашу мысль не понимаю. Там просто строка, массив байт, который нужно распечатать в читаемом виде. Или в виде HEX, если это бинарные данные. И не факт, что эта строка будет именно классический Юникод.
Нужно просто это как то распознать.
Я просто объясняю, что делает ваш пример, он просто ищет символы соответствующие диапазону адресов 0x0080-0xffff, т.е. исключающие коды Basic Latin. Просто формат регулярок такой, x{} соответствует коду символа юникода. Просто посмотрите описание класса QRegExp, ссылку я давал, также это же описание присутствует в Qt Assistant. Для байтов там предусмотрен формат \0ooo. Интересно а что выведет если прописать в условии [^\\w\\d\\s]? Это если не слово, не цифра и не пробел. Но скорее всего нужно на оборот без знака ^, так как перечисление в [] идет как через оператор или, просто в if поменять false на true. Вроде тоже самое должно получиться если прописать без [] просто \\w*\\d*\\s*, но тут не уверен.
Спасибо сказали:
Аватара пользователя
devilr
Сообщения: 3440
ОС: Mandriva => Gentoo (~amd64)

Re: Непечатаемые символы

Сообщение devilr »

ormorph я толком не могу себе описать эту задачу на человеческом языке, не то, что на регулярках. :)
Тут надо, видимо, сам подход менять.
Мудрость приходит с возрастом.
Иногда возраст приходит один.
Digital Art
Спасибо сказали:
Аватара пользователя
ormorph
Сообщения: 2236
ОС: Gentoo

Re: Непечатаемые символы

Сообщение ormorph »

devilr писал:
25.01.2023 23:30
Тут надо, видимо, сам подход менять.
Тут надо разбираться, так как всё что перечислил не должно работать, так как при или будет использовать любой из вариантов, это всё не то. Знаю только что описание регулярок нужно смотреть в QRegExp, это нужно ещё почитать.
Спасибо сказали:
Аватара пользователя
devilr
Сообщения: 3440
ОС: Mandriva => Gentoo (~amd64)

Re: Непечатаемые символы

Сообщение devilr »

ormorph писал(а):
25.01.2023 22:54
[^\\w\\d\\s]
Тоже не работает. Только что проверил.
P.S. Точнее работает, но в ограниченных случаях. Например, если текст не содержит русских символов. Наверняка, ещё что есть, пока не проверял.
Мудрость приходит с возрастом.
Иногда возраст приходит один.
Digital Art
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 19798
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Непечатаемые символы

Сообщение Bizdelnick »

devilr писал:
25.01.2023 20:48
Там и так QByteArray. Просто, если начинаешь говорить за QByteArray - разговор уходит прям сразу не туда.
А так дело ушло не туда. Нашли решение для QString, и удивляетесь, что оно не работает.
devilr писал:
25.01.2023 20:48
К тому же QString и QByteArray преобразовываются друг в друга элементарно.
Каким образом Вы это делаете? Я чайник в Qt и мысли читать не обучен. Показывайте код.
QString, вроде, подразумевает UTF-16, а Вы, как я понял с Ваших слов, ожидаете UTF-8. Значит, надо перекодировать, а потом уже пытаться с получившимся работать — регуляркой или циклом по символам строки. Пример из доки:

Код: Выделить всё

QByteArray encodedString = "...";
auto toUtf16 = QStringDecoder(QStringDecoder::Utf8);
QString string = toUtf16(encodedString);
Далее проверить результат, если ошибка — значит не текст в UTF-8, выводить в шестнадцатеричном виде. Если ошибки нет — проверять наличие непечатаемых символов.

Код: Выделить всё

if (toUtf16.hasError() || string.contains(QRegularExpression(QStringLiteral("[^[:print:][:space:]]"))) {
  // выводим encodedString как HEX
} else {
  // выводим string как текст
}
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
math
Сообщения: 221
Статус: Ъ участник
ОС: Artix (= Arch without systemd)

Re: Непечатаемые символы

Сообщение math »

ormorph писал(а):
25.01.2023 21:08
Символы Юникода это двух-байтовые слова
Это мягко говоря неправда.
Спасибо сказали:
Аватара пользователя
ormorph
Сообщения: 2236
ОС: Gentoo

Re: Непечатаемые символы

Сообщение ormorph »

math писал:
26.01.2023 05:04
ormorph писал(а):
25.01.2023 21:08
Символы Юникода это двух-байтовые слова
Это мягко говоря неправда.
Пардон 4 байта(До 4 байт). ASCII в utf8 кодируется также, чего не скажешь о utf16.
Спасибо сказали:
Аватара пользователя
devilr
Сообщения: 3440
ОС: Mandriva => Gentoo (~amd64)

Re: Непечатаемые символы

Сообщение devilr »

Bizdelnick посмотрю Ваш код. Когда найду машину с Qt6
Мудрость приходит с возрастом.
Иногда возраст приходит один.
Digital Art
Спасибо сказали:
math
Сообщения: 221
Статус: Ъ участник
ОС: Artix (= Arch without systemd)

Re: Непечатаемые символы

Сообщение math »

ormorph писал(а):
26.01.2023 09:36
Пардон 4 байта(До 4 байт). ASCII в utf8 кодируется также, чего не скажешь о utf16.
Всё же говорить о количестве байт без конкретной кодировки не очень. Символы Юникод (и тут сразу стоит уточнить, что имеются в виду кодепоинты, а не графемы) кодируются числами в диапазоне от 0 до 10FFFFh включительно, кроме запрещённого диапазона от D800h до DFFFh. В кодировке UTF-32 каждый символ это всегда 4 байта, в UTF-16 — 2 или 4 байта, в UTF-8 — от 1 до 4 байт.
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 19798
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Непечатаемые символы

Сообщение Bizdelnick »

devilr писал:
26.01.2023 10:36
Когда найду машину с Qt6
В Qt5 надо делать с помощью QTextCodec, как я понимаю, но сам принцип не меняется.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
ormorph
Сообщения: 2236
ОС: Gentoo

Re: Непечатаемые символы

Сообщение ormorph »

math писал:
26.01.2023 12:36
кодируются числами в диапазоне от 0 до 10FFFFh включительно
Что то тут не так, это числа до трёх байт. Я бы хотел бы найти более точную информацию. Так как 4 байта это XXXXXXXXh, каждый байт 11111111 соответствует FF в hex.
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 19798
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Непечатаемые символы

Сообщение Bizdelnick »

Offtopic
ormorph писал(а):
26.01.2023 13:33
4 байта это XXXXXXXXh, каждый байт 11111111 соответствует FF в hex.
Да, но в UTF-8 столько закодировать невозможно.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
devilr
Сообщения: 3440
ОС: Mandriva => Gentoo (~amd64)

Re: Непечатаемые символы

Сообщение devilr »

Bizdelnick а какой принцип то? Если не смогли перевести в UTF-16 или соответствуем регулярке "[^[:print:]]" - то это бинарные данные? Я подсуну ему на вход строку в том же cp-1251 и обломлюсь, скорее всего.
Возможно, я неполно объяснил условия задачи. Попробую ещё раз.
Есть 100500 девайсов. Мультиметры, калибраторы, компараторы и многое другое. Их всех объединяет одно - RS-232. ПО для них написано разными людьми и в разное время. Часть девайсов шлёт свои данные в текстовом виде, часть - в бинарном. Мне их надо как то получить в читаемом виде. Пока обходился костылём в виде чекбокса "HEX-TEXT". Но, хотелось бы это автоматизировать.
Мудрость приходит с возрастом.
Иногда возраст приходит один.
Digital Art
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 19798
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Непечатаемые символы

Сообщение Bizdelnick »

devilr писал:
26.01.2023 13:43
Я подсуну ему на вход строку в том же cp-1251 и обломлюсь, скорее всего.
Да. А Вы как хотели, ещё и кодировку автоматом детектировать? ТЗ надо точнее составлять.
devilr писал:
26.01.2023 13:43
Есть 100500 девайсов. Мультиметры, калибраторы, компараторы и многое другое. Их всех объединяет одно - RS-232.
Ну там вряд ли используется что-то за пределами ASCII, так что о cp-1251 можно не беспокоиться. Но зато там \r\n, скорее всего, будут, так что стоит добавить их в регулярку. Или вообще весь класс [:space:]. (Отредактировал код в своём сообщении выше.)
devilr писал:
26.01.2023 13:43
Пока обходился костылём в виде чекбокса "HEX-TEXT".
Там ведь не было перекодировки, да? Выплёвывали текст в локаль UTF-8, и работало?
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
devilr
Сообщения: 3440
ОС: Mandriva => Gentoo (~amd64)

Re: Непечатаемые символы

Сообщение devilr »

Bizdelnick писал:
26.01.2023 13:56
Там ведь не было перекодировки, да? Выплёвывали текст в локаль UTF-8, и работало?
Не было. Да и не предполагалось. Если я видел "кракозябры" - это меня вполне устраивало (я просто переключу кодировку в программе, запрошу данные вновь и прочитаю). Другое дело, что символ 0x00 или 0xFF отобразятся "квадратиками". А мне нужен либо текст, либо HEX.
Мудрость приходит с возрастом.
Иногда возраст приходит один.
Digital Art
Спасибо сказали: