रूबी में स्ट्रिंग के रूप में बाइनरी फ़ाइल पढ़ें


263

मुझे एक टार फ़ाइल लेने और इसे एक स्ट्रिंग (और इसके विपरीत) में बदलने के लिए एक आसान तरीका चाहिए। क्या रूबी में ऐसा करने का कोई तरीका है? मेरा सबसे अच्छा प्रयास यह था:

file = File.open("path-to-file.tar.gz")
contents = ""
file.each {|line|
  contents << line
}

मैंने सोचा था कि इसे एक स्ट्रिंग में बदलने के लिए पर्याप्त होगा, लेकिन तब जब मैं इसे इस तरह से वापस लिखने की कोशिश करता हूं ...

newFile = File.open("test.tar.gz", "w")
newFile.write(contents)

यह एक ही फाइल नहीं है। करना ls -lदिखाता है कि फाइलें विभिन्न आकारों की हैं, हालांकि वे बहुत करीब हैं (और फ़ाइल खोलने से अधिकांश सामग्री का खुलासा होता है)। क्या इसे पूरा करने के लिए एक छोटी सी गलती हो रही है या पूरी तरह से अलग (लेकिन काम करने योग्य) तरीका है?


3
यह एक gzipped टार फ़ाइल (मुझे आशा है)। कोई "रेखाएं" नहीं हैं। Pls स्पष्ट करें कि आप क्या हासिल करने की कोशिश कर रहे हैं।
ब्रेंट.लॉन्गबरो

क्या आप संपीड़ित डेटा या असम्पीडित सामग्री को देखने की कोशिश कर रहे हैं?
डेविड नेहम

एक संकुचित डेटा स्ट्रीम में चार वर्णों में लाइन के अंत में परिभाषित \ n "" पर उतरने के 256 मौके में लगभग 1 होगा, और यह ठीक है अगर यह "\ r" की अपेक्षा नहीं करता है, तो नीचे मेरा उत्तर देखें
Purfideas

इस प्रश्न को " बाइनरी फ़ाइल को स्ट्रिंग में बदलें" के रूप में फिर से शीर्षक देना चाहिए , क्योंकि IO.readअन्यथा पसंदीदा उत्तर होगा।
इयान

जवाबों:


397

सबसे पहले, आपको फ़ाइल को बाइनरी फ़ाइल के रूप में खोलना चाहिए। फिर आप पूरी फाइल को एक कमांड में पढ़ सकते हैं।

file = File.open("path-to-file.tar.gz", "rb")
contents = file.read

यह आपको एक स्ट्रिंग में पूरी फाइल मिलेगा।

उसके बाद, आप शायद चाहते हैं file.close। यदि आप ऐसा नहीं करते हैं file, तो इसे तब तक बंद नहीं किया जाएगा जब तक कि यह कचरा-एकत्र न हो जाए, इसलिए यह सिस्टम संसाधनों का एक मामूली अपशिष्ट होगा जब यह खुला होता है।


22
बाइनरी ध्वज केवल विंडोज पर प्रासंगिक है, और यह फ़ाइल डिस्क्रिप्टर को खुला छोड़ देता है। File.read (...) बेहतर है।
डैनियल हूकस्टेप

क्या इतने सारे लोगों के साथ ऐसा करना गलत है और इसे एक-लाइनर समाधान के रूप में चिपकाना है (जैसे स्टैकफ़्लो पर बहुत सारी चीज़ें)? आखिरकार, यह काम करता है, और इन कार्यों के लिए नाम सिर्फ रूबी लाइब्रेरी डिजाइनरों की एक मनमानी पसंद थे। यदि केवल हमारे पास पर्यायवाची के साथ कुछ भाषा थी ... जो अभी भी किसी तरह जानता है कि हम किन मामलों / अस्पष्ट उदाहरणों में चाहते हैं। तब मैं बस होता contents = (contents of file "path to file.txt" as string)
मास्टरएक्सिलो

2
यह begin {..open..} ensure {..close..} endब्लॉकों में किया जाना चाहिए
शैडोबक

3
@ArianFaurtosh नहीं, यह फ़ाइल को पढ़ने का एक और तरीका है - इसका मतलब यह नहीं है कि इसे एक बहाना माना जाएगा और इसे चलाया जाएगा! यह एक 'सरल' विधि के लिए एक भयानक दुष्परिणाम होगा।
मैथ्यू पढ़ें

