I am writing code that utilizes the StringIO
object and rubygems/package
which includes TarWriter
and TarReader
.
My end goal is to be able to call a method add_file
to add/append a file to the archive and then call a method read_all_files
to read back the file names and contents of the added files.
My two methods currently stand as:
require "rubygems/package"
def add_file(io)
Gem::Package::TarWriter.new(io) do |tar|
puts "What is the name of the file you wish to add?"
print "> "
filename = gets.chomp
puts
tar.add_file(filename, 0755) do |file|
puts "Enter the file contents"
print "> "
contents = gets.chomp
file.write contents
end
end
end
def read_all_files(io)
Gem::Package::TarReader.new(io) do |tar|
tar.each do |tarfile|
puts "File Name> #{tarfile.full_name}"
puts tarfile.read
end
end
end
#usage:
io = StringIO.new
add_file(io)
add_file(io)
add_file(io)
io.rewind
read_all_files(io)
Output:
What is the name of the file you wish to add?
> test1
Enter the file contents
> this is the first test
What is the name of the file you wish to add?
> test2
Enter the file contents
> this is the second test
What is the name of the file you wish to add?
> test3
Enter the file contents
> this is the third test
File Name> test1
this is the first test
The problem that is currently happening is that for one reason or another read_all_files
is only reading a single file although I should be iterating all three files.
I have tried various ideas such as rewinding the file after each add_file
call, but this overwrites the tar file each time. I have also tried to seek to the end of the io object and add the files but this also does not function correctly.
I initially thought that TarWriter
would read the header and automatically append new files to the tar archive in the correct position, but it seems that this is not the case.
This seems as if I will need to read all files from the StringIO
tar archive to variables and then re-add all the files each time a new file is added. Is this proper behavior? Is there a way around this?
Thanks
The problem is because you are creating a new TarWriter each time you call add_file. You need to preserve the TarWriter object between calls to add_file. e.g.
require "rubygems/package"
def add_file(io, tar=nil)
tar = Gem::Package::TarWriter.new(io) if tar.nil?
puts "What is the name of the file you wish to add?"
print "> "
filename = gets.chomp
puts
tar.add_file(filename, 0755) do |file|
puts "Enter the file contents"
print "> "
contents = gets.chomp
file.write contents
end
tar
end
def read_all_files(io)
Gem::Package::TarReader.new(io) do |tar|
puts 'TarReader created'
tar.each do |tarfile|
puts "File Name> #{tarfile.full_name}"
puts tarfile.read
end
end
end
io = StringIO.new
tar1 = add_file(io)
tar1 = add_file(io, tar1)
tar1 = add_file(io, tar1)
io.rewind
read_all_files(io)
The output from this:
C:\Users\Administrator\test>ruby tarwriter.rb
What is the name of the file you wish to add?
> x.txt
Enter the file contents
> xxx
What is the name of the file you wish to add?
> z.txt
Enter the file contents
> zzz
What is the name of the file you wish to add?
> y.txt
Enter the file contents
> yyy
TarReader created
File Name> x.txt
xxx
File Name> z.txt
zzz
File Name> y.txt
yyy