बाइनरी फ़ाइल को C / C ++ स्ट्रिंग शाब्दिक के रूप में कैसे डंप करें?


39

मेरे पास एक द्विआधारी फ़ाइल है जिसे मैं अपने सी स्रोत कोड (अस्थायी रूप से, परीक्षण के प्रयोजनों के लिए) में शामिल करना चाहता हूं, इसलिए मैं फ़ाइल सामग्री को सी स्ट्रिंग के रूप में प्राप्त करना चाहूंगा, कुछ इस तरह से:

\x01\x02\x03\x04

क्या यह संभव है, odया hexdumpउपयोगिताओं द्वारा संभव है ? जबकि आवश्यक नहीं है, अगर स्ट्रिंग हर 16 इनपुट बाइट्स को अगली पंक्ति में लपेट सकती है, और प्रत्येक पंक्ति के शुरू और अंत में दोहरे उद्धरण शामिल हैं, जो कि अच्छा भी होगा!

मुझे पता है कि स्ट्रिंग में एम्बेडेड नल होंगे ( \x00) इसलिए मुझे इन बाइट्स को स्ट्रिंग को जल्दी समाप्त करने से रोकने के लिए कोड में स्ट्रिंग की लंबाई निर्दिष्ट करने की आवश्यकता होगी।



मैं भी ऐसा ही चाहता हूं लेकिन एएससीआई प्रिंट करने योग्य ग्लिफ़ को बनाए रखें, केवल 1-127 से बचकर, बोली, बैकलैश, नल, आदि
在 盐

जवाबों:


10

आप लगभग वही कर सकते हैं जो आप चाहते हैं hexdump, लेकिन मैं यह पता नहीं लगा सकता कि प्रारूप स्ट्रिंग में उद्धरण और एकल बैकस्लैश कैसे प्राप्त करें। इसलिए मैं थोड़ी पोस्ट-प्रोसेसिंग करता हूं sed। एक बोनस के रूप में, मैंने प्रत्येक पंक्ति को 4 स्थानों से प्रेरित किया है। :)

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

संपादित करें

जैसा कि Cengiz बताया जा सकता है, उपरोक्त कमांड लाइन लघु डेटा लाइनों के साथ अच्छी तरह से सामना नहीं करता है। तो यहाँ एक नया उन्नत संस्करण है:

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

जैसा कि टिप्पणियों में माल्विनस उल्लेख किया गया है, हमें समान बाइट्स के लंबे रन को संक्षिप्त -vकरने hexdumpसे रोकने के लिए क्रिया विकल्प को पास करने की भी आवश्यकता है *

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

यदि इनपुट 16 बाइट्स से कम है, तो यह निरर्थक और अमान्य तत्व पैदा करता है।
सेंगिज

@CengizCan:: उफ़:! क्या वो बेहतर है?
PM 2Ring

1
-vविकल्प को जोड़ने की आवश्यकता है hexdump, अन्यथा उसी इनपुट बाइट के लंबे रन आउटपुट लाइनों को कहते हैं "*"
मालविनस

@ मालविनस गुड पॉइंट! मैंने अपना उत्तर संशोधित कर दिया है। हेड-अप के लिए धन्यवाद (और मेरे उत्तर को स्वीकार करने के लिए धन्यवाद)।
PM 2Ring

66

xxdइसके लिए एक विधा है। -i/ --includeविकल्प होगा:

C में आउटपुट में फ़ाइल शैली शामिल है। एक पूर्ण स्थिर सरणी परिभाषा लिखी जाती है (इनपुट फ़ाइल के नाम पर), जब तक कि xxd स्टड से नहीं पढ़ता है।

आप उस फ़ाइल को #included होने के लिए डंप कर सकते हैं , और फिर 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स्रोत के बाहर अपने दम पर उपकरण का निर्माण भी कर सकते हैं ।


अच्छा! मुझे यह भी नहीं पता था कि मेरे पास xxd है। अब मुझे सिर्फ यह याद रखना है कि अगली बार मुझे इसकी आवश्यकता है ... या मैं शायद पायथन में आवश्यक कार्यक्षमता को दोहराऊंगा। :)
PM 2Ring

objcopyबेहतर होगा
मोनिका

@LightnessRacesinOrbit objcopyओपी को द्विआधारी डेटा को ऑब्जेक्ट फ़ाइल के रूप में निष्पादन योग्य के साथ लिंक करने की अनुमति देगा, जो कि उपयोगी है लेकिन वास्तव में यहां नहीं पूछा जा रहा है।
वांडर नुटा

1
@WanderNauta: आप इसे उसी तरीके से एक्सेस करेंगे जैसे आप यहां पहुंचेंगे foo/ करेंगे foo_len, और आप स्टोरेज स्पेस को बर्बाद नहीं करेंगे। मुझे विश्वास है कि ओपी के साथ बेहतर होगा objcopyऔर यह उसकी आवश्यकताओं के अनुरूप है।
मोनिका

2
objcopyयह ठीक है जब यह चारों ओर है, लेकिन यह पोर्टेबल नहीं है और आउटपुट भी कम है। यह निश्चित रूप से एक अच्छे स्थायी समाधान का हिस्सा हो सकता है, लेकिन यहाँ यह सवाल नहीं है।
माइकल होमर

3

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);

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


2

जैसा आपने पूछा, वैसा ही होना चाहिए:

hexdump -v -e '"\\" "x" 1/1 "%02X"' file.bin ; echo

0

यह एक छोटी उपयोगिता है जो मैंने लिखा है कि अनिवार्य रूप से एक ही काम करता है (मूल रूप से स्टैक ओवरफ्लो पर पोस्ट किया गया ):

#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;
}

1
यदि आप इसके साथ इनपुट और आउटपुट उदाहरण भी प्रदान करते हैं तो आपका उत्तर अधिक उपयोगी होगा।
not2qubit

0

यदि आप अजगर में हैं, तो इसे एक चर "बफ़र" में लोड करें और इस तरह से कुछ का उपयोग करें:

buff2 = buff.encode("hex")
print ("0x"+", 0x".join([buff2[i:i+2] for i in range(0,len(buff2),2)]))
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.