Как вывести двоичный файл как строковый литерал C/C++?

Существует много инструментов, которые Вы могли использовать, чтобы сделать это. Вот решение в жемчуге.

На командной строке:

perl -p -e 's/^ *//; s/ *$//; chomp' < FILE > OUTFILE

где Вы заменяете FILE с названием файла и OUTFILE с новым файлом Вы хотите вывод, записанный в. Не используйте то же имя файла для обоих.

Что это делает: perl -p запускает скрипт жемчуга на каждой строке входа, это получает и пишет результат в вывод. Вы устанавливаете ввод и вывод с < и > операторы в файлы Вы хотите. Сам сценарий следует -e опция и делает три замены.

s/^ *//: замените любым количеством пробелов (пространство, звезда) в начале строки (^) ни с чем (команда s/this/that/ изменения this кому: that). Если Вы ожидаете иметь Символы табуляции вместо пробелов, сделать s/^[ \t]*// который заменяет далеко любым количеством пробелов или вкладок (\t).

s/ *$//: то же, но в конце строки ($).

chomp: perl-говорите за удаление разрыва строки в конце строки.

39
27.12.2014, 08:40
6 ответов

Вы можете почти делать все, что хотите, с помощью hexdump, но я не могу понять, как получить кавычки и одинарные обратные слеши в строке форматирования. Поэтому я делаю небольшую постобработку с помощью sed. В качестве бонуса, я также отступил от каждой строки на 4 пробела. :)

hexdump -e '16/1 "_x%02X" "\n"' filename | sed 's/_/\\/g; s/.*/    "&"/'

Edit

Как отметил Cengiz Can, выше командная строка не справляется с короткими строками данных. Итак, вот новая улучшенная версия:

hexdump -e '16/1 "_x%02X" "\n"' filename | sed 's/_/\\/g; s/\\x  //g; s/.*/    "&"/'

Как Malvineous упоминает в комментариях, нам также нужно передать опцию -v verbose в hexdump, чтобы предотвратить сокращение длинных отрезков одинаковых байтов до *.

hexdump -v -e '16/1 "_x%02X" "\n"' filename | sed 's/_/\\/g; s/\\x  //g; s/.*/    "&"/'
10
27.01.2020, 19:35

XXD хорош, но результат является очень многословным и принимает много места для хранения.

Вы можете достичь практически одинакового использования objcopy ; например

objcopy --input binary \
    --output elf32-i386 \
    --binary-architecture i386 foo foo.o

Тогда ссылка foo.o в вашу программу и просто используйте следующие символы:

00000550 D _binary_foo_end
00000550 A _binary_foo_size 
00000000 D _binary_foo_start

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

unsigned char* ptr = _binary_foo_start;
int i;
for (i = 0; i < _binary_foo_size; i++, ptr++)
   putc(*ptr);

​​Недостатная связь состоит в том, что вам необходимо указать свою целевую архитектуру, чтобы сделать файл объекта совместимого, и это может не быть тривиальным в вашей системе сборки.

3
27.01.2020, 19:35

Флаг -c средства распаковки извлекает файлы на stdout/screen , поэтому никакие файлы фактически не записываются на диск и, следовательно, опция -d бессмысленна - она также может объяснить странные символы, которые вы видите в терминале Возможно, вы думаете об модификаторе -C ( использование без учета регистра )?

Вместо использования grep , вероятно, вы хотите предоставить необязательный список архивных членов, которые будут обрабатываться после файла zipfile: также, вероятно, вам потребуется использовать разделители пути / в стиле Unix, даже если файл zipfile является системой Windows.

Наконец, «/~/Music », вероятно, будет интерпретироваться как буквальный абсолютный путь; Вам, вероятно, потребуется ~/Music/ или «$ HOME/Music/» - последняя форма более легко модифицируется для целевых каталогов с местами в них, например, « $ HOME/My Music/»

unzip -C "$file" '*/Username/Music/*' -d "$HOME/Music/"

Однако обратите внимание, что это, вероятно, приведет к такой структуре папок, как ~/Music/Username/Music/somefile AFAIK unzip не обладает той же гибкостью, что и некоторые реализации tar , однако может потребоваться просмотреть модификатор -j .

-121--217551-

Запустите service apache2 restart . Появится любое сообщение об ошибке (обычно служба запускает конфигурационный тест перед остановкой и запуском apache)

-121--34181-

xxd имеет для этого режим. Параметр -i / -include будет иметь значение

, выводимое в формате C, включая стиль файла. Полное определение статического массива записывается (по имени входного файла), если xxd не считывается из stdin.

Можно выгрузить файл под именем # include d, а затем просто получить доступ к foo , как к любому другому массиву символов (или связать его). Он также включает объявление длины массива.

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

$ xxd --include foo
unsigned char foo[] = {
  0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64,
  0x21, 0x0a, 0x0a, 0x59, 0x6f, 0x75, 0x27, 0x72, 0x65, 0x20, 0x76, 0x65,
  0x72, 0x79, 0x20, 0x63, 0x75, 0x72, 0x69, 0x6f, 0x75, 0x73, 0x21, 0x20,
  0x57, 0x65, 0x6c, 0x6c, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x2e, 0x0a
};
unsigned int foo_len = 47;

xxd является, что несколько странно, частью распределения vim , так что вы, вероятно, уже есть. Если нет, то вы получаете его - вы также можете построить инструмент самостоятельно из vim источника.

68
27.01.2020, 19:35

Это короткая утилита, которую я написал и которая, по сути, делает то же самое (изначально размещенная на Stack Overflow):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LENGTH 80

int main(void)
{
    FILE *fout = fopen("out.txt", "w");

    if(ferror(fout))
    {
        fprintf(stderr, "Error opening output file");
        return 1;
    }
    char init_line[]  = {"char hex_array[] = { "};
    const int offset_length = strlen(init_line);

    char offset_spc[offset_length];

    unsigned char buff[1024];
    char curr_out[64];

    int count, i;
    int line_length = 0;

    memset((void*)offset_spc, (char)32, sizeof(char) * offset_length - 1);
    offset_spc[offset_length - 1] = '\0';

    fprintf(fout, "%s", init_line);

    while(!feof(stdin))
    {
        count = fread(buff, sizeof(char), sizeof(buff) / sizeof(char), stdin);

        for(i = 0; i < count; i++)
        {
            line_length += sprintf(curr_out, "%#x, ", buff[i]);

            fprintf(fout, "%s", curr_out);
            if(line_length >= MAX_LENGTH - offset_length)
            {
                fprintf(fout, "\n%s", offset_spc);
                line_length = 0;
            }
        }
    }
    fseek(fout, -2, SEEK_CUR);
    fprintf(fout, " };");

    fclose(fout);

    return EXIT_SUCCESS;
}
0
27.01.2020, 19:35

Должно быть именно то, что вы просили:

hexdump -v -e '"\\" "x" 1/1 "%02X"' file.bin ; echo
2
27.01.2020, 19:35

Если вы используете Python, загрузите его в переменную "buff" и используйте что-то вроде этого:

buff2 = buff.encode("hex")
print ("0x"+", 0x".join([buff2[i:i+2] for i in range(0,len(buff2),2)]))
0
27.01.2020, 19:35

Теги

Похожие вопросы