Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.83/6: Рейтинг темы: голосов - 6, средняя оценка - 4.83
0 / 0 / 0
Регистрация: 12.06.2014
Сообщений: 17

Найти UTF-16 строку в бинарном файле

25.06.2014, 11:38. Показов 1542. Ответов 13
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте,

Есть вот такая процедура для поиска и замены строк в бинарном файле. Применяю ее на обычном PE-файле. Проблема в том, что строки она не находит, хотя аналогичный вариант с narrow char работает прекрасно.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
void scrambleWide(const char *filename, const char key) 
{
    std::wfstream ifs(filename, ios::binary|ios::out|ios::in);
    if(!ifs.is_open())
    {
        printf("Unable to open file in wide mode...\n");
        return;
    }
 
    ifs.imbue(std::locale(ifs.getloc(), new std::codecvt_utf8<wchar_t>));
 
    std::wstring str((std::istreambuf_iterator<wchar_t>(ifs)), std::istreambuf_iterator<wchar_t>());
 
    std::wsmatch matches;
    std::wregex rgx (L"(START_MARK)(.*?)(END_MARK)");
    std::wstring fullMatch, stringMatch;
    size_t appendSize;
 
    while (std::regex_search (str,matches,rgx)) {
        printf("Found match: %s at position: %d...", matches[2].str().c_str(), matches.position(2));
 
        fullMatch = matches[0].str(); 
        stringMatch = matches[2].str();
        appendSize = fullMatch.size() - stringMatch.size(); 
 
        stringMatch.append(appendSize, L'\0');
 
        ifs.seekp(matches.position(0));
        ifs.write(stringMatch.c_str(), stringMatch.size());
 
        printf("replaced\n");
 
        str = matches.suffix().str();
    }
    ifs.close();
}
Как ее переделать для поддержки widechar? Я думаю проблемы с локалью, но какую поставить не могу понять.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
25.06.2014, 11:38
Ответы с готовыми решениями:

Удалить строку в бинарном файле
Подскажите, пожалуйста, как удалить определенную строку из бинарного файла (.bin)? дельфи.

прочитать последнею строку в бинарном файле
как прочитать последнею строку в бинарном файле ?

Найти k-ую строчку в бинарном файле
День добрый! Подскажите, как реализовать данный алгоритм, значение К вводится с клавиатуры, нам задан двумерный массив. Нужно в двумерном...

