Russian Qt Forum

Qt => Вопросы новичков => Тема начата: Alexu007 от Март 11, 2014, 23:42



Название: Как поместить в int 8-битный код русского символа?
Отправлено: Alexu007 от Март 11, 2014, 23:42
Код
C++ (Qt)
Qchar X = 'f';
int A = X.uncode();  // A = 102
 
Qchar X = 'ф';
int A = X.uncode();  // A = 1092






Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Old от Март 11, 2014, 23:50
Для этого нужно решить в какой кодировке вы хотите получить этот код.


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Alexu007 от Март 12, 2014, 00:03
В виндосовской.


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Old от Март 12, 2014, 00:05
В виндосовской.
Используйте QTextCodec, он для этого специально предназначен.


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Alexu007 от Март 13, 2014, 08:31
А как лучше сделать побайтовый доступ к файлу, чтобы чтение-запись быстрее работали? Я использую старые добрые:

Код
C++ (Qt)
fread (&read_byte, sizeof(char), 1, inpf);
fwrite(&write_byte, sizeof(char), 1, outf);


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Old от Март 13, 2014, 08:40
А как лучше сделать побайтовый доступ к файлу, чтобы чтение-запись быстрее работали? Я использую старые добрые:
Например, QTextStream. Ему можно сразу указать кодек для той кодировки, в которой лежат данные в этом файле.


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Alexu007 от Март 13, 2014, 09:02
Не, мне не нужен кодек. Я хочу шифровать любые файлы - не только данные. Это может быть и ехе-шник и вообще что угодно. Они же все из байтов состоят. Поэтому мне нужно читать за раз определённое количество байт - поток для этого подходит?


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Old от Март 13, 2014, 09:42
Не, мне не нужен кодек. Я хочу шифровать любые файлы - не только данные. Это может быть и ехе-шник и вообще что угодно. Они же все из байтов состоят. Поэтому мне нужно читать за раз определённое количество байт - поток для этого подходит?
Подходит, но проще использовать QFile.


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: OKTA от Март 13, 2014, 09:45
Если вопрос в шифровании, то кодировки-то тут при чем? Когда работаешь именно с байтами, никакие кодировки не нужны - шифруешь байты, дешифруешь байты... Если же нужен поток, то лучше QDataStream.

Reading and writing raw binary data
You may wish to read/write your own raw binary data to/from the data stream directly. Data may be read from the stream into a preallocated char * using readRawData(). Similarly data can be written to the stream using writeRawData(). Note that any encoding/decoding of the data must be done by you.
A similar pair of functions is readBytes() and writeBytes(). These differ from their raw counterparts as follows: readBytes() reads a quint32 which is taken to be the length of the data to be read, then that number of bytes is read into the preallocated char *; writeBytes() writes a quint32 containing the length of the data, followed by the data. Note that any encoding/decoding of the data (apart from the length quint32) must be done by you.


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Alexu007 от Март 13, 2014, 14:52
Кое-какие тексты тоже шифровать приходится, например имя файла - я пишу прогу, которая будет шифровать и сам файл и его имя, и на выходе будет выдавать что-то вроде: "keffmznimkkasvwsrenz.320". А при расшифровке восстанавливать и исходный файл и имя. С этим и вышла заминка, с латинскими именами файлов всё работало, с русскими лажала.

В общем то я уже всё переделал, вопрос только в скорости чтения-записи с диска. Я пока реализовал самый простой вариант: чтение-запись по 1 байту.


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: OKTA от Март 13, 2014, 15:29
а какой алгоритм шифрования?


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Old от Март 13, 2014, 15:32
Я пока реализовал самый простой вариант: чтение-запись по 1 байту.
Ну это не очень хорошее решение. Лучше читайте сразу блоками, например, килобайт так по 32 или 64, обрабатывайте и сохраняйте.


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: OKTA от Март 13, 2014, 15:38
Если шифр потоковый, то побайтово читать и писать мне кажется будет оптимальнее. Если же блочный, то по размеру блока конечно.


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Old от Март 13, 2014, 15:44
Если шифр потоковый, то побайтово читать и писать мне кажется будет оптимальнее. Если же блочный, то по размеру блока конечно.
Не имеет значения какой шифр. :)
Всегда будет оптимальней получать от ядра большой блок данных, чем один байт.


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: OKTA от Март 13, 2014, 15:48
Да, согласен  :)


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Alexu007 от Март 13, 2014, 21:36
Шифрование побайтовое примитивное, но задачи и не ставится зашифровать абсолютно. Достаточно, что из осмысленного файла будет мешанина байт -  это я уже реализовал.  По поводу записи/чтения - если по байту, не стоит вопроса конца файла - читаем до !EOF. Если читать блоками - последний блок наверняка будет заполнен не полностью (файл не будет кратен), нужно это программно отслеживать, особенно при записи. Ну, сами понимаете. Это может быстрее, но требует дополнительных телодвижений програмиста.

