0

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

randy newfield
  • 1,221
  • 3
  • 25
  • 38

1 Answers1

0

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
sxm1972
  • 722
  • 8
  • 15