Форум программистов, компьютерный форум, киберфорум
Наши страницы

Qt

Войти
Регистрация
Восстановить пароль
 
 
WxMaper
33 / 33 / 9
Регистрация: 19.10.2013
Сообщений: 341
#1

Как отличить бинарные данные от текстовых? - C++ Qt

25.03.2016, 19:52. Просмотров 483. Ответов 15
Метки нет (Все метки)

Есть ini-файл. Неважно как он сохранялся (допустим, мне это неизвестно), но его содержимое такое:

C++ (Qt)
1
2
[General]
property=@ByteArray(textValue)
При получении значения property с помощью QSettings, на выходе я получаю QVariant<QByteArray>, который должен быть конвертирован в строку, но тут получается такая вот загвоздочка:

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
QVariant value = settings.value("property");
 
while(value.type() == QMetaType::QVariant) {
    value = value.value<QVariant>(); // извлекаю истинный тип :-)
}
 
switch (value.type()) {
case QMetaType::QByteArray: {
    // тут должны быть бинарные данные
    QByteArray ba = value.toByteArray();
    call_some_method(ba);
    break;
}
 
case QMetaType::QString: {
    // тут должна быть обычная строка 
    QByteArray ba = value.toString().toUtf8(); 
    call_some_method(ba);
    break;
}
всегда вызывается метод для работы с бинарными данными, при чем на вход попадает не строка "textValue", а какое-то значение " \xtra-ta-ta", хотя очевидно, что значение в property вполне читаемое-текстовое-строковое.

Какой есть способ отличить бинарные данные от строки?

п.с. QSettings привел просто в качестве наглядного примера, поэтому предлагать сохранять строки строками, а не байт-массивами не нужно
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
25.03.2016, 19:52
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Как отличить бинарные данные от текстовых? (C++ Qt):

Что быстрей читает текст и бинарные данные QFile или std::istream? - C++ Qt
Что быстрей читает текст и бинарные данные QFile или std::istream? есть у кого опыт в тестировании?

Как отличить, кто изменил состояние виджета: программа или пользователь? - C++ Qt
Например , есть объект foo типа QSpinBox. Сигнал textChanged генерируется при изменении значения пользователем и из...

Как правильно прописать бинарные данные? - C#
Имеется значение реестра в HEX виде: Как в Visual Studio 2015 прописать это значение через приложение Windows Form? ...

Strlen и бинарные данные в char - как выполнить их отправку - C++
Размер бинарных данных готовых к отправки всегда разный. В середине может содержатся любое кол-во 0x00. Как выполнить отправку таких...

Как считывать бинарные данные из файла с big-endian порядком? - Visual Basic .NET
Как считать данный из bin файла в котором данные(байты) записаны от старшего к младшему(т.е. в big-endian) сейчас я использую такой код...

Как считать данные из нескольких текстовых файлов? - VBA
Есть некая папка, в ней может находится каждый раз РАЗНОЕ количество текстовых файлов. Нужно, чтобы программа открывала данную папку...

15
RazrFalcon
1384 / 1241 / 262
Регистрация: 10.11.2013
Сообщений: 3,763
26.03.2016, 01:30 #2
Так все верно же. Если QSetting уже сохранил их как QByteArray, то нужно и грузить их в обратном порядке.
Если бы была строка, тогда ваш код бы работал. QSetting не знает что в самом QByteArray было изначально, поэтому строку он никак оттуда не получит.
0
WxMaper
33 / 33 / 9
Регистрация: 19.10.2013
Сообщений: 341
26.03.2016, 09:36  [ТС] #3
Так может ему можно как-то помочь? Вроде бинарные данные от текстовых отличаются наличием каких-то специфических байт в самом начале строки.

У меня в коде есть еще одно очень проблемное место: входным параметром является char *, который может быть либо просто "Hello world!", либо может быть результатом чтения бинарного файла, например PNG картинки. Их тоже нужно как-то различать =)

В первом случае char * без проблем конвертируется в "текстовые" QString или QByteArray:
C++ (Qt)
1
2
3
4
void someMethod(char *data) {
    QString string = QString(data); // ok
    QByteArray ba = QByteArray(data); // ok
}
Во втором случае char * нельзя конвертировать ни в QString , ни даже в QByteArray, иначе там отпадают несколько байт в самом начале и данные становятся битыми:

