Existe-t-il un moyen d'inclure un fichier texte entier sous forme de chaîne dans un programme C au moment de la compilation?
quelque chose comme:
file.txt:
This is a little text file
principal c:
#include <stdio.h> int main(void) { #blackmagicinclude("file.txt", content) /* equiv: char[] content = "This is\na little\ntext file"; */ printf("%s", content); }
obtenir un petit programme qui imprime sur stdout "Ceci est un petit fichier texte"
Pour le moment, j'ai utilisé un script python hackish, mais c'est moche et limité à un seul nom de variable, pouvez-vous me dire une autre façon de le faire?
c
include
c-preprocessor
Brian Tompsett - 汤 莱恩
la source
la source
Réponses:
Je suggérerais d'utiliser (unix util) xxd pour cela. tu peux l'utiliser comme ça
les sorties:
la source
xxd
, comme le dit la réponse. le nom du tableau est le nom du fichier d'entrée. si vous transférez des données au lieu d'utiliser un fichier d'entrée, vous obtiendrez une liste de valeurs hexadécimales à la place (sans la déclaration de tableau ou la variable len).xxd -i file.txt | sed 's/\([0-9a-f]\)$/\0, 0x00/' > file.h
La question concernait C mais au cas où quelqu'un essaie de le faire avec C ++ 11, cela peut être fait avec seulement de petites modifications dans le fichier texte inclus grâce aux nouveaux littéraux de chaîne bruts :
En C ++, procédez comme suit:
Dans le fichier texte, procédez comme suit:
Il ne doit donc y avoir qu'un préfixe en haut du fichier et un suffixe à la fin de celui-ci. Entre cela, vous pouvez faire ce que vous voulez, aucun échappement spécial n'est nécessaire tant que vous n'avez pas besoin de la séquence de caractères
)"
. Mais même cela peut fonctionner si vous spécifiez votre propre délimiteur personnalisé:la source
1+R"...
comme délimiteur de départ au lieu deR"...
, puis ajoutez une nouvelle ligne avantLine 1
. Cela transformera l'expression d'un tableau en pointeur, mais ce n'est pas vraiment un problème ici, puisque vous initialisez un pointeur, pas un tableau.Vous avez deux possibilités:
\
), de"
caractères d' échappement et d'autres pour que cela fonctionne. Plus facile d'écrire simplement un petit programme pour convertir les octets en une séquence comme'\xFF', '\xAB', ...., '\0'
(ou d'utiliser l'outil unixxxd
décrit par une autre réponse, si vous l'avez disponible!):Code:
(pas testé). Alors fais:
Où data.h est généré par
la source
char my_file[] = { #include my_large_file.h };
Merci!bin2c
n'est pas le même bin2c que celui de Debianhxtools
, attentionbin2c -H myoutput.h myinput1.txt myinputN.txt
ok, inspiré du post de Daemin, j'ai testé l'exemple simple suivant:
a. données:
test.c:
Sortie gcc -E test.c:
Cela fonctionne donc mais nécessite des données entre guillemets.
la source
J'aime la réponse de Kayahr. Cependant, si vous ne souhaitez pas toucher les fichiers d'entrée , et si vous utilisez CMake , vous pouvez ajouter les séquences de caractères de délimitation sur le fichier. Le code CMake suivant, par exemple, copie les fichiers d'entrée et encapsule leur contenu en conséquence:
Ensuite, incluez en c ++ comme ceci:
la source
Vous pouvez le faire en utilisant
objcopy
:Vous avez maintenant un fichier objet que vous pouvez lier à votre exécutable qui contient des symboles pour le début, la fin et la taille du contenu à partir de
myfile.txt
.la source
Vous avez besoin de mon
xtr
utilitaire mais vous pouvez le faire avec un fichierbash script
. C'est un script que j'appellebin2inc
. Le premier paramètre est le nom du résultatchar[] variable
. Le deuxième paramètre est le nom dufile
. La sortie est Cinclude file
avec le contenu du fichier codé (en minusculeshex
) comme nom de variable donné. Lechar array
estzero terminated
et la longueur des données est stockée dans$variableName_length
VOUS POUVEZ OBTENIR XTR ICI xtr (character eXTRapolator) est GPLV3
la source
Si vous êtes prêt à recourir à des astuces sales, vous pouvez faire preuve de créativité avec des littéraux de chaîne bruts et
#include
pour certains types de fichiers.Par exemple, disons que je veux inclure des scripts SQL pour SQLite dans mon projet et que je veux obtenir une coloration syntaxique mais je ne veux pas d'infrastructure de construction spéciale. Je peux avoir ce fichier
test.sql
qui est SQL valide pour SQLite où--
commence un commentaire:Et puis dans mon code C ++, je peux avoir:
La sortie est:
Ou pour inclure du code Python à partir d'un fichier
test.py
qui est un script Python valide (car#
démarre un commentaire en Python etpass
est un no-op):Et puis dans le code C ++:
Qui produira:
Il devrait être possible de jouer des tours similaires pour divers autres types de code que vous voudrez peut-être inclure sous forme de chaîne. Que ce soit une bonne idée ou non, je ne suis pas sûr. C'est une sorte de hack soigné, mais probablement pas quelque chose que vous voudriez dans un vrai code de production. Cela pourrait cependant convenir à un projet de hack du week-end.
la source
J'ai réimplémenté xxd en python3, corrigeant tous les ennuis de xxd:
unsigned
sur le tableau.Voici le script, filtré par lui-même, pour que vous puissiez voir ce qu'il fait:
pyxxd.c
Utilisation (ceci extrait le script):
la source
Ce qui pourrait fonctionner, c'est si vous faites quelque chose comme:
Bien sûr, vous devrez faire attention à ce qui se trouve réellement dans le fichier , en vous assurant qu'il n'y a pas de guillemets doubles, que tous les caractères appropriés sont échappés, etc.
Par conséquent, il peut être plus facile de charger simplement le texte d'un fichier au moment de l'exécution ou d'incorporer le texte directement dans le code.
Si vous vouliez toujours le texte dans un autre fichier, vous pourriez l'avoir là-dedans, mais il devrait y être représenté sous forme de chaîne. Vous utiliseriez le code comme ci-dessus, mais sans les guillemets. Par exemple:
file.txt
main.cpp
Donc, en gros, avoir une chaîne de style C ou C ++ dans un fichier texte que vous incluez. Cela rendrait le code plus net car il n'y a pas autant de texte au début du fichier.
la source
Même si cela peut être fait au moment de la compilation (je ne pense pas que cela soit possible en général), le texte serait probablement l'en-tête prétraité plutôt que le contenu des fichiers textuellement. J'espère que vous devrez charger le texte du fichier au moment de l'exécution ou faire un mauvais travail de couper-coller.
la source
La réponse de Hasturkun en utilisant l'option xxd -i est excellente. Si vous souhaitez incorporer le processus de conversion (texte -> fichier d'inclusion hexadécimal) directement dans votre build, l'outil / bibliothèque hexdump.c a récemment ajouté une fonctionnalité similaire à l'option -i de xxd (elle ne vous donne pas l'en-tête complet - vous avez besoin pour fournir la définition du tableau char - mais cela a l'avantage de vous permettre de choisir le nom du tableau char):
http://25thandclement.com/~william/projects/hexdump.c.html
Sa licence est beaucoup plus "standard" que xxd et est très libérale - un exemple de son utilisation pour intégrer un fichier init dans un programme peut être vu dans les fichiers CMakeLists.txt et scheme.c ici:
https://github.com/starseeker/tinyscheme-cmake
Il y a des avantages et des inconvénients à inclure les fichiers générés dans les arborescences sources et à regrouper les utilitaires - la façon de les gérer dépendra des objectifs et des besoins spécifiques de votre projet. hexdump.c ouvre l'option de regroupement pour cette application.
la source
Je pense que ce n'est pas possible avec le compilateur et le préprocesseur seuls. gcc permet ceci:
Mais malheureusement pas ça:
L'erreur est:
la source
/etc/hostname
une manière d'incorporer le nom de la machine de construction dans la chaîne, ce qui (même si cela fonctionnait) ne serait pas portable car Mac OS X n'a pas de fichier/etc/hostname
. Notez que l'utilisation de noms de macro commençant par un trait de soulignement suivi d'une lettre majuscule consiste à utiliser un nom réservé à l'implémentation, qui est A Bad Thing ™.Pourquoi ne pas lier le texte au programme et l'utiliser comme variable globale! Voici un exemple. J'envisage de l'utiliser pour inclure les fichiers de shader Open GL dans un exécutable car les shaders GL doivent être compilés pour le GPU au moment de l'exécution.
la source
J'ai eu des problèmes similaires, et pour les petits fichiers, la solution susmentionnée de Johannes Schaub a fonctionné comme un charme pour moi.
Cependant, pour les fichiers un peu plus volumineux, il a rencontré des problèmes avec la limite de tableau de caractères du compilateur. Par conséquent, j'ai écrit une petite application d'encodeur qui convertit le contenu du fichier en un tableau de caractères 2D de morceaux de taille égale (et éventuellement de zéros de remplissage). Il produit des fichiers texte de sortie avec des données de tableau 2D comme ceci:
où 4 est en fait une variable MAX_CHARS_PER_ARRAY dans l'encodeur. Le fichier avec le code C résultant, appelé par exemple "main_js_file_data.h" peut alors facilement être inséré dans l'application C ++, par exemple comme ceci:
Voici le code source de l'encodeur:
la source
Ce problème m'irritait et xxd ne fonctionne pas pour mon cas d'utilisation car il a fait de la variable appelée quelque chose comme __home_myname_build_prog_cmakelists_src_autogen lorsque j'ai essayé de l'écrire, j'ai donc créé un utilitaire pour résoudre ce problème exact:
https://github.com/Exaeta/brcc
Il génère un fichier source et un fichier d'en-tête et vous permet de définir explicitement le nom de chaque variable afin que vous puissiez les utiliser via std :: begin (arrayname) et std :: end (arrayname).
Je l'ai incorporé dans mon projet cmake comme ceci:
Avec de petites modifications, je suppose que cela pourrait également fonctionner pour C.
la source
dans xh
dans main.c
devrait faire le travail.
la source