Основное требование: дешифрованный файл 100% должен соответствовать исходному.


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Old от Март 13, 2014, 21:39
Это может быстрее, но требует дополнительных телодвижений програмиста.
Да нет там никаких дополнительных телодвижений.
Простите, но это какие то детские причины. ;)

От проседания производительности вас спасает fread/fwrite, которые буферезированы под капотом. :)


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: OKTA от Март 13, 2014, 23:30
Если размер последнего блока не совпадает с размером стандартного блока, с которым работает шифр, то используют паддинг, например очень простой и понятный -
http://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7
Old прав. На маленьких файлах разницы не заметишь в побайтовом-поблочном чтении, но чем больше файл и чем больше их количество, тем заметнее будет разница.


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Alexu007 от Март 14, 2014, 07:21
Да нет там никаких дополнительных телодвижений.
Простите, но это какие то детские причины. ;)
Ну как же? Сейчас я читаю/записываю файл просто по байту до конца файла:

Код
C++ (Qt)
   // цикл шифрования
   while(1)
      {
      fread (&read_byte, sizeof(char), 1, inpf);
      if (feof(inpf)) break;
 
      write_byte = fn_Shifr_byte(read_byte);
 
      fwrite (&write_byte, sizeof(char), 1, outf);
      }


Допустим я начну читаю его блоками по 1024 байта. Последний блок почти всегда будет заполнен не полностью - нужно это отслеживать. И при записи последний блок нужно добавлять не полностью.

Конечно на самом деле ничего не читается "по байту". Чтение/запись неявно буферизуется либо самой программой, либо виндой. Вот и интересно, чтение блоками даст выигрыш в скорости?


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: OKTA от Март 14, 2014, 07:32
Optimum buffer size is related to a number of things: file system block size, CPU cache size and cache latency.

Most file systems are configured to use block sizes of 4096 or 8192. In theory, if you configure your buffer size so you are reading a few bytes more than the disk block, the operations with the file system can be extremely inefficient (i.e. if you configured your buffer to read 4100 bytes at a time, each read would require 2 block reads by the file system). If the blocks are already in cache, then you wind up paying the price of RAM -> L3/L2 cache latency. If you are unlucky and the blocks are not in cache yet, the you pay the price of the disk->RAM latency as well.

This is why you see most buffers sized as a power of 2, and generally larger than (or equal to) the disk block size. This means that one of your stream reads could result in multiple disk block reads - but those reads will always use a full block - no wasted reads.

Now, this is offset quite a bit in a typical streaming scenario because the block that is read from disk is going to still be in memory when you hit the next read (we are doing sequential reads here, after all) - so you wind up paying the RAM -> L3/L2 cache latency price on the next read, but not the disk->RAM latency. In terms of order of magnitude, disk->RAM latency is so slow that it pretty much swamps any other latency you might be dealing with.

So, I suspect that if you ran a test with different cache sizes (haven't done this myself), you will probably find a big impact of cache size up to the size of the file system block. Above that, I suspect that things would level out pretty quickly.

There are a ton of conditions and exceptions here - the complexities of the system are actually quite staggering (just getting a handle on L3 -> L2 cache transfers is mind bogglingly complex, and it changes with every CPU type).

This leads to the 'real world' answer: If your app is like 99% out there, set the cache size to 8192 and move on (even better, choose encapsulation over performance and use BufferedInputStream to hide the details). If you are in the 1% of apps that are highly dependent on disk throughput, craft your implementation so you can swap out different disk interaction strategies, and provide the knobs and dials to allow your users to test and optimize (or come up with some self optimizing system).


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Old от Март 14, 2014, 07:53
Ну как же?
Пишу код прямо здесь, поэтому могут быть опечатки. :)
Код
C++ (Qt)
QFile in( ... );
QFile out( ... );
 