C++ (Qt)
1
2
3
4
void someMethod(char *data) {
    QByteArray ba = QByteArray(data); // wrong!
    QByteArray ba = QByteArray::fromRawData(data, sizeof(data)); // ok
}
данные будут не повреждены, но с ними нужно работать осторожно, потому что:
Constructs a QByteArray that uses the first size bytes of the data array. The bytes are not copied. The QByteArray will contain the data pointer. The caller guarantees that data will not be deleted or modified as long as this QByteArray and any copies of it exist that have not been modified.
http://doc.qt.io/qt-5/qbytearray.html#fromRawData

и как в таком случае отличать что же на самом деле в char *?
0
Wyn
1055 / 637 / 232
Регистрация: 14.01.2016
Сообщений: 2,031
Записей в блоге: 9
26.03.2016, 10:41 #4
Цитата Сообщение от WxMaper Посмотреть сообщение
void someMethod(char *data) {
* * QByteArray ba = QByteArray(data); // wrong!
* * QByteArray ba = QByteArray::fromRawData(data, sizeof(data)); // ok
}
Что это за бред?

Добавлено через 33 секунды
Цитата Сообщение от WxMaper Посмотреть сообщение
sizeof(data)
И чему же тут равен sizeof?

Добавлено через 11 минут
Цитата Сообщение от WxMaper Посмотреть сообщение
Так может ему можно как-то помочь?
Если у вас завис компьютер или программа, то они не отвиснут от того, что вы нажмёте 1000 раз на мышку или пнёте его корпус пару раз. Прежде чем лезть своими ручками куда-то "помогать" нужно вначале разобраться как это работает, а не выдумывать оголтелые фантазии на основе своего волшебного быдлокода и иллюзий, полученных в результате чтения мануала по диагонали.
0
alexu_007
140 / 151 / 34
Регистрация: 29.05.2015
Сообщений: 1,088
26.03.2016, 10:44 #5
Цитата Сообщение от WxMaper Посмотреть сообщение
и как в таком случае отличать что же на самом деле в char *?
В char в любом случае записаны цифры от 0 до 255. Которые могут означать что угодно... тому, кто их туда записал. Если там в основном коды букв и цифр - то скорей всего это текст. Если что другое - записывайтесь в дешифровальщики.
0
RazrFalcon
1384 / 1241 / 262
Регистрация: 10.11.2013
Сообщений: 3,763
26.03.2016, 14:43 #6
Цитата Сообщение от WxMaper Посмотреть сообщение
и как в таком случае отличать что же на самом деле в char *
Это невозможно.

Цитата Сообщение от WxMaper Посмотреть сообщение
Вроде бинарные данные от текстовых отличаются наличием каких-то специфических байт в самом начале строки.
Нет.

Цитата Сообщение от WxMaper Посмотреть сообщение
Их тоже нужно как-то различать
Никак.
0
WxMaper
33 / 33 / 9
Регистрация: 19.10.2013
Сообщений: 341
26.03.2016, 17:18  [ТС] #7
Цитата Сообщение от Wyn Посмотреть сообщение
И чему же тут равен sizeof?
омг... ну очевидно же, что это псевдокод. Подставьте туда что вам удобно использовать для получения размера...

Цитата Сообщение от Wyn Посмотреть сообщение
Что это за бред?
Это не бред, это реальная ситуация с которой вы просто никогда не сталкивались. Вот вам даже простейший пример

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    
    QFile file("d:/header_bg.png");
    if(!file.open(QIODevice::ReadOnly))
        return;
 
    char *file_data = new char[file.size()];
    file.read(file_data, file.size());
 
    QByteArray ba1 = QByteArray(file_data); // broken
    QByteArray ba2 = QByteArray::fromRawData(file_data, file.size()); // ok
 
    qDebug() << "ba1" << ba1; // ba1 "\x89PNG\r\n\x1A\n"
    qDebug() << "ba2" << file_data; // ba2 ?PNG
    
    QPixmap pixmap;
    pixmap.loadFromData(file.readAll()); // broken
    pixmap.loadFromData(ba1); // broken
    pixmap.loadFromData(ba2); // ok
