อ่านไฟล์ไบนารีเป็นสตริงใน Ruby


263

ฉันต้องการวิธีง่ายๆในการใช้ไฟล์ tar และแปลงเป็นสตริง (และในทางกลับกัน) มีวิธีการทำเช่นนี้ใน Ruby หรือไม่? ความพยายามที่ดีที่สุดของฉันคือ:

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
นั่นคือไฟล์ tar gzipped (ฉันหวังว่า) ไม่มี "เส้น" กรุณาชี้แจงสิ่งที่คุณพยายามที่จะบรรลุ
Brent.Longborough

คุณพยายามดูข้อมูลที่ถูกบีบอัดหรือเนื้อหาที่ไม่มีการบีบอัดหรือไม่?
David Nehme

ดังนั้นตัวอักษรในสตรีมข้อมูลที่บีบอัดจะมีโอกาสประมาณ 1 ใน 256 ที่จะลงจอดบน "\ n" กำหนดจุดสิ้นสุดของบรรทัดและไม่เป็นไรถ้าไม่คาดว่า "\ r" ด้วยโปรดดูคำตอบด้านล่าง
Purfideas

คำถามนี้ควรตั้งชื่อใหม่เป็น "แปลงไฟล์ไบนารีเป็นสตริง" เนื่องจากIO.readอาจเป็นคำตอบที่ต้องการ
เอียน

คำตอบ:


397

ก่อนอื่นคุณควรเปิดไฟล์เป็นไฟล์ไบนารี่ จากนั้นคุณสามารถอ่านไฟล์ทั้งหมดในหนึ่งคำสั่ง

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

คุณจะได้รับไฟล์ทั้งหมดในสตริง

file.closeหลังจากนั้นคุณอาจต้องการ หากคุณไม่ทำเช่นนั้นfileจะไม่ถูกปิดจนกว่าจะมีการรวบรวมขยะดังนั้นจะเป็นการสิ้นเปลืองทรัพยากรระบบเล็กน้อยในขณะที่เปิดอยู่


22
แฟล็กไบนารีเกี่ยวข้องเฉพาะกับ Windows และนี่จะเปิดไฟล์ descriptor ไว้ File.read (... ) ดีกว่า
Daniel Huckstep

มีอะไรผิดปกติหรือไม่ที่มีคนจำนวนมากมองหาสิ่งนี้และคัดลอกวางมันเป็นโซลูชั่นแบบหนึ่งซับ (เช่นสิ่งต่าง ๆ มากมายใน stackoverflow)? ท้ายที่สุดแล้วมันใช้งานได้และชื่อของฟังก์ชั่นเหล่านี้เป็นเพียงตัวเลือกโดยพลการของนักออกแบบห้องสมุดทับทิม ถ้าเพียงเรามีภาษาที่มีคำพ้องความหมาย ... ซึ่งยังคงรู้อย่างชัดเจนว่าสิ่งที่เราต้องการในกรณีขอบ / กรณีที่ไม่ชัดเจน contents = (contents of file "path to file.txt" as string)แล้วฉันจะเป็นเพียงแค่
masterxilo

2
สิ่งนี้ควรทำในbegin {..open..} ensure {..close..} endบล็อก
shadowbq

3
@ArianFaurtosh ไม่เป็นอีกวิธีในการอ่านไฟล์ - มันไม่ได้หมายความว่ามันจะถือว่าเป็น exectuable และเรียกใช้! นั่นจะเป็นผลข้างเคียงที่น่ากลัวสำหรับวิธีการ 'อ่าน' ที่ง่าย
Matthew อ่าน

1
@ David คุณไม่สามารถทำหนึ่งซับต่อไปนี้ได้ใช่ไหม? contents = File.binread('path-to-file.tar.gz')ดูapidock Fileเป็น subclass IOของ
vas

244

หากคุณต้องการโหมดไบนารีคุณจะต้องทำอย่างหนัก:

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

ถ้าไม่สั้นและหวานคือ:

s = IO.read(filename)

ใน ruby ​​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
นี่เป็นคำตอบที่ดีกว่าของ David Nehme เพราะตัวอธิบายไฟล์เป็นทรัพยากรระบบที่ จำกัด และการใช้คำศัพท์เหล่านี้เป็นปัญหาทั่วไปที่สามารถหลีกเลี่ยงได้อย่างง่ายดาย
เจฟฟ์ McCune

17

บน OS x สิ่งเหล่านี้เหมือนกันสำหรับฉัน ... นี่อาจเป็นพิเศษ "\ r" ใน windows

ในกรณีใด ๆ คุณอาจจะดีกว่าด้วย:

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

ดูเหมือนว่าทางออกที่ง่ายที่สุด
Dishcandanty

17

วิธีการเกี่ยวกับความปลอดภัยเปิด / ปิดบางส่วน

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

ทำไมไม่ชัดเจน. ปิด เช่นในไฟล์ OP.close เมื่อเสร็จแล้ว?
Joshua

2
File.open () {| file | block} ปิดโดยอัตโนมัติเมื่อบล็อกสิ้นสุดลง ruby-doc.org/core-1.9.3/File.html#method-c-open
อเล็กซ์

14
นี่เป็นคำตอบเดียวกับของAaron Hinniที่โพสต์ในปี 2008 (ยกเว้นไม่ได้ใช้ไฟล์ OP และชื่อตัวแปร) ...
Abe Voelker

10

Ruby มีการอ่านไบนารี

data = IO.binread(path/filaname)

หรือน้อยกว่า Ruby 1.9.2

data = IO.read(path/file)

7

คุณสามารถเข้ารหัสไฟล์ tar ใน Base64 ฐาน 64 จะให้การแทน ASCII จริงของไฟล์ที่คุณสามารถเก็บไว้ในไฟล์ข้อความธรรมดา จากนั้นคุณสามารถเรียกคืนไฟล์ tar ได้โดยถอดรหัสข้อความกลับ

คุณทำสิ่งที่ชอบ:

require 'base64'

file_contents = Base64.encode64(tar_file_data)

ดูที่ Base64 Rubydocsเพื่อทำความเข้าใจให้ดีขึ้น


เยี่ยมมากดูเหมือนว่ามันจะใช้ได้เช่นกัน! ฉันจะต้องตรวจสอบว่าด้วยเหตุผลบางอย่างอ่านเนื้อหาไบนารีจะเปรี้ยว
Chris Bunch

0

หากคุณสามารถเข้ารหัสไฟล์ tar โดย Base64 (และเก็บไว้ในไฟล์ข้อความธรรมดา) ที่คุณสามารถใช้ได้

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

หรือ

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

เพื่อพิมพ์แต่ละบรรทัด (ข้อความ) ใน cmd

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.