"[एक सी के रूप में सी कार्यक्रम में एक पाठ फ़ाइल"]


130

क्या संकलन-समय पर 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 पर प्रिंट करता है "यह एक छोटी टेक्स्ट फ़ाइल है"

फिलहाल मैंने एक हैकिश पाइथन स्क्रिप्ट का उपयोग किया है, लेकिन यह बट-बदसूरत है और केवल एक चर नाम तक सीमित है, क्या आप मुझे इसे करने का दूसरा तरीका बता सकते हैं?


एक फ़ाइल को चार [] में पढ़ने के लिए यहां देखें। /programming/410943/reading-a-text-file-into-an-array-in-c C प्रीप्रोसेसर की मैक्रो का उपयोग करने के लिए यहां कुछ सुझाव दिए गए हैं। http://gcc.gnu.org/oniltocs/cpp/Macros.html
डैनियल ए। व्हाइट

3
तुम ऐसा क्यों करना चाहते हो? रनटाइम पर फाइल क्यों नहीं पढ़ी? (उत्तर: हो सकता है क्योंकि यह जानना मुश्किल है कि फ़ाइल रनटाइम पर कहाँ है, या शायद इसलिए कि केवल एक फ़ाइल स्थापित होनी चाहिए।)
जोनाथन लेफ़लर

या, शायद पाठ फ़ाइल केवल संकलित समय पर उपलब्ध है, जैसे स्रोत कोड।
टीएमएस

1
कभी-कभी आप विकास के समय में डेटा को अलग-अलग फ़ाइलों के रूप में एक्सेस करना चाहते हैं लेकिन आपके बाइनरी में संकलित सामग्री है। उदाहरण एक Arduino पर एक वेब सर्वर चला रहा है जिसमें स्थानीय भंडारण तक पहुंच नहीं है। आप अपनी html फ़ाइलों को उन्हें संपादित करने के लिए अलग रखना चाहते हैं, लेकिन संकलन के समय उन्हें आपके स्रोत में तार के रूप में मौजूद होना चाहिए।
जियोर्डी

जवाबों:


134

मैं इसके लिए xxd का उपयोग (यूनिक्स उपयोग) करने का सुझाव दूंगा । आप इसे इस तरह से उपयोग कर सकते हैं

$ echo hello world > a
$ xxd -i a

आउटपुट:

unsigned char a[] = {
  0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x0a
};
unsigned int a_len = 12;

18
बस एक नोट: xxd द्वारा बनाया गया char [] पूर्ण नहीं है! इसलिए मैं $ xxd -i <file.txt> file.xxd $ echo ', 0' >> file.xxd और main.c char file_content [] = {# #include "file.xxd"} में करता हूं;

2
मुझे xxd के बारे में कभी नहीं पता था। यह विस्मयकारी है!

1
@eSKay: जो सीधे आउटपुट से आता है xxd, जैसा कि उत्तर कहता है। सरणी का नाम इनपुट फ़ाइल नाम है। यदि आप इनपुट फ़ाइल का उपयोग करने के बजाय डेटा को पाइप कर रहे हैं, तो आपको इसके बजाय हेक्साडेसिमल मानों की एक सूची मिलेगी (सरणी घोषणा या लेन चर के बिना)।
हस्त्कर्ण

4
GLSL शेड्स को एम्बेड करते समय यह बहुत उपयोगी है।
लिनेलो

5
Xxd में 0x00 समाप्ति को जोड़ने का एक और तरीका है C कोड:xxd -i file.txt | sed 's/\([0-9a-f]\)$/\0, 0x00/' > file.h
vleo

104

सवाल सी के बारे में था, लेकिन अगर कोई इसे सी ++ 11 के साथ करने की कोशिश करता है, तो इसे शामिल किए गए पाठ फ़ाइल में केवल थोड़े से बदलाव के साथ किया जा सकता है, नए कच्चे स्ट्रिंग लीटर के लिए धन्यवाद :

C ++ में ऐसा करें:

const char *s =
#include "test.txt"
;

पाठ फ़ाइल में ऐसा करें:

R"(Line 1
Line 2
Line 3
Line 4
Line 5
Line 6)"