Проблемы с оголтелыми фантазиями и фобиями быдлокода только у вас.

Добавлено через 29 секунд
Цитата Сообщение от RazrFalcon Посмотреть сообщение
Это невозможно.
ок, понял

Добавлено через 1 час 15 минут
Помогло решение в лоб:

C++ (Qt)
1
2
3
4
5
6
7
8
QString str = QString::fromLatin1(data.str->val); // data.str->val - это тот самый char *
 
if(str.length() == data.str->len) {
    // работаем с plain text
}
else {
    // работаем с raw data
}
вроде работает адекватно, символы в юникоде распознаются благодаря fromLatin1, с латиницей и так все ясно... длинна смешанного текста тоже правильно считается
0
Wyn
1055 / 637 / 232
Регистрация: 14.01.2016
Сообщений: 2,031
Записей в блоге: 9
27.03.2016, 12:51 #8
Цитата Сообщение от WxMaper Посмотреть сообщение
омг... ну очевидно же, что это псевдокод. Подставьте туда что вам удобно использовать для получения размера...
Кому очевидно? Вам? Я не видел там псевдокода, я видел ошибку, которую к сожалению встречал очень часто.
Цитата Сообщение от WxMaper Посмотреть сообщение
Это не бред, это реальная ситуация с которой вы просто никогда не сталкивались. Вот вам даже простейший пример
Это именно что бред. Любой вменяемый программист С++ прекрасно понимает что такое данные и как с ними работать. В том числе понимает что тот же текст(в виде char*) - это те самые "бинарные данные", только интерпретируемые как текст(о чём вам выше RazrFalcon написал). У вас там ещё куча ошибок в вашем "псевдокоде", которые я просто не стал перечислять.
Цитата Сообщение от WxMaper Посмотреть сообщение
Проблемы с оголтелыми фантазиями и фобиями быдлокода только у вас.
У меня подобных проблем не возникает, что уже должно говорить о многом.
Не верите? Так давайте разберём ваш очередной быдло"псевдокод":
Цитата Сообщение от WxMaper Посмотреть сообщение
QFile file("d:/header_bg.png");
if(!file.open(QIODevice::ReadOnly))
return;

char *file_data = new char[file.size()];
file.read(file_data, file.size());
QByteArray ba1 = QByteArray(file_data); // broken
QByteArray ba2 = QByteArray::fromRawData(file_data, file.size()); // ok
qDebug() << "ba1" << ba1; // ba1 "\x89PNG\r\n\x1A\n"
qDebug() << "ba2" << file_data; // ba2 ?PNG

QPixmap pixmap;
pixmap.loadFromData(file.readAll()); // broken
pixmap.loadFromData(ba1); // broken
pixmap.loadFromData(ba2); // ok
Зачем все эти волшебные пляски с бубном(с char*), когда есть тупая операция QIODevice::readAll(), возвращающая данные сразу в QByteArray?
Разумеется QByteArray(file_data); будет у вас сломан - данный конструктор в случае отсутствия второго аргумента ждёт обычную char* строку, которая заканчивается '\0'. Правильное использование в данном случае было бы QByteArray(file_data, file.size()).
И разумеется pixmap.loadFromData(file.readAll()); у вас тоже будет сломано. Потому что вы уже считали все данные операцией read() и файловый курсор у вас стоит в конце файла.

Добавлено через 7 минут
Проблема же отличия текста от других данных - это не проблема программы, а проблема программиста. Всё иное подразумевает под собой хреновую архитектуру программы.
0
WxMaper
33 / 33 / 9
Регистрация: 19.10.2013
Сообщений: 341
27.03.2016, 14:26  [ТС] #9
Цитата Сообщение от Wyn Посмотреть сообщение
Зачем все эти волшебные пляски с бубном(с char*), когда есть тупая операция QIODevice::readAll(), возвращающая данные сразу в QByteArray?
В смысле зачем? При чем тут "зачем"? Это был пример. Который легко описывает ситуацию "как есть".
Я же объяснил: у моей функции на входе просто char*, она не знает откуда эти данные пришли, но ей нужно определить что с ними делать.

