how to extract .tar file - ruby

I am trying to extract .tar file using the below code, but getting invalid file format error, what is way to extract .tar file in ruby, FYI I am using window OS. I can see the file property as Tar archive (application/x-tar)
file_path = "/home/logan/skype/bill_2015-12-14.txt.tar"
extract = Gem::Package::TarReader.new(Zlib::GzipReader.open(file_name))
ERROR:
Zlib::GzipFile::Error: not in gzip format
from (irb):68:in `initialize'
from (irb):68:in `open'

A solution is given on The Buckblog and looks like this :
require 'rubygems/package'
File.open("chunky_png-1.3.4.gem", "rb") do |file|
Gem::Package::TarReader.new(file) do |tar|
tar.each do |entry|
if entry.file?
FileUtils.mkdir_p(File.dirname(entry.full_name))
File.open(entry.full_name, "wb") do |f|
f.write(entry.read)
end
File.chmod(entry.header.mode, entry.full_name)
end
end
end
end

Related

Making subdirectories while copying files

I have simple script that goes through txt file and copies files according to line in txt file
Here is it
require 'fileutils'
File.open("files.txt", "r") do |f|
f.each_line do |line|
line = line.chop #need to remove \n symbol from like
system("cp #{line} new/#{line}")
end
end
In my txt files - there are file path in each like like:
app/helpers/api/v1/application_helper.rb
However when i run script it fails if there is no such directory inside my new folder. So either i have to create them manually to reflect folder structure as in my txt file, or create with script.
Is there any way how can i do this in my script?
There are many ways to solve this. Here's one method:
require 'fileutils'
File.open("files.txt", "r") do |f|
f.each_line do |line|
line = line.chop
system("mkdir -p new/#{File.dirname(line)}")
system("cp #{line} new/#{line}")
end
end
I see you're requiring fileutils but not using any of its methods. You can use it like this
require 'fileutils'
File.open("files.txt", "r") do |f|
f.each_line do |line|
line = line.chop #need to remove \n symbol from like
FileUtils.mkdir_p(File.dirname(line))
FileUtils.cp(line, "new/#{line}")
end
end

No such file or directory?

Ruby is giving me this error:
C:/Ruby/new.rb:11:in `read': No such file or directory - m.txt (Errno::ENOENT)
from C:/Ruby/new.rb:11:in `<main>'
But I'm sure that there is such file, Here is my code:
text = File.read("m.txt").split('\n')
text.each do |x|
x.to_i
File.open("m.txt", "w") do |file|
file.gsub(x, x *10)
end
end
The line that is generating this error:
text = File.read("m.txt").split('\n')
I have checked several examples, like this: How can I read a file with Ruby?
And tried things like:
File.open("m.txt", "r+") do |infile|
while (line = infile.gets)
line.to_i.gsub(line, line *10)
end
end
But I'm still getting this error.
What I'm trying to do is: I have some numbers in text file like
12.2
432.3
3.43
.342
...
And I want to multiply each one by 10. Note I'm sure about the file and that it exists.
You have to provide the absolute path:
text = File.read("C:/Ruby/m.txt").split('\n')
since your current directory is not the same as your script's directory.
Alternatively, you should navigate to that specific folder and then run the script.
You can do it this way:
text = File.read("C:/Ruby/m.txt").split('\n')
File.open("C:/Ruby/m.txt", "w") do |file|
text.each do |x|
file.puts x.to_f * 10
end
end

Read compressed csv file on-the-fly

I have wrote some csv file and compress it, using this code:
arr = (0...2**16).to_a
File.open('file.bz2', 'wb') do |f|
writer = Bzip2::Writer.new f
CSV(writer) do |csv|
(2**16).times { csv << arr }
end
writer.close
end
I want to read this csv bzip2ed file (csv files compressed with bzip2). These files uncompressed look like:
1,2
4,12
5,2
8,7
1,3
...
So I tried this code:
Bzip2::Reader.open(filename) do |bzip2|
CSV.foreach(bzip2) do |row|
puts row.inspect
end
end
but when it is executed, it throws:
/Users/foo/.rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/csv.rb:1256:in `initialize': no implicit conversion of Bzip2::Reader into String (TypeError)
from /Users/foo/.rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/csv.rb:1256:in `open'
from /Users/foo/.rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/csv.rb:1256:in `open'
from /Users/foo/.rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/csv.rb:1121:in `foreach'
from worm_pathfinder_solver.rb:79:in `block in <main>'
from worm_pathfinder_solver.rb:77:in `open'
from worm_pathfinder_solver.rb:77:in `<main>'
Question:
What is wrong?
How should I do?
CSV.foreach assumes you're passing a file path to open. If you want to pass a stream to CSV you need to be more explicit and use CSV.new. This code will process a gzipped file:
Zlib::GzipReader.open(filename) do |gzip|
csv = CSV.new(gzip)
csv.each do |row|
puts row.inspect
end
end
Based on the brief docs you'll probably need send the read method on bzip2 object (not tested):
Bzip2::Reader.open(filename) do |bzip2|
CSV.foreach(bzip2.read) do |row|
# ^^^^
puts row.inspect
end
end
My guess would be that CSV tries to convert the Bzip2::Reader to a string but doesn't know how and simply throws the exception. You can manually read the data into a string and then pass THAT to CSV.
Though it's strange since it could handle Bzip2::Writer just fine.

Zipping an existing file with Rubyzip

I would like to use rubyzip to archive "zip" an existing file:
c:\textfile.txt
to
textfile.zip
I know how to add a stream to a text file:
require 'zip/zip'
Zip::ZipFile.open("mp.zip", Zip::ZipFile::CREATE) {
|zipfile|
zipfile.get_output_stream("text.txt") { |f| f.puts "Creating text file" }
}
but not how to add an existing file to a zip. Thanks for your help
This reads in the source file and writes it 1mb at a time to the zipfile.
I've been using something very similar in production for some time now.
require 'zip/zip'
Zip::ZipFile.open("mp.zip", Zip::ZipFile::CREATE) do |zipfile|
zipfile.get_output_stream("text.txt") do |out_file|
File.open("text.txt") do |in_file|
while blk = in_file.read(1024**2)
out_file << blk
end
end
end
end
Hope this answers your question.

Ruby Load multiple xml from a directory in a program to parse them

I want to load a set of xml from a directory and use REXML to parse all the xml in a loop.
I cant seem to create File Object after i start reading from a directory
i=1
filearray=Array.new
documentarray=Array.new
directory = 'xml'
Dir.foreach(directory).each { |file|
next if file == '.' or file == '..'
filearray[i]=File.open(directory +"/"+file)
i=i+1
Please help
You are opening the file, but not reading it. This is ugly, but will work:
require 'find'
files = []
directory = 'xml'
def get_contents(file)
contents = ""
contents = File.open(file).readlines
end
Find.find(directory) do |file|
next if FileTest.directory?(file)
files << get_contents(file)
end
Hope it helps

Resources