इसलिए फ़ाइल के शीर्ष पर केवल एक उपसर्ग और उसके अंत में एक प्रत्यय होना चाहिए। इसके बीच आप वही कर सकते हैं जो आप चाहते हैं, जब तक आपको चरित्र अनुक्रम की आवश्यकता नहीं है तब तक कोई विशेष भागने की आवश्यकता नहीं है )"। लेकिन यहां तक ​​कि यह काम कर सकता है यदि आप अपने स्वयं के कस्टम सीमांकक को निर्दिष्ट करते हैं:

R"=====(Line 1
Line 2
Line 3
Now you can use "( and )" in the text file, too.
Line 5
Line 6)====="

5
धन्यवाद, मैंने अपने सी ++ 11 कोड में एसक्यूएल के लंबे टुकड़े को एम्बेड करने के लिए यहां प्रस्तावित विधि को चुना । यह मुझे SQL को अपनी फाइलों में अलग से साफ रखने की अनुमति देता है, और उन्हें उचित वाक्यविन्यास जाँच, हाइलाइटिंग आदि के साथ संपादित करता है
YitzikC

1
यह वास्तव में मैं क्या चाहता हूँ के करीब है। विशेष रूप से उपयोगकर्ता परिभाषित सीमांकक। बहुत उपयोगी। मैं एक कदम और आगे जाना चाहता हूं: क्या आप जिस फ़ाइल को शामिल करना चाहते हैं, उससे उपसर्ग R (और प्रत्यय) को पूरी तरह से हटाने का एक तरीका है? मैंने प्रीफ़िक्स और प्रत्यय के साथ bra.in और ket.in नामक दो फ़ाइलों को परिभाषित करने की कोशिश की, उनमें एक-एक करके bra.in, file.txt और ket.in शामिल हैं। लेकिन कंपाइलर नेक्स्ट फाइल को शामिल करने से पहले ब्रा.इन (जो अभी आर है) () की सामग्री का मूल्यांकन करता है। इसलिए यह शिकायत करेगा। कृपया मुझे बताएं कि अगर किसी को पता है कि फाइल टाइक्स से प्रीफिक्स और प्रत्यय की सवारी कैसे हो सकती है। धन्यवाद।
टीएमएस

मुझे लग रहा है कि C ++ R "(<newline> #include ...)" की अनुमति नहीं देगा? फ़ाइल को संकलित करने के लिए अच्छा होगा, किसी भी एन्कोडिंग की आवश्यकता नहीं होने के लिए समय-समय पर किया जाएगा .... यानी सीधे json या xml या csv या क्या नहीं ..
ब्रायन क्रिसमैन

आप कच्चे शाब्दिक पाठ को थोड़ा अधिक पठनीय बना सकते हैं यदि आप 1+R"...इसके बजाय प्रारंभिक सीमांकक के रूप में उपयोग करते हैं R"..., और फिर पहले एक नई रूपरेखा प्रस्तुत करते हैं Line 1। यह एक एरे से एक पॉइंटर में एक्सप्रेशन को बदल देगा, लेकिन यह वास्तव में यहां कोई समस्या नहीं है, क्योंकि आप पाइंटर को इनिशियलाइज़ कर रहे हैं, एरे को नहीं।
रुस्लान

14

आपके पास दो संभावनाएँ हैं:

  1. बाइनरी डेटा की शुरुआत और अंत की ओर इशारा करते हुए उचित प्रतीकों के साथ एक फाइल को बाइनरी फ़ाइल में बदलने के लिए कंपाइलर / लिंकर एक्सटेंशन का उपयोग करें। इस उत्तर को देखें: GNU ld लिंकर स्क्रिप्ट के साथ बाइनरी फ़ाइल शामिल करें
  2. अपनी फ़ाइल को वर्ण स्थिरांक के अनुक्रम में परिवर्तित करें जो किसी सरणी को आरंभ कर सकता है। ध्यान दें कि आप बस "" नहीं कर सकते हैं और कई लाइनों को फैला सकते हैं। आपको उस काम को करने के लिए एक पंक्ति निरंतरता चरित्र ( \), भागने के "पात्रों और अन्य की आवश्यकता होगी। बाइट्स को अनुक्रम में बदलने के लिए बस एक छोटा सा प्रोग्राम लिखना आसान है '\xFF', '\xAB', ...., '\0'(या xxdयदि आपके पास उपलब्ध है तो किसी अन्य उत्तर के द्वारा वर्णित यूनिक्स टूल का उपयोग करें !)।

