बाइनरी फ़ाइल की सामग्री को उल्टा कैसे करें?


11

मैं एक चुनौती है, जहां मैं एक पाया सुलझाने था डेटा फ़ाइल कोई फ़ाइल एक्सटेंशन के साथ। fileआदेश से पता चलता है कि यह एक है कि data file (application/octet-stream)hdआदेश से पता चलता है जीएनपी। अंतिम पंक्ति में। इसलिए अगर मैं इस फाइल को रिवर्स करता हूं तो मुझे .PNG फॉर्मेट फाइल मिल जाएगी , मैंने हर जगह सर्च किया लेकिन मुझे कोई हल नहीं मिला जिसमें बताया गया कि बाइनरी फाइल का कंटेंट कैसे रिवर्स किया जाए।

जवाबों:


11

के साथ xxd(और vim) और tacजीएनयू कोर्यूटिल्स से, tail -rकुछ प्रणालियों पर भी ):

< file.gnp xxd -p -c1 | tac | xxd -p -r > file.png

क्या इसके लिए vi.stackexchange.com/a/2237/10649 के साथ संयोजन करने का कोई तरीका है ? मैंने बिना किसी भाग्य के सभी प्रकार के संयोजनों की कोशिश की :(
इयूलियन ओनोफ्रेई

यह एक समाधान नहीं है क्योंकि यह सभी फ़ाइल को दर्पण करेगा।
फिलिप डेल्टिल

@PhilippeDelteil, सभी फ़ाइल को मिरर कर रहा था कि ओपी यहाँ क्या मांग रहा है? आप इसे और क्या करना चाहेंगे?
स्टीफन चेज़ेलस

4

में zsh(केवल शेल जो बाइनरी डेटा से आंतरिक रूप से निपट सकता है (जब तक कि आप ksh93 के बेस 64 एन्कोडिंग दृष्टिकोण पर विचार नहीं करना चाहते )):

zmodload zsh/mapfile
(LC_ALL=C; printf %s ${(s::Oa)mapfile[file.gnp]} > file.png)
  • LC_ALL=C: अक्षर बाइट्स हैं
  • $mapfile[file.gnp]: file.gnpफ़ाइल की सामग्री
  • s::: स्ट्रिंग को अपने बाइट घटकों में विभाजित करें
  • Oa: एरे को सब्सक्राइब करें Oपर रिवर्स aराइडर उस एरे को

1
zshकेवल ऐसा शेल नहीं है जो बाइनरी डेटा को संभाल सकता है।
fpmurphy

2

यहाँ एक द्विआधारी फ़ाइल का उपयोग करने का एक तरीका है ksh93। मैंने कोड "ढीला" छोड़ दिया है ताकि इसे समझना आसान हो सके।

#!/bin/ksh93

typeset -b byte

redirect 3< image.gpj || exit 1

eof=$(3<#((EOF)))

read -r -u 3 -N 1 byte
printf "%B" byte > image.jpg
3<#((CUR - 1))

while (( $(3<#) > 0 ))
do
    read -r -u 3 -N 1 byte
    printf "%B" byte >> image.jpg
    3<#((CUR - 2))
done

read -r -u 3 -N 1 byte
printf "%B" byte >> image.jpg

redirect 3<&- || echo 'cannot close FD 3'

exit 0

अच्छा। यह अब तक का एकमात्र उत्तर है जिसमें संपूर्ण फ़ाइल को मेमोरी में संग्रहीत करना शामिल नहीं है। हालाँकि, यह बहुत अक्षम है कि यह फ़ाइल के प्रत्येक बाइट के लिए कई सिस्टम कॉल करता है (और बेस 64 से / रूपांतरण), इसलिए यह उन फ़ाइलों के लिए उपयुक्त नहीं होगा जो या तो मेमोरी में फिट नहीं होती हैं। मेरी मशीन पर, यह
स्टीफन चेज़लस

ध्यान दें कि readउपरोक्त पहले को कुछ भी नहीं पढ़ना चाहिए क्योंकि यह फ़ाइल के अंत में किया गया है।
स्टीफन चेज़लस

यह समझने की कोशिश करना कि यह इतना धीमा क्यों था, मैंने इसे चलाने की कोशिश की straceऔर ksh93लगता है कि यह बहुत ही अजीब व्यवहार कर रहा है, जहां यह फाइल के भीतर सभी जगह तलाशता है और समय पर बड़ी मात्रा में पढ़ता है। हो सकता है कि github.com/att/ast/issues/15
स्टीफन चेज़लस

@ StéphaneChazelas। कोई रहस्य नहीं है कि यह अपेक्षाकृत धीमा क्यों है। लूप के भीतर इसे बाइट पढ़ते समय हर बार पीछे की ओर देखना होता है। यह आसानी से एक बार में एक से अधिक बाइट पढ़ने और लिखने से 20 या उससे अधिक के एक कारक से काफी कम हो सकता है। चीजों के लेखन पक्ष को इसी तरह अनुकूलित किया जा सकता है। चीजों को और गति देने के लिए अन्य तकनीकें उपलब्ध हैं। मैं उस व्यायाम को तुम्हारे ऊपर छोड़ दूंगा।
fpmurphy

straceस्क्रिप्ट पर कोशिश करें कि मेरा क्या मतलब है। ksh93फाइलों को हजारों बार पढ़ता है। उदाहरण के लिए, पहले बाइट को पढ़ने से पहले, यह फ़ाइल के अंत में 64KiB की तलाश करता है, 64KiB को पढ़ता है, फिर अंतिम बाइट से पहले और 1 बाइट को पढ़ता है और हर बाइट के लिए कुछ ऐसा ही करता है। ध्यान दें कि आप उन बेस 64 एन्कोडेड स्ट्रिंग्स के साथ क्या कर सकते हैं, यह सीमित है, इसलिए यदि आप एक बार में एक से अधिक बाइट पढ़ते हैं, तो उस के अलग-अलग बाइट्स को निकालना अधिक मुश्किल होगा।
स्टीफन चेजलस

2

पर्ल के साथ:

perl -0777pe '$_=reverse $_'  [input_file]

प्रदर्शन का परीक्षण:

dd if=/dev/urandom of=/tmp/a bs=1M count=1
LC_ALL=C tac -rs $'.\\|\n' /tmp/a > /tmp/r

time perl -0777pe '$_=reverse $_' /tmp/a         | diff -q - /tmp/r
time xxd -p -c1 /tmp/a | tac | xxd -p -r         | diff -q - /tmp/r
time perl -0777 -F -ape '$_=reverse@F' /tmp/a    | diff -q - /tmp/r
time LC_ALL=C tac -rs $'.\\|\n' /tmp/a           | diff -q - /tmp/r

परिणाम:

  • स्थानीय रूप से परीक्षण किया गया: मेरा समाधान सबसे तेज़ है, सबसे perl -0777 -Fधीमा है।
  • यह ऑनलाइन कोशिश पर परीक्षण किया गया ! : मेरा समाधान सबसे तेज़ है, सबसे xxdधीमा है।

नोट: समय diffरन सभी समाधानों के लिए समान होना चाहिए, क्योंकि आउटपुट समान होना चाहिए।


1
मैंने अपना perlएक डिलीट कर दिया है । मुझे समझ में नहीं आया था कि समय के reverseसाथ-साथ तार भी उलट सकते हैं, इसलिए ऐसा करने से विभाजन का कोई मतलब नहीं है और आपका संस्करण बहुत बेहतर है।
स्टीफन चेज़लस

1

मैंने निम्नलिखित कोशिश की:

tac -rs '.' input.gnp > output.png

विचार किसी भी चरित्र को विभाजक के रूप में उपयोग करने के लिए 'टैक' को बाध्य करने के लिए है। मैंने कोशिश की कि एक बाइनरी फ़ाइल पर और यह काम करने लगे लेकिन किसी भी पुष्टि की सराहना की जाएगी।

मुख्य लाभ यह है कि यह फ़ाइल को मेमोरी में लोड नहीं करता है।


मेरे लिए काम नहीं करता है (यहाँ GNU tac8.28 के साथ ) जब इनपुट में नई वर्ण होते हैं। printf '1\n2' | tac -rs . | od -vAn -tcके \n 2 1बजाय आउटपुट 2 \n 1। आपको मल्टी-बाइट वर्णों की भी आवश्यकता हो सकती है LC_ALL=Cया .हो सकती है।
स्टीफन चेजेलस

4
LC_ALL=C tac -rs $'.\\|\n'हालांकि काम करने लगता है।
स्टीफन चेजेलस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.