13
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
25.06.2014, 17:00
Может дело просто в том, что неизвестно, где начинается строка и соответственно откуда раскодировку начинать. Ты же не в текстовом файле ищешь.
0
0 / 0 / 0
Регистрация: 12.06.2014
Сообщений: 17
25.06.2014, 23:19  [ТС]
Да нет, вряд ли. Вот такая же функция, только для обычного char, работает нормально. Тут еще строка ксорится перед возвратом на место, но это не принципиально.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
bool scramble(const char *filename, const char key) 
{
    printf("Running in narrow char mode...\n");
    std::fstream ifs(filename, ios::binary|ios::out|ios::in);
    std::string str((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
 
    std::smatch matches;
    std::regex rgx ("(START_MARK)(.*?)(END_MARK)");
    std::string fullMatch, stringMatch;
    size_t appendSize;
 
    bool somethingFound = false;
 
    if (std::regex_search (str,matches,rgx)) {
        somethingFound = true;
        fullMatch = matches[0].str(); 
        stringMatch = matches[2].str();
        appendSize = fullMatch.size() - stringMatch.size(); 
 
        for(size_t i = 0; i < stringMatch.size(); i++)
        {
            stringMatch[i] ^= key;
        }
 
        stringMatch.append(appendSize, '\0');
 
        printf("Found string: %s at position: %d\n", stringMatch.c_str(), matches.position(0));
 
        ifs.seekp(matches.position(0));
        ifs.write(stringMatch.c_str(), stringMatch.size());
    }
 
    ifs.close();
 
    return somethingFound;
};
0
20 / 20 / 3
Регистрация: 14.06.2012
Сообщений: 95
25.06.2014, 23:56
Не имею привычки работать с wchar_t и std-аналогами функций для него, но может быть это связано с тем, что wchar_t занимает 2 байта и вы читаете в бинарном формате по два байта вместо одного? char работает небось потому, что строка запилена в PE-файле побайтово, а wchar_t аналог ищет по "двубайтово". Пересмотрите или поправьте меня, может и бред пишу
0
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
26.06.2014, 08:12
Ну так обычный char однобайтный, поэтому где бы строка не находилась, её можно найти, потому что куда ни ткни в ней, какую-то часть с любого места прочитаешь, а с двухбайтными надо ещё правильно попасть на начало пары. Как это можно сделать, если файл бинарный и неизвестно, где там вообще строки? С utf8 ещё сложнее, там тоже надо знать где начало, чтобы серии правильно потом декодировались. Не думаю, что regex сам может всё это сделать. Он рассчитан на строки, а не на кучу бинарных данных, в которых, может быть, есть строки и неизвестно где.
0
0 / 0 / 0
Регистрация: 12.06.2014
Сообщений: 17
26.06.2014, 11:23  [ТС]
Вы оба правы, в UTF-16 используется два байта на символ. И нужно правильный формат указать, что бы читались символы wchar_t. Только я не могу понять как это сделать.

У fstream есть метод imbue, который позволяет модифицировать поток под подходящую локаль. Пробовал например так, но не вкатило.
C++
1
ifs.imbue(std::locale(ifs.getloc(), new std::codecvt_utf16<wchar_t>));
Я пытаюсь модифицировать обычный PE-файл. Насколько я понимаю, там UTF-16LE внутри, но как это знание использовать ума не приложу.
0
20 / 20 / 3
Регистрация: 14.06.2012
Сообщений: 95
26.06.2014, 14:01
У меня парочка вопросов:
1) строки известны?
2) уверены, что UTF-16LE? как там кодируется число 0xAABB? (или приведите пример на известных вам данных)
Собственно это и не важно. Расширение стандартной кодировки до "двубайтовой" может происходить добавлением нулевого байта после (LE) или перед (BE) каждым байтом, после чего применяете ваш алгоритм с wchar_t к полученному массиву байт. Если стандартные средства с этим не справляются, пишите свои - заведите буфер и скопируйте туда все байты файла, после чего расширьте его, добавив нулевые байты в зависимости от вашей кодировки (лучше LE, конечно).
Оговорочка: добавление нулевого байта делается для латинских символов, для кириллицы там немного по-другому.
И ещё по поводу LE/BE - BOM там есть?
Прочитайте первые два байта, если там 0xfeff, то это big-endian, если наоборот, то little-endian, если там что-то другое, то скорее всего используется стандартный little-endian =)
0
0 / 0 / 0
Регистрация: 12.06.2014
Сообщений: 17
26.06.2014, 14:23  [ТС]
Что б было понятно, я пробую вот такой способ шифрования http://stackoverflow.com/a/7625156.

Это тестовый файл, строки известны. Вот пример строки в файле:



Very wide string: 56 00 65 00 72 00 79 00 20 00 77 00 69 00 64 00 65 00 20 00 73 00 74 00 72 00 69 00 6E 00 67 00 - судя по тому, что вы написали, это LE.

Вначале файла стандартные MZ "0x4D 0x5A", т.е. BOM нет.
0
20 / 20 / 3
Регистрация: 14.06.2012
Сообщений: 95
26.06.2014, 15:51
Подождите секундочку... А с чего вы решили, что ваш алгоритм не находит строки? Вы добавили в свой код с wchar_t следующий код:
C++
1
2
3
4
for(size_t i = 0; i < stringMatch.size(); i++)
        {
            stringMatch[i] ^= key;
        }