// Открываем файлы
 
while( !in.atEnd() )
{
   QByteArray src = in.read( 1024 );
   QByteArray dst = coded_buffer( src );
   out.write( dst );
}
 

Код
C++ (Qt)
QByteArray coded_buffer( const QByteArray &src )
{
   const int sz = src.size();
   QByteArray result( sz, 0 );
   for( int i = 0; i < sz; ++i )
   {
        // Кодируем
   }
 
   return result;
}
 

Конечно на самом деле ничего не читается "по байту".
Да, fread буферизирован сам по себе.
Но если бы вы использовали обычный read, то скорость упала бы значительно.


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Alexu007 от Март 14, 2014, 13:47
Спасибо за помощь. Попробую и ваш вариант - насколько окажется быстрее.


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Alexu007 от Март 16, 2014, 08:12
Ваш вариант быстрее минимум в 2 раза. В связи с чем возник следующий вопрос:

1. как втиснуть int в 4 байта, ну например в quint8 A[4] - так чтобы была возможна, например, побайтовая запись в файл? Напрямую же не получится присвоить?

2. как проще этот int вытащить обратно из байтов?


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Old от Март 16, 2014, 08:41
1. как втиснуть int в 4 байта, ну например в quint8 A[4] - так чтобы была возможна, например, побайтовая запись в файл? Напрямую же не получится присвоить?
2. как проще этот int вытащить обратно из байтов?
Вы хотите читать кусок файла в QByteArray, а потом разбирать его на инты?
Тогда лучше воспользоваться для этого QDataStream.


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Igors от Март 16, 2014, 09:47
1. как втиснуть int в 4 байта, ну например в quint8 A[4] - так чтобы была возможна, например, побайтовая запись в файл? Напрямую же не получится присвоить?
Да чего ж не получится
Код
C++ (Qt)
union MyInt {
int i;
quint8 a[4];
};
 
MyInt test;
test.i = 44;
stream << test.a[0] << ...
 
Или даже так
Код
C++ (Qt)
int i = 5;
quint8 * dummy = (quint8 *) &i;   // или reinterpret
 

Не очень ясно чего Вы хотите добиться


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Old от Март 16, 2014, 09:49
Да чего ж не получится
С byte order могут случиться неприятности. Файл на разных платформах могут попробовать открыть.


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Igors от Март 16, 2014, 10:23
С byte order могут случиться неприятности. Файл на разных платформах могут попробовать открыть.
После перехода на Intel Mac (где-то в районе 2006) "большая индиана" как бы уже "дань истории", затрудняюсь привести пример такой платформы. Хотя по-прежнему считается хорошим тоном хранить данные на диске в big endian.

Возвращаясь к теме: не связывайтесь с fread/fwrite, будете латать долго и все равно будет плохо. Используйте QDataStream, а если нужно что-то с байтами, то выливайте напр в QByteArray и там уже резвитесь


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Old от Март 16, 2014, 10:33
После перехода на Intel Mac (где-то в районе 2006) "большая индиана" как бы уже "дань истории", затрудняюсь привести пример такой платформы.
То что вы не знаете таких платформ, не означает что их нет. Пример ARM - они bi. :) И хоть в большинстве своем их запускают в little, но big до сих пор очень возможен с увеличением популярности армов.

Хотя по-прежнему считается хорошим тоном хранить данные на диске в big endian.
Как это соотносится с вашими примерами с union? Или вы продемонстрировали, что знаете как работает union?


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Igors от Март 16, 2014, 12:04
Как это соотносится с вашими примерами с union? Или вы продемонстрировали, что знаете как работает union?
Не заводитесь, я просто ответил на вопрос  :)


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Old от Март 16, 2014, 12:12
Не заводитесь, я просто ответил на вопрос  :)
Да, неправильно. ;)
Вот мне и стало интересно: для чего советовать одно, а самому делаете наоборот. :)
Ну да ладно, это не вопрос. :)


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Alex Custov от Март 16, 2014, 13:33
Пример ARM - они bi. :) И хоть в большинстве своем их запускают в little, но big до сих пор очень возможен с увеличением популярности армов.

Я даже больше скажу, есть АРМы с mixed endian, я для таких как раз писал бинарный ввод/вывод данных ::)


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Alexu007 от Март 16, 2014, 14:02
Не очень ясно чего Вы хотите добиться

Мне нужно в QByteArray записать несколько int. То есть int занимает 4 байта, вот эти 4 байта и записать в QByteArray, а QByteArray дальше записать в файл. Потом соответственно прочитать из файла и восстановить исходный int.

В fread/fwrite такой проблемы не было, я в файл записывал sizeof(byte) и где нужно sizeof(int).

Не, конечно я могу сделать "по науке", т.е int & 0x000000FF - получить младший байт из инта, потом со сдвигом вправо вытащить остальные - и потом так же туда обратно засунуть. Я спрашиваю - нет ли способа попроще, чтобы сразу из int в QByteArray и наоборот?


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Old от Март 16, 2014, 14:40
Я спрашиваю - нет ли способа попроще, чтобы сразу из int в QByteArray и наоборот?
Есть. Это QDataStream. :)


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Igors от Март 16, 2014, 14:48
Вот мне и стало интересно: для чего советовать одно, а самому делаете наоборот. :)
Автор не обязан следовать собственным рекомендациям, они пишутся для других  :)
Лучше сначала ответить на прямой вопрос ТС, а затем уже "рекомендовать" стоит ли так делать, не лучше ли и.т.п.

Ладно, есть у меня большая задача к которой скоро надо вернуться (визуализация пены). Если есть желание там ко мне попридираться - оживлю тему, может там извлеку что-то из Вас. А так гонять порожняк неинтересно  :)

Мне нужно в QByteArray записать несколько int. То есть int занимает 4 байта, вот эти 4 байта и записать в QByteArray, а QByteArray дальше записать в файл. Потом соответственно прочитать из файла и восстановить
"Неправильный" ответ  :)
Код
C++ (Qt)
int val = 7;
QByteArray ba("test");
ba.append((char *) &val, sizeof(val));
 
Хотя это и будет работать - потом трудно читать. Правильно навесить QDataStreаm и все делать в нем
Код
C++ (Qt)
int val = 7;
QByteArray ba;
QDataStream strm(&ba, QIODevice::WriteOnly);
strm << val;
 
При этом "ba" заполняется данными. Читать так же, только ReadOnly и >>


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Old от Март 16, 2014, 14:50
может там извлеку что-то из Вас. А так гонять порожняк неинтересно  :)
Врядли. :)
Помните ваши же слова про "забесплатно"... Вот, вы не сможете себе позволить меня. :)

Хотя это и будет работать - потом трудно читать.
Нет, правильно не будет и не по причине "трудно читать".
Это может работать правильно только на некоторых платформах.


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Igors от Март 16, 2014, 16:12
Вот, вы не сможете себе позволить меня. :)
А какая от Вас польза чтобы я Вас "позволял"?  :)


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Alexu007 от Март 16, 2014, 16:15
Господа Old и Igors, спасибо за помощь.


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Old от Март 16, 2014, 16:21
А какая от Вас польза чтобы я Вас "позволял"?  :)

Если есть желание там ко мне попридираться

Да, вы как всегда противоречивы. :)
Польза в том, что я к вам "придираюсь", а вы учитесь. Иначе зачем вы это просите. :)


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Igors от Март 16, 2014, 17:35
Польза в том, что я к вам "придираюсь", а вы учитесь. Иначе зачем вы это просите. :)
Не припоминаю чтобы я у Вас что-то "просил", и вообще, не увлекайтесь ролью учителя  :)
Я предложил обсудить (вот правильное выражение) вещи посложнее. Ну на нет и суда нет.


Название: Re: Как поместить в int 8-битный код русского символа?
Отправлено: Old от Март 16, 2014, 17:42
Не припоминаю чтобы я у Вас что-то "просил"
Неее, вы уже не просили, вы хотели:
может там извлеку что-то из Вас. А так гонять порожняк неинтересно  :)
Но нет. :)

и вообще, не увлекайтесь ролью учителя  :)
Хотите что бы я оставил это вам? Но простите, в очередной раз слушать истории о финдреплейсах и векторах лично мне уже наскучило. Подтяните знания - будьте интересней.