कोड:

#include <stdio.h>

int main() {
    int c;
    while((c = fgetc(stdin)) != EOF) {
        printf("'\\x%X',", (unsigned)c);
    }
    printf("'\\0'"); // put terminating zero
}

(टेस्ट नहीं हुआ)। फिर करो:

char my_file[] = {
#include "data.h"
};

जहाँ data.h द्वारा जनरेट किया जाता है

cat file.bin | ./bin2c > data.h

1
अंतिम पंक्ति शायद "बिल्ली file.bin |/bin2c> data.h" या "./bin2c <file.bin> data.h"
Hasturkun

मैंने एक बाइनरी से एक हेक्स फ़ाइल (विंडोज पर) बनाने के लिए codeproject.com/Tips/845393/… का उपयोग किया और फिर char my_file[] = { #include my_large_file.h };धन्यवाद के अपने सुझाव का इस्तेमाल किया !
कोई व्यक्ति

bin2cहै डेबियन के रूप में एक ही से bin2c hxtools, सावधान रहना
ThorSummoner

या यदि यह है, तो आह्वान अब बहुत bin2c -H myoutput.h myinput1.txt myinputN.txt
अजीब है

9

ठीक है, डेमिन की पोस्ट से प्रेरित होकर मैंने निम्नलिखित सरल उदाहरण का परीक्षण किया:

a.data:

"this is test\n file\n"

test.c:

int main(void)
{
    char *test = 
#include "a.data"
    ;
    return 0;
}

gcc -E test.c आउटपुट:

# 1 "test.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "test.c"

int main(void)
{
    char *test =
# 1 "a.data" 1
"this is test\n file\n"
# 6 "test.c" 2
    ;
    return 0;
}

तो यह काम कर रहा है लेकिन उद्धरण चिह्नों से घिरे डेटा की आवश्यकता है।


यही कारण है कि मैं अपने जवाब के अंतिम बिट में था।
डेमिन

उद्धरण, या इसे जो भी कहा जाता है, मेरी अंग्रेजी को क्षमा करें
इल्या

इसके लिए डेटा को C- बचना आवश्यक है। मुझे नहीं लगता कि पोस्ट की तलाश है। यदि इसमें कुछ प्रकार के मैक्रो शामिल होते हैं जो सी-फ़ाइल की सामग्री से बच जाते हैं, तो यह ठीक होगा।
ब्रायन क्रिसमैन

8

मुझे कहार का जवाब पसंद है। यदि आप इनपुट फ़ाइलों को स्पर्श नहीं करना चाहते हैं , और यदि आप CMake का उपयोग कर रहे हैं, तो आप फ़ाइल पर delimeter वर्ण अनुक्रम जोड़ सकते हैं। उदाहरण के लिए, निम्न CMake कोड, इनपुट फ़ाइलों की प्रतिलिपि बनाता है और तदनुसार अपनी सामग्री लपेटता है:

function(make_includable input_file output_file)
    file(READ ${input_file} content)
    set(delim "for_c++_include")
    set(content "R\"${delim}(\n${content})${delim}\"")
    file(WRITE ${output_file} "${content}")
endfunction(make_includable)

# Use like
make_includable(external/shaders/cool.frag generated/cool.frag)

फिर सी ++ में इस तरह शामिल करें:

constexpr char *test =
#include "generated/cool.frag"
;

5

आप इसका उपयोग कर सकते हैं objcopy:

objcopy --input binary --output elf64-x86-64 myfile.txt myfile.o

अब आपके पास एक ऑब्जेक्ट फ़ाइल है जिसे आप अपने निष्पादन योग्य में लिंक कर सकते हैं जिसमें सामग्री की शुरुआत, अंत और आकार के लिए प्रतीक हैं myfile.txt


1
क्या आप हमें बता पाएंगे कि प्रतीक के नाम क्या होंगे?
मार्क Ch

@MarkCh: डॉक्स के अनुसार, प्रतीक नाम इनपुट फ़ाइल नाम से उत्पन्न होते हैं।
जॉन Zwinck

मैं गैर x86-64 मशीनों पर इस अभ्यस्त काम का अनुमान लगा रहा हूँ, यह होगा?
ThorSummoner


2

आपको मेरी xtrउपयोगिता चाहिए लेकिन आप इसे कर सकते हैं bash script। यह एक स्क्रिप्ट है जिसे मैं कॉल करता हूं bin2inc। पहला पैरामीटर परिणामी का नाम है char[] variable। दूसरा पैरामीटर का नाम है file। आउटपुट C include file, फ़ाइल सामग्री के साथ दिया गया है जो एनकोडेड (लोअरकेस में hex) चर नाम के रूप में दिया गया है। char arrayहै zero terminated, और डेटा की लंबाई में संग्रहित है$variableName_length

#!/bin/bash

fileSize ()

{

    [ -e "$1" ]  && {

        set -- `ls -l "$1"`;

        echo $5;

    }

}

echo unsigned char $1'[] = {'
./xtr -fhex -p 0x -s ', ' < "$2";
echo '0x00'
echo '};';
echo '';
echo unsigned long int ${1}_length = $(fileSize "$2")';'

आप XTR यहाँ प्राप्त कर सकते हैं (चरित्र eXTRapolator) GPLV3 है


2

यदि आप कुछ गंदे चालों का सहारा लेने के लिए तैयार हैं, तो आप कच्चे स्ट्रिंग शाब्दिक और #includeकुछ प्रकार की फ़ाइलों के साथ रचनात्मक प्राप्त कर सकते हैं ।

उदाहरण के लिए, मान लीजिए कि मैं अपने प्रोजेक्ट में SQLite के लिए कुछ एसक्यूएल स्क्रिप्ट शामिल करना चाहता हूं और मैं सिंटैक्स हाइलाइटिंग प्राप्त करना चाहता हूं, लेकिन कोई विशेष स्क्रिप्ट इंफ्रास्ट्रक्चर नहीं चाहता। मेरे पास यह फ़ाइल हो सकती है test.sqlजो SQLite के लिए मान्य SQL है जहाँ --एक टिप्पणी शुरू होती है:

--x, R"(--
SELECT * from TestTable
WHERE field = 5
--)"