? Только поправочку на 2 байта сделайте, если там это не применяется автоматически
0
0 / 0 / 0
Регистрация: 12.06.2014
Сообщений: 17
26.06.2014, 20:48  [ТС]
Да нет, это ж просто xor с заданным ключом. До него не доходит выполнение. Регэксп не обнаруживает строчку. Если str предварительно инициализировать чем-нибудь подходящим, типа:

C++
1
std::wstring str (L"bla-bla-bla MARK_BEGINsomewidestringMARK_END bla-bla");
тогда норм все работает, но это, ясное дело, не содержимое файла.
0
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
26.06.2014, 21:03
Создай текстовый файл utf16 с нужной строкой и проверь на нём.
0
0 / 0 / 0
Регистрация: 12.06.2014
Сообщений: 17
28.06.2014, 16:12  [ТС]
nmcf, ну так я на нем и проверяю.

Ребят, спасибо за проявленный интерес, но тема больше не актуальна.
0
20 / 20 / 3
Регистрация: 14.06.2012
Сообщений: 95
28.06.2014, 16:13
Проблему-то решил? отпишись где собака зарыта)
0
0 / 0 / 0
Регистрация: 12.06.2014
Сообщений: 17
28.06.2014, 20:00  [ТС]
IIARTEMII, нет, не решил. Потребность пропала.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
28.06.2014, 20:00
Помогаю со студенческими работами здесь

Как найти количество элементов в бинарном файле?
Требуется записать в бинарный файл все оставшиеся числа после одиннадцатого по порядку. Предполагалось сделать это так: ...

Как найти последний элемент в бинарном файле?
Как найти последний элемент в бинарном файле?

Найти и вывести на экран продукты одной фирмы в бинарном файле
Вот функция записи void dobavit() {ofstream fot(&quot;database.txt&quot;,ios_base::binary | ios_base::app); int gt; for(int...

В заданном бинарном файле, содержащем целые числа, найти произведение положительных чисел
Помогите,пожалуйста,с заданием,учусь на психолога,а нам вот поставили информатику,в которой я ничего не понимаю :(

Найти в бинарном файле все пары точек, лежащих с точкой d на одной прямой
В файле заданы множество точек А и точка d вне его. Найти все пары точек, лежащих с точкой d на одной прямой. с++ срочно!!!


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

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Новые блоги и статьи
Вывод диалогового окна перед закрытием, если документ не проведён
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать программный контроль на предмет проведения документа. . .
Программный контроль заполнения реквизита табличной части документа
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать контроль заполнения реквизита "ПричинаСписания". . .
wmic не является внутренней или внешней командой
Maks 02.04.2026
Решение: DISM / Online / Add-Capability / CapabilityName:WMIC~~~~ Отсюда: https:/ / winitpro. ru/ index. php/ 2025/ 02/ 14/ komanda-wmic-ne-naydena/
Программная установка даты и запрет ее изменения
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: при создании документов установить период списания автоматически. . .
Вывод данных в справочнике через динамический список
Maks 01.04.2026
Реализация из решения ниже выполнена на примере нетипового справочника "Спецтехника" разработанного в конфигурации КА2. Задача: вывести данные из ТЧ нетипового документа. . .
Программное заполнения текстового поля в реквизите формы документа
Maks 01.04.2026
Алгоритм из решения ниже реализован на нетиповом документе "ВыдачаОборудованияНаСпецтехнику" разработанного в конфигурации КА2, в дополнении к предыдущему решению. На форме документа создается. . .
К слову об оптимизации
kumehtar 01.04.2026
Вспоминаю начало 2000-х, университет, когда я писал на Delphi. Тогда среди программистов на форумах активно обсуждали аккуратную работу с памятью: нужно было следить за переменными, вовремя. . .
Идея фильтра интернета (сервер = слой+фильтр).
Hrethgir 31.03.2026
Суть идеи заключается в том, чтобы запустить свой сервер, о чём я если честно мечтал давно и давно приобрёл книгу как это сделать. Но не было причин его запускать. Очумелые учёные напечатали на. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru