Ruby'de ikili dosyayı dize olarak okuyun


263

Bir tar dosyası almak ve bir dize (ve tersi) dönüştürmek için kolay bir yol gerekir. Ruby'de bunu yapmanın bir yolu var mı? En iyi denemem şuydu:

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

Bunun bir dizeye dönüştürmek için yeterli olacağını düşündüm, ama sonra böyle yazmaya çalıştığımda ...

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

Aynı dosya değil. Bunu yapmak ls -l, dosyaların farklı boyutlarda olduğunu, ancak oldukça yakın olduklarını gösterir (ve dosyayı açmak içeriğin çoğunu olduğu gibi gösterir). Yaptığım küçük bir hata veya bunu başarmak için tamamen farklı (ama uygulanabilir) bir yol var mı?


3
Bu bir gzipli tar dosyası (umarım). "Hat" yok. Pls ne elde etmeye çalıştığınızı açıklığa kavuşturuyor.
Brent.Longborough

sıkıştırılmış verilere veya sıkıştırılmamış içeriğe bakmaya mı çalışıyorsunuz?
David Nehme

sıkıştırılmış bir veri akışındaki karakterlerin bir satırın sonunu tanımlayan "\ n"
değerine

Aksi takdirde tercih edilen cevap olacağından , bu soru " İkili dosyayı dizeye dönüştür" olarak yeniden adlandırılmalıdır IO.read.
Ian

Yanıtlar:


397

İlk olarak, dosyayı ikili dosya olarak açmalısınız. Ardından tüm dosyayı tek bir komutta okuyabilirsiniz.

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

Bu, tüm dosyayı bir dizede alacaktır.

Bundan sonra, muhtemelen istiyorsun file.close. Bunu yapmazsanız file, çöp toplanana kadar kapatılmaz, bu yüzden açıkken sistem kaynaklarının hafif bir israfı olur.


22
İkili bayrak yalnızca Windows ile ilgilidir ve dosya tanımlayıcısını açık bırakır. File.read (...) daha iyidir.
Daniel Huckstep

Pek çok insanın bunu araması ve tek katmanlı bir çözüm olarak yapıştırmasıyla ilgili bir sorun var mı (stackoverflow'daki birçok şey gibi)? Sonuçta, işe yarıyor ve bu işlevlerin adı yakut kütüphane tasarımcılarının keyfi bir seçimiydi. Eğer sadece eşanlamlı bir dilimiz olsaydı ... bu hala bir şekilde uç durumlarda / belirsiz örneklerde ne istediğimizi biliyor. Sonra sadece yapardım contents = (contents of file "path to file.txt" as string).
masterxilo

2
Bu begin {..open..} ensure {..close..} endbloklar halinde yapılmalıdır
shadowbq

3
@ArianFaurtosh Hayır, bu dosyayı okumak için başka bir yöntem - bu, çalıştırılabilir ve çalıştırılacağı anlamına gelmiyor! Bu basit bir 'okuma' yöntemi için korkunç bir yan etki olacaktır.
Matthew,

1
@David aşağıdaki tek astarı yapamaz mıydınız? contents = File.binread('path-to-file.tar.gz')Bkz apidock . Filebir alt sınıfıdır IO.
vas

244

İkili moda ihtiyacınız varsa, bunu zor bir şekilde yapmanız gerekir:

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

Değilse, daha kısa ve daha tatlı:

s = IO.read(filename)

1.9.3 ve sonraki sürümlerde, IO.read size Encoding.default_external içindeki kodlama ile işaretlenmiş bir dize verecektir. Ben düşünüyorum dosyada olduğu gibi aynen "ikili-güvenli değil" değil yani bayt hepsi olacak (?), Ama bu istediğin buysa ikili kodlamasıyla etiketine bunu gerekecek.
jrochkind

Kısalık ve tatlılık çok s = File.open(filename, 'rb', &:read)
önemliyse

114

Dosyayı açık bırakmamak için File.open dosyasına bir blok geçirmek en iyisidir. Bu şekilde, blok yürütüldükten sonra dosya kapatılacaktır.

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

10
Bu, David Nehme'den daha iyi bir cevaptır çünkü dosya tanımlayıcıları sonlu bir sistem kaynağıdır ve bunları tüketmek, kolayca önlenebilecek yaygın bir sorundur.
Jeff McCune

17

os x üzerinde bu benim için aynı ... bu belki windows ekstra "\ r" olabilir?

her durumda daha iyi olabilirsiniz:

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

Bu en basit çözüm gibi görünüyor.
Dishcandanty


10

Ruby ikili okuma var

data = IO.binread(path/filaname)

veya Ruby 1.9.2'den küçükse

data = IO.read(path/file)

7

Muhtemelen tar64 dosyasını Base64'te kodlayabilirsiniz. Base 64 size düz metin dosyasında saklayabileceğiniz saf ASCII temsilini verecektir. Daha sonra metni geri çözerek tar dosyasını alabilirsiniz.

Gibi bir şey yapıyorsun:

require 'base64'

file_contents = Base64.encode64(tar_file_data)

Daha iyi bir fikir edinmek için Base64 Rubydocs'a bakın .


Harika, bu da işe yarayacak gibi görünüyor! Herhangi bir nedenle ikili içeriği okumak ekşi olup olmadığını kontrol etmek zorunda kalacak.
Chris Bunch

0

Tar dosyasını Base64 ile kodlayabilir (ve düz metin dosyasında saklayabilirseniz)

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

veya

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

cmd'deki her (metin) satırı yazdırmak için.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.