Цитата Сообщение от Wyn Посмотреть сообщение
Любой вменяемый программист С++ прекрасно понимает что такое данные и как с ними работать
Покажите мне где я тут спрашивал что такое данные и как с ними работать?

Цитата Сообщение от Wyn Посмотреть сообщение
У вас там ещё куча ошибок в вашем "псевдокоде", которые я просто не стал перечислять.
Это вы еще весь код не видели, вы бы наверное захлебнулись слюнями комментируя каждую строчку "быдлокода". Сделайте лучше, сделайте правильно, кто вам не даёт? Или у вас хватает сил только на то, чтобы чужой труд нарекать "быдлокодом"?

Цитата Сообщение от Wyn Посмотреть сообщение
Проблема же отличия текста от других данных - это не проблема программы, а проблема программиста
При чем тут проблемы какие-то? Я писал в форум программистов, а не психологов.
0
pav1uxa
1855 / 1709 / 645
Регистрация: 23.01.2014
Сообщений: 6,082
Завершенные тесты: 1
27.03.2016, 14:51 #10
Цитата Сообщение от WxMaper Посмотреть сообщение
Помогло решение в лоб:
А что такое data.str->len ?
0
WxMaper
33 / 33 / 9
Регистрация: 19.10.2013
Сообщений: 341
27.03.2016, 15:17  [ТС] #11
Цитата Сообщение от pav1uxa Посмотреть сообщение
А что такое data.str->len ?
Это размер данных (длинна строки).

C++ (Qt)
1
2
3
4
5
6
struct _zend_string {
    zend_refcounted_h gc;
    zend_ulong        h;                /* hash value */
    size_t            len;
    char              val[1];
};
Если опустить все детали, то можно сказать так: на стороне c++ я получаю данные из PHP функции file_get_contents() (читает любой файл). Результат возвращаются в виде структуры zend_string, которая имеет 2 основных поля: char *val и size_t len.
Далее нужно было извлечь из этой структуры либо строку и отправить по назначению, например, в QPushButton::setText() или в QTextEdit::setPlainText(), либо напрямую передать "сырые" данные в QPixmap::loadFromData() или еще куда...
Весь затык в том, что в этом контексте не известно куда дальше отправятся данные и какой тип ожидается на том конце. Здесь просто есть zend_string, а задача функции - извлечь из этого zend_string данные.
0
pav1uxa
1855 / 1709 / 645
Регистрация: 23.01.2014
Сообщений: 6,082
Завершенные тесты: 1
27.03.2016, 15:50 #12
Цитата Сообщение от WxMaper Посмотреть сообщение
Далее нужно было извлечь из этой структуры либо строку и отправить по назначению
Это понятно, просто я не понял как это Вы по длине этих данных пытаетесь определить строка это или не строка оО Ну лежит там 1 байт, и как понять, это 1 символ в кодировке ANSI или 1 байт информации? Да никак.

Если там может быть либо текст, либо картинка, то нужно для начала определить - какая картинка? Например у BMP-файла первые 2 байта 0x4D42 - по ним сразу можно понять что это картинка в формате bmp. У всех остальных форматов есть подобные маркеры.
0
WxMaper
33 / 33 / 9
Регистрация: 19.10.2013
Сообщений: 341
27.03.2016, 16:07  [ТС] #13
Цитата Сообщение от pav1uxa Посмотреть сообщение
Это понятно, просто я не понял как это Вы по длине этих данных пытаетесь определить строка это или не строка оО Ну лежит там 1 байт, и как понять, это 1 символ в кодировке ANSI или 1 байт информации? Да никак.
С этим не поспоришь... но в приоритете остаются все-же строки.

Кликните здесь для просмотра всего текста
Сейчас вот такой php-код отрабатывается корректно:
PHP
1
2
3
4
5
6
7
8
9
10
11
$settings = new QSettings("data.ini", QSettings::IniFormat);
$settings->setValue('test1', "1");
$settings->setValue('test2', "z");
$settings->setValue('test3', "я");
$settings->setValue('test4', file_get_contents("d:/vertical.png"));
 
