বাইনারি ফাইলের বিষয়বস্তুটি কীভাবে বিপরীত করবেন?


11

আমি একটি চ্যালেঞ্জের সমাধান করছিলাম যেখানে আমি কোনও ফাইল এক্সটেনশন ছাড়াই একটি ডেটা ফাইল পেয়েছি । fileকমান্ড শো এটি একটি যে data file (application/octet-stream)hdকমান্ড শো জিএনপি। শেষ লাইনে সুতরাং আমি যদি এই ফাইলটি বিপরীত করি তবে আমি .PNG ফর্ম্যাট ফাইলটি পেয়ে যাব, আমি সর্বত্র অনুসন্ধান করেছি কিন্তু বাইনারি ফাইলের বিষয়বস্তুটি কীভাবে বিপরীত করা যায় তা ব্যাখ্যা করার মতো কোনও সমাধান আমি পাইনি।

উত্তর:


11

সঙ্গে xxd(থেকে vim) এবং tac(গনুহ coreutils থেকে, এছাড়াও tail -rকিছু সিস্টেমে):

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

এটির সাথে vi.stackexchange.com/a/2237/10649 একত্রিত করার কোনও উপায় আছে কি ? আমি ভাগ্য ছাড়াই সমস্ত ধরণের সংমিশ্রণ চেষ্টা করেছি :(
আইলিয়ান ওনোফ্রেই

এটি কোনও সমাধান নয় কারণ এটি সমস্ত ফাইল মিরর করবে।
ফিলিপ ডেলটিল

ফিলিপডেল্টিল, সমস্ত ফাইলের মিররিংয়ে ওপি এখানে যা চেয়েছিলেন তা ছিল? আপনি এটি আরও কি করতে চান?
স্টাফেন চেজেলাস

4

ইন zsh(শুধুমাত্র শেল যে অভ্যন্তরীণভাবে বাইনারি ডেটা সাথে মোকাবিলা করতে পারেন (যদি না আপনি বিবেচনা করতে পদ্ধতির এনকোডিং ksh93 এর করুন Base64- )):

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উপর rder array সাবস্ক্রিপ্ট যে অ্যারের

1
zshবাইনারি ডেটা পরিচালনা করতে পারে এমন একমাত্র শেল নয়।
এফএমপুরফি

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 থেকে / থেকে রূপান্তর) এর জন্য একাধিক সিস্টেম কল করে, সুতরাং মেমরির সাথে খাপ খায় না এমন ফাইলগুলির পক্ষে উপযুক্ত হবে না। আমার মেশিনে, এটি প্রায় 10KB / s
-র

নোট করুন যে readফাইলের শেষে যেমনটি করা হয়েছে ঠিক তেমন উপরের প্রথমটি কিছুই পড়বে না।
স্টাফেন চেজেলাস

এটি এত মন্থর কেন ছিল তা বোঝার চেষ্টা করে, আমি এটি চালানোর চেষ্টা করেছি straceএবং ksh93মনে হচ্ছে এটি খুব অদ্ভুত আচরণ করছে, যেখানে এটি ফাইলের মধ্যে সমস্ত জায়গার সন্ধান করে এবং সেই সময়ে প্রচুর পরিমাণে পড়ে। হতে পারে github.com/att/ast/issues/15 এর
স্টাফেন চেজেলাস

@ StéphaneChazelas। এটি তুলনামূলকভাবে ধীরগতির বিষয়ে কোনও রহস্য নেই। লুপের মধ্যে এটি প্রতিবার বাইট পড়ার সময় পিছনের দিকে সন্ধান করতে হয়। এটি একবারে 20 বা আরও বেশি ফ্যাক্টর দ্বারা একসাথে একাধিক বাইট পড়ার দ্বারা এবং উল্লেখযোগ্যভাবে হ্রাস করা যেতে পারে। জিনিসগুলির লেখার দিকটি একইভাবে অনুকূলিত করা যায়। আরও গতি সম্পন্ন জিনিসগুলি আরও গতি বাড়ানোর জন্য উপলব্ধ। আমি এই অনুশীলনটি আপনার উপর ছেড়ে দেব।
এফএমপুরফি

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

ধারণাটি হ'ল 'ট্যাক' কে বিভাজক হিসাবে কোনও অক্ষর ব্যবহার করে বল প্রয়োগ করা। আমি এটি বাইনারি ফাইলটিতে চেষ্টা করেছি এবং এটি কাজ করছে বলে মনে হয়েছে তবে কোনও নিশ্চিতকরণ প্রশংসিত হবে।

প্রধান সুবিধা হ'ল এটি মেমরিতে ফাইল লোড করে না।


tacযখন ইনপুটটিতে নতুন লাইনের অক্ষর রয়েছে তখন আমার পক্ষে (এখানে জিএনইউ 8.28 সহ) কাজ করে না । পরিবর্তে printf '1\n2' | tac -rs . | od -vAn -tcআউটপুট । আপনারও প্রয়োজন বা মাল্টি-বাইট অক্ষর মেলে। \n 2 12 \n 1LC_ALL=C.
স্টাফেন চেজেলাস

4
LC_ALL=C tac -rs $'.\\|\n'যদিও কাজ বলে মনে হচ্ছে।
স্টাফেন চেজেলাস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.