1
@ डेविड आप केवल निम्नलिखित वन-लाइनर नहीं कर सकते हैं? contents = File.binread('path-to-file.tar.gz')देखें apidockFileका एक उपवर्ग है IO
वास

244

यदि आपको बाइनरी मोड की आवश्यकता है, तो आपको इसे कठिन तरीके से करने की आवश्यकता होगी:

s = File.open(filename, 'rb') { |f| f.read }

यदि नहीं, तो छोटा और मीठा है:

s = IO.read(filename)

माणिक 1.9.3+ में, IO.read आपको Encoding.default_external में एन्कोडिंग के साथ चिह्नित एक स्ट्रिंग देगा। मुझे लगता है कि (!) बाइट्स सभी के रूप में वे फ़ाइल में होंगे, इसलिए यह बिल्कुल "बाइनरी-सुरक्षित नहीं" है, लेकिन आपको इसे बाइनरी एन्कोडिंग के साथ टैग करना होगा यदि आप चाहते हैं।
१२:१४ पर १२:१४ पर jrochkind

यदि लघुता और मधुरता सार की है, तो एम्परसेंड-सिंबल s = File.open(filename, 'rb', &:read)
प्रिकोट

114

फ़ाइल को खुला छोड़ने से बचने के लिए, ब्लॉक करने के लिए File.open पास करना सबसे अच्छा है। इस तरह, ब्लॉक निष्पादित होने के बाद फ़ाइल बंद हो जाएगी।

contents = File.open('path-to-file.tar.gz', 'rb') { |f| f.read }

10
डेविड नेहमे की तुलना में यह एक बेहतर जवाब है क्योंकि फाइल डिस्क्रिप्टर एक परिमित प्रणाली संसाधन हैं और उन्हें समाप्त करना एक आम समस्या है जिससे आसानी से बचा जा सकता है।
जेफ मैककिन

17

ओएस एक्स पर ये मेरे लिए समान हैं ... क्या यह विंडोज़ में अतिरिक्त "\ r" हो सकता है?

किसी भी मामले में आप के साथ बेहतर हो सकता है:

contents = File.read("e.tgz")
newFile = File.open("ee.tgz", "w")
newFile.write(contents)

यह सबसे सरल समाधान की तरह लगता है।
दिशाकंदिनी

17

कुछ खुली / नज़दीकी सुरक्षा के बारे में कैसे।

string = File.open('file.txt', 'rb') { |file| file.read }

एक स्पष्ट .close क्यों नहीं? जैसे ओपी में file.close कब किया जाता है?
जोशुआ

2
File.open () {| फ़ाइल | ब्लॉक} ब्लॉक समाप्त होने पर स्वचालित रूप से बंद हो जाता है। ruby-doc.org/core-1.9.3/File.html#method-c-open
एलेक्स

14
यह हारून हिन्नी के उत्तर के समान है जो 2008 में पोस्ट किया गया था (ओपी की फ़ाइल और चर नामों का उपयोग नहीं करने के अलावा) ...
अबे वोल्कर

10

रूबी के पास बाइनरी रीडिंग है

data = IO.binread(path/filaname)

या अगर रूबी 1.9.2 से कम है

data = IO.read(path/file)

7

आप शायद बेस 64 में टार फाइल को एनकोड कर सकते हैं। बेस 64 आपको एक शुद्ध ASCII फाइल का प्रतिनिधित्व देगा जिसे आप एक सादे पाठ फ़ाइल में संग्रहीत कर सकते हैं। फिर आप पाठ को वापस डिकोड करके टार फाइल को पुनः प्राप्त कर सकते हैं।

आप कुछ ऐसा करें:

require 'base64'

file_contents = Base64.encode64(tar_file_data)

एक बेहतर विचार प्राप्त करने के लिए Base64 Rubydocs को देखें ।


महान, यह ऐसा लगता है जैसे यह भी काम करेगा! मुझे यह देखना होगा कि क्या किसी कारण से द्विआधारी सामग्री पढ़ने से खटास आती है।
क्रिस बंच

0

यदि आप बेस फ़ाइल को बेस 64 (और इसे एक सादे पाठ फ़ाइल में संग्रहीत) द्वारा एन्कोड कर सकते हैं तो आप उपयोग कर सकते हैं

File.open("my_tar.txt").each {|line| puts line}

या

File.new("name_file.txt", "r").each {|line| puts line}

cmd में प्रत्येक (टेक्स्ट) लाइन को प्रिंट करने के लिए।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.