Есть ли способ включить весь текстовый файл в виде строки в программу C во время компиляции?
что-то вроде:
file.txt:
This is a little text file
main.c:
#include <stdio.h> int main(void) { #blackmagicinclude("file.txt", content) /* equiv: char[] content = "This is\na little\ntext file"; */ printf("%s", content); }
получение небольшой программы, которая печатает на stdout «Это небольшой текстовый файл»
На данный момент я использовал хакерский скрипт на Python, но он уродлив и ограничен только одним именем переменной, вы можете подсказать мне другой способ сделать это?
c
include
c-preprocessor
Брайан Томпсетт - 莱恩
источник
источник
Ответы:
Я бы предложил использовать для этого (unix util) xxd . вы можете использовать это так
выходы:
источник
xxd
, как говорится в ответе. имя массива - это имя входного файла. если вы передаете данные по конвейеру вместо использования входного файла, вместо этого вы получите список шестнадцатеричных значений (без объявления массива или переменной len).xxd -i file.txt | sed 's/\([0-9a-f]\)$/\0, 0x00/' > file.h
Вопрос касался C, но если кто-то попытается сделать это с помощью C ++ 11, то это можно будет сделать с небольшими изменениями во включенном текстовом файле благодаря новым необработанным строковым литералам :
В C ++ сделайте это:
В текстовом файле сделайте следующее:
Таким образом, в верхней части файла должен быть только префикс, а в конце - суффикс. Между ними вы можете делать то, что хотите, никакого специального экранирования не требуется, если вам не нужна последовательность символов
)"
. Но даже это может сработать, если вы укажете свой собственный ограничитель:источник
1+R"...
в качестве начального разделителя вместоR"...
, а затем добавляете перед ним новую строкуLine 1
. Это преобразует выражение из массива в указатель, но это не проблема, поскольку вы инициализируете указатель, а не массив.У вас есть две возможности:
\
), escape-"
символы и другие символы. Проще просто написать небольшую программу для преобразования байтов в такую последовательность'\xFF', '\xAB', ...., '\0'
(или использовать инструмент unix,xxd
описанный в другом ответе, если он у вас есть!):Код:
(не проверено). Затем сделайте:
Где data.h создается
источник
char my_file[] = { #include my_large_file.h };
Спасибо!bin2c
это не то же самое bin2c, что и от debianhxtools
, будьте осторожныbin2c -H myoutput.h myinput1.txt myinputN.txt
хорошо, вдохновленный постом Дэмина, я протестировал следующий простой пример:
a.data:
test.c:
gcc -E test.c вывод:
Итак, он работает, но требуются данные, заключенные в кавычки.
источник
Мне нравится ответ Каяра. Однако, если вы не хотите касаться входных файлов и если вы используете CMake , вы можете добавить в файл последовательности символов-разделителей. Например, следующий код CMake копирует входные файлы и соответствующим образом обертывает их содержимое:
Затем включите в C ++ вот так:
источник
Вы можете сделать это, используя
objcopy
:Теперь у вас есть объектный файл, который вы можете связать со своим исполняемым файлом, который содержит символы для начала, конца и размера содержимого
myfile.txt
.источник
Вам нужна моя
xtr
утилита, но вы можете сделать это с помощьюbash script
. Это сценарий, который я называюbin2inc
. Первый параметр - это имя результатаchar[] variable
. Второй параметр - это имяfile
. Результатом является Cinclude file
с содержимым файла, закодированным (в нижнем регистреhex
) как указанное имя переменной. Этоchar array
естьzero terminated
, а длина данных хранится в$variableName_length
ВЫ МОЖЕТЕ ПОЛУЧИТЬ XTR ЗДЕСЬ xtr (character eXTRapolator) является GPLV3
источник
Если вы готовы прибегнуть к некоторым грязным уловкам, вы можете проявить творческий подход с необработанными строковыми литералами и
#include
для определенных типов файлов.Например, предположим, что я хочу включить несколько сценариев SQL для SQLite в свой проект, и я хочу получить подсветку синтаксиса, но не хочу никакой специальной инфраструктуры сборки. У меня может быть этот файл,
test.sql
который является действительным SQL для SQLite, где--
начинается комментарий:И тогда в моем коде на C ++ я могу иметь:
Результат:
Или включить некоторый код Python из файла,
test.py
который является допустимым сценарием Python (потому что#
запускает комментарий в Python иpass
не работает):А затем в коде C ++:
Что выведет:
Должна быть возможность проделывать аналогичные приемы для различных других типов кода, которые вы, возможно, захотите включить в виде строки. Я не уверен, хорошая это идея или нет. Это своего рода изящный прием, но, вероятно, не то, что вам нужно в реальном производственном коде. Впрочем, для хакерского проекта на выходных может подойти.
источник
Я повторно реализовал xxd в python3, устранив все неприятности xxd:
unsigned
в массив.Вот сценарий, отфильтрованный сам по себе, чтобы вы могли видеть, что он делает:
pyxxd.c
Использование (это извлекает сценарий):
источник
Что может сработать, если вы сделаете что-то вроде:
Конечно, вам нужно быть осторожным с тем, что на самом деле находится в файле , убедитесь, что нет двойных кавычек, что все соответствующие символы экранированы и т. Д.
Поэтому может быть проще, если вы просто загрузите текст из файла во время выполнения или встроите текст непосредственно в код.
Если вам по-прежнему нужен текст в другом файле, он может быть там, но он должен быть представлен там в виде строки. Вы бы использовали код, как указано выше, но без двойных кавычек. Например:
file.txt
main.cpp
Итак, в основном это строка стиля C или C ++ в текстовом файле, который вы включаете. Это сделало бы код более аккуратным, потому что в начале файла не так много текста.
источник
Даже если это можно сделать во время компиляции (я не думаю, что это возможно в целом), текст, скорее всего, будет предварительно обработанным заголовком, а не дословно содержимым файлов. Я ожидаю, что вам придется загрузить текст из файла во время выполнения или выполнить неприятную работу вырезания и вставки.
источник
Ответ Хастуркуна с использованием опции xxd -i превосходен. Если вы хотите включить процесс преобразования (текст -> шестнадцатеричный включаемый файл) непосредственно в вашу сборку, инструмент / библиотека hexdump.c недавно добавили возможность, аналогичную опции -i xxd (она не дает вам полного заголовка - вам нужен чтобы предоставить определение массива символов, но это имеет то преимущество, что позволяет вам выбрать имя массива символов):
http://25thandclement.com/~william/projects/hexdump.c.html
Эта лицензия намного более "стандартна", чем xxd, и очень либеральна - пример ее использования для встраивания файла инициализации в программу можно увидеть в файлах CMakeLists.txt и scheme.c здесь:
https://github.com/starseeker/tinyscheme-cmake
Есть свои плюсы и минусы как для включения сгенерированных файлов в деревья исходных текстов, так и для пакетных утилит - как с этим справиться, будет зависеть от конкретных целей и потребностей вашего проекта. hexdump.c открывает возможность связывания этого приложения.
источник
Я думаю, что это невозможно только с компилятором и препроцессором. gcc позволяет это:
Но, к сожалению, не это:
Ошибка:
источник
/etc/hostname
способ встраивания имени машины сборки в строку, которая (даже если бы она сработала) не была бы переносимый, поскольку в Mac OS X нет файла/etc/hostname
. Обратите внимание, что при использовании имен макросов, которые начинаются с подчеркивания, за которым следует заглавная буква, используется имя, зарезервированное для реализации, а это A Bad Thing ™.Почему бы не связать текст с программой и не использовать его как глобальную переменную! Вот пример. Я подумываю об использовании этого для включения файлов шейдеров Open GL в исполняемый файл, поскольку шейдеры GL необходимо компилировать для графического процессора во время выполнения.
источник
У меня были похожие проблемы, и для небольших файлов вышеупомянутое решение Йоханнеса Шауба подействовало для меня как шарм.
Однако для файлов, которые немного больше, возникали проблемы с ограничением массива символов компилятора. Поэтому я написал небольшое приложение-кодировщик, которое преобразует содержимое файла в массив 2D-символов, состоящий из блоков одинакового размера (и, возможно, дополняющих нулей). Он создает выходные текстовые файлы с данными 2D-массива, например:
где 4 - это фактически переменная MAX_CHARS_PER_ARRAY в кодировщике. Файл с результирующим кодом C, называемый, например, «main_js_file_data.h», затем можно легко встроить в приложение C ++, например, следующим образом:
Вот исходный код кодировщика:
источник
Эта проблема меня раздражала, и xxd не работает для моего варианта использования, потому что из-за этого переменная называлась чем-то вроде __home_myname_build_prog_cmakelists_src_autogen, когда я пытался ее скрипт, поэтому я сделал утилиту для решения этой точной проблемы:
https://github.com/Exaeta/brcc
Он генерирует исходный файл и файл заголовка и позволяет вам явно указать имя каждой переменной, чтобы затем вы могли использовать их через std :: begin (имя массива) и std :: end (имя массива).
Я включил его в свой проект cmake так:
С небольшими изменениями, я полагаю, его можно было бы заставить работать и для C.
источник
в xh
в main.c
должен делать свою работу.
источник