और फिर मेरे C ++ कोड में मैं हो सकता है:

int main()
{
    auto x = 0;
    const char* mysql = (
#include "test.sql"
    );

    cout << mysql << endl;
}

आउटपुट है:

--
SELECT * from TestTable
WHERE field = 5
--

या एक फ़ाइल से कुछ पायथन कोड को शामिल करने के लिए test.pyजो एक वैध पायथन लिपि है (क्योंकि #पायथन में एक टिप्पणी शुरू होती है और passएक नो-ऑप है):

#define pass R"(
pass
def myfunc():
    print("Some Python code")

myfunc()
#undef pass
#define pass )"
pass

और फिर C ++ कोड में:

int main()
{
    const char* mypython = (
#include "test.py"
    );

    cout << mypython << endl;
}

जो आउटपुट देगा:

pass
def myfunc():
    print("Some Python code")

myfunc()
#undef pass
#define pass

विभिन्न प्रकार के कोड के लिए समान चालें चलाना संभव हो सकता है जिन्हें आप एक स्ट्रिंग के रूप में शामिल करना चाहते हैं। यह एक अच्छा विचार है या नहीं, मुझे यकीन नहीं है। यह एक साफ-सुथरी हैक की तरह है, लेकिन शायद ऐसा कुछ नहीं है जिसे आप वास्तविक उत्पादन कोड में चाहते हैं। हालांकि सप्ताहांत हैक प्रोजेक्ट के लिए ठीक हो सकता है।


मैंने इस दृष्टिकोण का उपयोग OpenGL Shaders को पाठ फ़ाइलों में करने के लिए किया है!
16

1

मैंने python3 में xxd को फिर से लागू किया, xxd की सभी परेशानियों को ठीक किया:

  • लगातार सुधार
  • स्ट्रिंग लंबाई डेटाटाइप: int → size_t
  • अशक्त समाप्ति (यदि आप चाहते हैं कि मामले में)
  • सी स्ट्रिंग संगत: unsignedसरणी पर छोड़ें ।
  • छोटे, पठनीय आउटपुट, जैसा कि आपने लिखा होगा: प्रिंट करने योग्य एससीआई आउटपुट है जैसा कि; अन्य बाइट्स हेक्स-एन्कोडेड हैं।

यहाँ स्क्रिप्ट है, स्वयं द्वारा फ़िल्टर की गई है, इसलिए आप देख सकते हैं कि यह क्या करता है:

pyxxd.c

#include <stddef.h>

extern const char pyxxd[];
extern const size_t pyxxd_len;

const char pyxxd[] =
"#!/usr/bin/env python3\n"
"\n"
"import sys\n"
"import re\n"
"\n"
"def is_printable_ascii(byte):\n"
"    return byte >= ord(' ') and byte <= ord('~')\n"
"\n"
"def needs_escaping(byte):\n"
"    return byte == ord('\\\"') or byte == ord('\\\\')\n"
"\n"
"def stringify_nibble(nibble):\n"
"    if nibble < 10:\n"
"        return chr(nibble + ord('0'))\n"
"    return chr(nibble - 10 + ord('a'))\n"
"\n"
"def write_byte(of, byte):\n"
"    if is_printable_ascii(byte):\n"
"        if needs_escaping(byte):\n"
"            of.write('\\\\')\n"
"        of.write(chr(byte))\n"
"    elif byte == ord('\\n'):\n"
"        of.write('\\\\n\"\\n\"')\n"
"    else:\n"
"        of.write('\\\\x')\n"
"        of.write(stringify_nibble(byte >> 4))\n"
"        of.write(stringify_nibble(byte & 0xf))\n"
"\n"
"def mk_valid_identifier(s):\n"
"    s = re.sub('^[^_a-z]', '_', s)\n"
"    s = re.sub('[^_a-z0-9]', '_', s)\n"
"    return s\n"
"\n"
"def main():\n"
"    # `xxd -i` compatibility\n"
"    if len(sys.argv) != 4 or sys.argv[1] != \"-i\":\n"
"        print(\"Usage: xxd -i infile outfile\")\n"
"        exit(2)\n"
"\n"
"    with open(sys.argv[2], \"rb\") as infile:\n"
"        with open(sys.argv[3], \"w\") as outfile:\n"
"\n"
"            identifier = mk_valid_identifier(sys.argv[2]);\n"
"            outfile.write('#include <stddef.h>\\n\\n');\n"
"            outfile.write('extern const char {}[];\\n'.format(identifier));\n"
"            outfile.write('extern const size_t {}_len;\\n\\n'.format(identifier));\n"
"            outfile.write('const char {}[] =\\n\"'.format(identifier));\n"
"\n"
"            while True:\n"
"                byte = infile.read(1)\n"
"                if byte == b\"\":\n"
"                    break\n"
"                write_byte(outfile, ord(byte))\n"
"\n"
"            outfile.write('\";\\n\\n');\n"
"            outfile.write('const size_t {}_len = sizeof({}) - 1;\\n'.format(identifier, identifier));\n"
"\n"
"if __name__ == '__main__':\n"
"    main()\n"
"";

const size_t pyxxd_len = sizeof(pyxxd) - 1;

उपयोग (यह स्क्रिप्ट निकालता है):

#include <stdio.h>

extern const char pyxxd[];
extern const size_t pyxxd_len;

int main()
{
    fwrite(pyxxd, 1, pyxxd_len, stdout);
}

1

अगर आप कुछ ऐसा करते हैं तो क्या काम हो सकता है:

int main()
{
    const char* text = "
#include "file.txt"
";
    printf("%s", text);
    return 0;
}

बेशक आप वास्तव में क्या फ़ाइल में है के साथ सावधान रहना होगा , यह सुनिश्चित करते हुए कि कोई दोहरे उद्धरण नहीं हैं, कि सभी उपयुक्त अक्षर बच गए हैं, आदि।

इसलिए यह आसान हो सकता है यदि आप पाठ को रनटाइम पर किसी फ़ाइल से लोड करते हैं , या टेक्स्ट को सीधे कोड में एम्बेड करते हैं।

यदि आप अभी भी किसी अन्य फ़ाइल में पाठ चाहते थे, तो आप इसे वहां रख सकते हैं, लेकिन इसे वहां स्ट्रिंग के रूप में प्रस्तुत करना होगा। आप उपरोक्त कोड का उपयोग करेंगे लेकिन इसमें दोहरे उद्धरण चिह्नों के बिना। उदाहरण के लिए:

file.txt

"Something evil\n"\
"this way comes!"

main.cpp

int main()
{
    const char* text =
#include "file.txt"
;
    printf("%s", text);
    return 0;
}

तो मूल रूप से आपके द्वारा सम्मिलित पाठ फ़ाइल में C या C ++ शैली स्ट्रिंग है। यह कोड को शून्य बना देगा क्योंकि फ़ाइल के प्रारंभ में यह बहुत बड़ा पाठ नहीं है।


3
अच्छा विचार है, लेकिन यह काम नहीं करेगा, या तो आपके पास एक त्रुटि है क्योंकि शाब्दिक में एक नई-पंक्ति शामिल है या #include भाग को एक स्ट्रिंग के रूप में पढ़ा जाएगा और निष्पादित नहीं किया जाएगा, यदि आप करते हैं और शापित नहीं होने पर शापित हो जाएगा। ।
13

1
@Motti: सहमत - जैसा कि लिखा गया है, वाक्यविन्यास अमान्य सी। विचार दिलचस्प है - सी प्री-प्रोसेसर तार्किक रूप से एक अलग चरण है - लेकिन अभ्यास यह है कि यह जमीन से नहीं उतरता है क्योंकि शामिल फ़ाइल में प्रत्येक पंक्ति में होगा बैकस्लैश, आदि के साथ समाप्त करने के लिए
जोनाथन लेफ़लर

2
Humm। मुझे लगता है कि आपको बैकस्लैश की आवश्यकता नहीं होनी चाहिए क्योंकि अधिकांश संकलक एक साथ
सहायक

इस जवाब के साथ बात यह है ... अगर यह इतना आसान था, मुझे नहीं लगता कि ओपी ने कभी सवाल पूछा होगा! -1 क्योंकि इस उत्तर की उपस्थिति लोगों को अपना काम करने में कुछ समय बर्बाद करने के लिए प्रोत्साहित कर रही है। मुझे लगता है कि यदि आप "क्या काम कर सकते हैं" को "संदर्भ के लिए, यह काम नहीं करता है" तो हम नीचे को हटा सकते हैं
मार्क Ch

@JonathanLeffler प्रीप्रोसेसर के चलने के बाद यह मान्य होना चाहिए C या C ++ इस बात पर निर्भर करता है कि file.txt कैसे बनता है।
Daemin

0

यहां तक ​​कि अगर यह संकलन समय पर किया जा सकता है (मुझे नहीं लगता कि यह सामान्य रूप से हो सकता है), पाठ संभवतः फ़ाइलों की सामग्री वर्बटिम के बजाय प्रीप्रोसेड हेडर होगा। मुझे उम्मीद है कि आपको रनटाइम पर फ़ाइल से पाठ को लोड करना होगा या एक बुरा कट-एन-पेस्ट काम करना होगा।


0

Xxd -i विकल्प का उपयोग करके हस्त्कुर्कन का उत्तर उत्कृष्ट है। यदि आप रूपांतरण प्रक्रिया को शामिल करना चाहते हैं (पाठ -> हेक्स में फ़ाइल शामिल है) सीधे अपने निर्माण में शामिल करें hexdump.c टूल / लाइब्रेरी ने हाल ही में xxd -i विकल्प के समान क्षमता जोड़ी है (यह आपको पूर्ण हेडर नहीं देता है - आपको ज़रूरत है चार सरणी परिभाषा प्रदान करने के लिए - लेकिन आपको चार सरणी का नाम लेने की सुविधा देने का फायदा है):

http://25thandclement.com/~william/projects/hexdump.c.html

यह लाइसेंस xxd की तुलना में बहुत अधिक "मानक" है और बहुत उदार है - एक प्रोग्राम में एक इनिट फ़ाइल को एम्बेड करने के लिए इसका उपयोग करने का एक उदाहरण यहां CMakeLists.txt और स्कीम सी फाइलों में देखा जा सकता है:

https://github.com/starseeker/tinyscheme-cmake

स्रोत पेड़ों और बंडल उपयोगिताओं में उत्पन्न फ़ाइलों को शामिल करने के लिए पेशेवरों और विपक्ष दोनों हैं - यह कैसे संभालना है यह आपके प्रोजेक्ट के विशिष्ट लक्ष्यों और आवश्यकताओं पर निर्भर करेगा। hexdump.c इस एप्लिकेशन के लिए बंडल विकल्प खोलता है।


0

मुझे लगता है कि यह केवल कंपाइलर और प्रीप्रोसेसर के साथ संभव नहीं है। gcc इसे अनुमति देता है:

#define _STRGF(x) # x
#define STRGF(x) _STRGF(x)

    printk ( MODULE_NAME " built " __DATE__ " at " __TIME__ " on host "
            STRGF(
#               define hostname my_dear_hostname
                hostname
            )
            "\n" );

लेकिन दुर्भाग्य से यह नहीं:

#define _STRGF(x) # x
#define STRGF(x) _STRGF(x)

    printk ( MODULE_NAME " built " __DATE__ " at " __TIME__ " on host "
            STRGF(
#               include "/etc/hostname"
            )
            "\n" );

त्रुटि है:

/etc/hostname: In function init_module’:
/etc/hostname:1:0: error: unterminated argument list invoking macro "STRGF"

मैंने देखा है, जैसे आप मुझे देखो बोली। मुझे आपके उत्तर में कोई भी नई जानकारी नहीं दिख रही है (जानकारी जो अन्य उत्तरों में नहीं है), /etc/hostnameस्ट्रिंग में बिल्ड मशीन के नाम को एम्बेड करने के एक तरीके से परे है , जो (भले ही यह काम किया हो) नहीं होगा मैक ओएस एक्स में पोर्टेबल फ़ाइल नहीं है /etc/hostname। ध्यान दें कि बड़े अक्षरों के साथ शुरू होने वाले मैक्रो नामों का उपयोग करते हुए एक कैपिटल लेटर को लागू करने के लिए आरक्षित नाम का उपयोग किया जाता है, जो ए बैड थॉट ™ है।
जोनाथन लेफ़लर

0

पाठ को प्रोग्राम में लिंक क्यों न करें और इसे एक वैश्विक चर के रूप में उपयोग करें! यहाँ एक उदाहरण है। मैं एक निष्पादन योग्य के भीतर ओपन जीएल shader फ़ाइलों को शामिल करने के लिए इसका उपयोग करने पर विचार कर रहा हूं क्योंकि GL shaders को रनटाइम पर GPU के लिए संकलित करने की आवश्यकता है।


0

मेरे पास समान मुद्दे थे, और छोटी फाइलों के लिए जोहानस शाउब के उपरोक्त समाधान ने मेरे लिए एक आकर्षण की तरह काम किया।

हालाँकि, उन फ़ाइलों के लिए जो थोड़ी बड़ी हैं, यह संकलक की वर्ण सरणी सीमा के साथ मुद्दों में चली गई। इसलिए, मैंने एक छोटा सा एनकोडर एप्लिकेशन लिखा है जो फ़ाइल सामग्री को समान आकार के विखंडू के 2 डी चरित्र सरणी में परिवर्तित करता है (और संभवतः ज़ेडोस को पैड कर रहा है)। यह इस तरह से 2D सरणी डेटा के साथ आउटपुट टेक्स्टफाइल्स का उत्पादन करता है:

const char main_js_file_data[8][4]= {
    {'\x69','\x73','\x20','\0'},
    {'\x69','\x73','\x20','\0'},
    {'\x61','\x20','\x74','\0'},
    {'\x65','\x73','\x74','\0'},
    {'\x20','\x66','\x6f','\0'},
    {'\x72','\x20','\x79','\0'},
    {'\x6f','\x75','\xd','\0'},
    {'\xa','\0','\0','\0'}};

जहां 4 वास्तव में एनकोडर में एक चर MAX_CHARS_PER_ARRAY है। परिणामी C कोड वाली फ़ाइल, उदाहरण के लिए, "main_js_file_data.h", तब आसानी से C ++ एप्लिकेशन में इनलाइन की जा सकती है, उदाहरण के लिए:

#include "main_js_file_data.h"

यहाँ एनकोडर का स्रोत कोड है:

#include <fstream>
#include <iterator>
#include <vector>
#include <algorithm>


#define MAX_CHARS_PER_ARRAY 2048


int main(int argc, char * argv[])
{
    // three parameters: input filename, output filename, variable name
    if (argc < 4)
    {
        return 1;
    }

    // buffer data, packaged into chunks
    std::vector<char> bufferedData;

    // open input file, in binary mode
    {    
        std::ifstream fStr(argv[1], std::ios::binary);
        if (!fStr.is_open())
        {
            return 1;
        }

        bufferedData.assign(std::istreambuf_iterator<char>(fStr), 
                            std::istreambuf_iterator<char>()     );
    }

    // write output text file, containing a variable declaration,
    // which will be a fixed-size two-dimensional plain array
    {
        std::ofstream fStr(argv[2]);
        if (!fStr.is_open())
        {
            return 1;
        }
        const std::size_t numChunks = std::size_t(std::ceil(double(bufferedData.size()) / (MAX_CHARS_PER_ARRAY - 1)));
        fStr << "const char " << argv[3] << "[" << numChunks           << "]"    <<
                                            "[" << MAX_CHARS_PER_ARRAY << "]= {" << std::endl;
        std::size_t count = 0;
        fStr << std::hex;
        while (count < bufferedData.size())
        {
            std::size_t n = 0;
            fStr << "{";
            for (; n < MAX_CHARS_PER_ARRAY - 1 && count < bufferedData.size(); ++n)
            {
                fStr << "'\\x" << int(unsigned char(bufferedData[count++])) << "',";
            }
            // fill missing part to reach fixed chunk size with zero entries
            for (std::size_t j = 0; j < (MAX_CHARS_PER_ARRAY - 1) - n; ++j)
            {
                fStr << "'\\0',";
            }
            fStr << "'\\0'}";
            if (count < bufferedData.size())
            {
                fStr << ",\n";
            }
        }
        fStr << "};\n";
    }

    return 0;
}

0

यह समस्या मुझे परेशान कर रही थी और xxd मेरे उपयोग के मामले के लिए काम नहीं करता क्योंकि इसने चर को __home_myname_build_prog_cmakelists_src_autogen की तरह बनाया जब मैंने इसे स्क्रिप्ट करने की कोशिश की, इसलिए मैंने इस सटीक समस्या को हल करने के लिए एक उपयोगिता बनाई:

https://github.com/Exaeta/brcc

यह एक स्रोत और हेडर फ़ाइल बनाता है और आपको प्रत्येक चर का नाम स्पष्ट रूप से सेट करने की अनुमति देता है ताकि आप उन्हें std :: start (arrayname) और std :: end (arrayname) के माध्यम से उपयोग कर सकें।

मैंने इसे अपने cmake प्रोजेक्ट में शामिल किया जैसे:

add_custom_command(
  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/binary_resources.hpp ${CMAKE_CURRENT_BINARY_DIR}/binary_resources.cpp
  COMMAND brcc ${CMAKE_CURRENT_BINARY_DIR}/binary_resources RGAME_BINARY_RESOURCES_HH txt_vertex_shader ${CMAKE_CURRENT_BINARY_DIR}/src/vertex_shader1.glsl
  DEPENDS src/vertex_shader1.glsl)

छोटे ट्वीक्स के साथ मुझे लगता है कि इसे सी के लिए भी काम किया जा सकता है।


-1

, xh में

"this is a "
"buncha text"

में मुख्य

#include <stdio.h>
int main(void)
{
    char *textFileContents =
#include "x.h"
    ;

    printf("%s\n", textFileContents);

    return 0
}

काम करना चाहिए।


कई लाइनों के लिए आपको \ n जोड़ने की आवश्यकता है: "लाइन 1 \ n" "लाइन 2 \ n"
Superfly जॉन

यह थोड़ा भ्रामक है, जाहिर है इसके लिए उद्धरण और \ n वर्ण जोड़ने के लिए पाठ फ़ाइल की कुछ तैयारी की आवश्यकता होती है, सामान्य स्थिति में काम नहीं करता है
मार्क च
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.