$pixmap = new QPixmap;
$pixmap->loadFromData($settings->value('test4'));
 
$label = new QLabel($this);
$label->pixmap = $pixmap;
После его выполнения получаю форму с загруженной картинкой и ini-файлом с таким содержанием:
PHP
1
2
3
4
5
[General]
test1=1
test2=z
test3=\x44f
test4="@ByteArray(многобукаф)"


Цитата Сообщение от pav1uxa Посмотреть сообщение
Если там может быть либо текст, либо картинка, то нужно для начала определить - какая картинка? Например у BMP-файла первые 2 байта 0x4D42 - по ним сразу можно понять что это картинка в формате bmp. У всех остальных форматов есть подобные маркеры.
В том то и дело, что может быть не только картинка. Может быть звуковой файл, архив... да что угодно. Картинка - это просто пример
0
Wyn
1055 / 637 / 232
Регистрация: 14.01.2016
Сообщений: 2,031
Записей в блоге: 9
27.03.2016, 16:20 #14
Цитата Сообщение от WxMaper Посмотреть сообщение
В смысле зачем? При чем тут "зачем"? Это был пример. Который легко описывает ситуацию "как есть".
Я же объяснил: у моей функции на входе просто char*, она не знает откуда эти данные пришли, но ей нужно определить что с ними делать.
Это невозможно. "Просто char*" - это указатель на "что-то неизвестного размера". Я о том и говорю - ситуация "как есть" в данном случае возникла в следствии хреновой(непродуманной) архитектуры программы.
Цитата Сообщение от WxMaper Посмотреть сообщение
Покажите мне где я тут спрашивал что такое данные и как с ними работать?
Это вытекает из того что вы тут пишите. Огромное количество ошибок, которые явно показывают уровень вашего непонимания.
Цитата Сообщение от WxMaper Посмотреть сообщение
Это вы еще весь код не видели, вы бы наверное захлебнулись слюнями комментируя каждую строчку "быдлокода". Сделайте лучше, сделайте правильно, кто вам не даёт? Или у вас хватает сил только на то, чтобы чужой труд нарекать "быдлокодом"?
Так это не мне надо делать, а вам. Я вам лишь могу намекнуть как оно по хорошему работать, чтобы подобных ситуаций не возникало и привести пример. Но для этого надо знать что у вас в качестве изначальных входных данных и что вы хотите получить по итогу.
0
pav1uxa
1855 / 1709 / 645
Регистрация: 23.01.2014
Сообщений: 6,082
Завершенные тесты: 1
27.03.2016, 16:25 #15

Не по теме:

Первый раз вижу qt в php, здорово...



Добавлено через 1 минуту
Цитата Сообщение от WxMaper Посмотреть сообщение
В том то и дело, что может быть не только картинка. Может быть звуковой файл, архив... да что угодно. Картинка - это просто пример
Ну можно создать свой класс. Сделать 2 члена класса - массив байт (char*) и расширение (можно строкой), или название файла. Реализовать у него operator>> и operator<< "в" и "из" QDataStream. И записывать их как хотите, потом при считывании будет понятно что это...
0
27.03.2016, 16:25
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.03.2016, 16:25
Привет! Вот еще темы с ответами:

Как сохранить данные текстовых полей, леблов в exel? - Visual Basic .NET
Попробовал сделать вот так: Dim Exl As Object = CreateObject(&quot;Excel.Application&quot;) Exl.workbooks.open(&quot;D:\Test.xls&quot;) ...

Нужен пример кода как получить данные из текстовых полей HTML страницы - Java EE
Кто-нибудь может привести пример кода как получить данные из текстовых полей HTML страницы. Т.е. я ввожу данные в текстовые поля на HTML...

SqlDataReader и бинарные данные - C#
Уважаемое Эксперты помогите пожалуйста ! Я записываю двоичное данное на базе SQL 2000 обратно когда получаю по запросу SQL ...

Отправить бинарные данные на сервер - C++
Проблема вот в чем, у меня есть бинарная строка, которую надо отправить на сервер и там с ней работать. Я попробовал через POST ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru