How to append some data at the beginning of a file

Discussion in 'Ruby' started by Uday Thokala, Aug 24, 2007.

  1. Uday Thokala

    Uday Thokala Guest

    Hi,

    I am newbie to Ruby so please spare me if the question looks silly. My
    question is how to append data at the beginning of a file?

    Suppose I have a file named test.rb which contains some text, say
    "This is first line
    This is second line"

    Now if I wanted to append some data at the beginning of the file, lets
    say
    "This line has to be appended at the beginning of the file"

    My program

    filename = File.open("test","a") do |f|
    f.puts "This line should appear at the top of each file";
    f.close();
    end

    is appending at the end of the file. So the output is:

    "This is first line
    This is second line
    This line has to be appended at the beginning of the file"

    I searched the forums and found that if I use IO:seek and then try to
    append data to the existing file the earlier content which are in the
    first lines will get replaced. Is there any easy solution so that I can
    get a final output like:

    "This line has to be appended at the beginning of the file
    This is first line
    This is second line"
    --
    Posted via http://www.ruby-forum.com/.
     
    Uday Thokala, Aug 24, 2007
    #1
    1. Advertising

  2. > I am newbie to Ruby so please spare me if the question looks silly. My
    > question is how to append data at the beginning of a file?


    This is not so much a Ruby question, since nearly no operating system
    directly
    allows appending data to the beginning of a file. The general solution
    is to create a new file, putting there the data in the right order,
    delete
    the old file and rename the new file to the name of the old one.

    Renaming a file is done like this:

    File.rename("oldname","newname")=20

    This raises the exception SystemCallError, if renaming fails.

    HTH

    Ronald
    --=20
    Ronald Fischer <>
    Phone: +49-89-452133-162
     
    Ronald Fischer, Aug 24, 2007
    #2
    1. Advertising

  3. Uday Thokala

    Uday Thokala Guest

    Ronald Fischer wrote:
    >> I am newbie to Ruby so please spare me if the question looks silly. My
    >> question is how to append data at the beginning of a file?

    >
    > This is not so much a Ruby question, since nearly no operating system
    > directly
    > allows appending data to the beginning of a file.


    Thanks Ronald for your comments. I am wondering may be ruby got some way
    around it.

    > The general solution
    > is to create a new file, putting there the data in the right order,
    > delete
    > the old file and rename the new file to the name of the old one.
    >
    > Renaming a file is done like this:
    >
    > File.rename("oldname","newname")


    Yeah I implemented the above mentioned solution and it's working fine.
    The code is

    newfile = File.new("test1","w")
    newfile.puts "This line should appear at the top of each file";

    oldfile = File.open("test", "r+")
    oldfile.each_line { |line| newfile.puts line}

    oldfile.close();
    newfile.close();

    File.delete("test");
    File.rename("test1", "test");

    Thanks,
    Uday.
    --
    Posted via http://www.ruby-forum.com/.
     
    Uday Thokala, Aug 24, 2007
    #3
  4. > Thanks Ronald for your comments. I am wondering may be ruby=20
    > got some way=20
    > around it.


    It could, but I think it just happens too rare that someone
    wants to do this. In more than 2 decades of programming, I
    had this need only two or three times, for example.

    > newfile =3D File.new("test1","w")
    > newfile.puts "This line should appear at the top of each file";
    >=20
    > oldfile =3D File.open("test", "r+")
    > oldfile.each_line { |line| newfile.puts line}
    > oldfile.close();


    or simply

    newfile.puts(File.read("test"))

    so you don't need the Ruby variable 'oldfile'.

    > newfile.close();
    >=20
    > File.delete("test");
    > File.rename("test1", "test");



    --=20
    Ronald Fischer <>
    Phone: +49-89-452133-162
     
    Ronald Fischer, Aug 24, 2007
    #4
  5. Uday Thokala

    Jano Svitok Guest

    On 8/24/07, Ronald Fischer <> wrote:
    > > Thanks Ronald for your comments. I am wondering may be ruby
    > > got some way
    > > around it.

    >
    > It could, but I think it just happens too rare that someone
    > wants to do this. In more than 2 decades of programming, I
    > had this need only two or three times, for example.
    >
    > > newfile = File.new("test1","w")
    > > newfile.puts "This line should appear at the top of each file";
    > >
    > > oldfile = File.open("test", "r+")
    > > oldfile.each_line { |line| newfile.puts line}
    > > oldfile.close();

    >
    > or simply
    >
    > newfile.puts(File.read("test"))
    >
    > so you don't need the Ruby variable 'oldfile'.
    >
    > > newfile.close();
    > >
    > > File.delete("test");
    > > File.rename("test1", "test");


    1. it's better to use block form of File.open:

    File.open("test1","w") do |newfile|
    newfile.puts "This line should appear at the top of each file"

    File.open("test", "r+") do |oldfile|
    oldfile.each_line { |line| newfile.puts line}
    end
    end

    File.delete("test");
    File.rename("test1", "test");

    The difference is that in case of an exception the file is closed
    automatically. Otherwise you have to wait for garbage collector. It's
    a good habit to get used to this style.

    2. newfile.puts(File.read("test")) will read the entire file into
    memory. Don't do this on large files - use the original way (or even
    better, loop over the file with File#read(size)). For small files,
    this read() is better.

    3. newfile.puts(File.read("test")) will put an extra newline at the
    end. Use either
    newfile << File.read("test")
    or
    newfile.write(File.read("test"))
     
    Jano Svitok, Aug 24, 2007
    #5
  6. 2007/8/24, Uday Thokala <>:
    > Ronald Fischer wrote:
    > >> I am newbie to Ruby so please spare me if the question looks silly. My
    > >> question is how to append data at the beginning of a file?

    > >
    > > This is not so much a Ruby question, since nearly no operating system
    > > directly
    > > allows appending data to the beginning of a file.

    >
    > Thanks Ronald for your comments. I am wondering may be ruby got some way
    > around it.
    >
    > > The general solution
    > > is to create a new file, putting there the data in the right order,
    > > delete
    > > the old file and rename the new file to the name of the old one.
    > >
    > > Renaming a file is done like this:
    > >
    > > File.rename("oldname","newname")

    >
    > Yeah I implemented the above mentioned solution and it's working fine.
    > The code is
    >
    > newfile = File.new("test1","w")
    > newfile.puts "This line should appear at the top of each file";
    >
    > oldfile = File.open("test", "r+")
    > oldfile.each_line { |line| newfile.puts line}
    >
    > oldfile.close();
    > newfile.close();
    >
    > File.delete("test");
    > File.rename("test1", "test");


    Just a few remarks: better return to your old habit and use the block
    form of File.open (btw, you do not need to close the file, File#open
    takes care of that when the block is left - even in case of an
    exception).

    You don't need to terminate lines with ";".

    Also, you can use variables to make your life easier:

    file = "test"
    tmp = file + "~"

    File.open(tmp, "w") do |out|
    out.puts "This line should appear at the top of each file"

    File.foreach file do |line|
    out.puts line
    end
    end

    File.delete file
    File.rename tmp, file

    Kind regards

    robert
     
    Robert Klemme, Aug 24, 2007
    #6
  7. > 2. newfile.puts(File.read("test")) will read the entire file into
    > memory. Don't do this on large files - use the original way (or even
    > better, loop over the file with File#read(size)). For small files,
    > this read() is better.


    Good point! (Only that *prepending* data to a file which is so big that
    it would be a memory hog, is probably a nightmare anyway.

    > 3. newfile.puts(File.read("test")) will put an extra newline at the
    > end. Use either
    > newfile << File.read("test")
    > or
    > newfile.write(File.read("test"))


    Right, I overlooked this! Thanks for pointing this out.

    Ronald
     
    Ronald Fischer, Aug 24, 2007
    #7
  8. My solution for this question would be monkey patching the File class:

    require 'tempfile'

    class File
    def self.prepend(path, string)
    Tempfile.open File.basename(path) do |tempfile|
    # shift string to tempfile
    tempfile << string

    File.open(path, 'r+') do |file|
    # append original data to tempfile
    tempfile << file.read
    # reset file positions
    file.pos = tempfile.pos = 0
    # copy tempfile back to original file
    file << tempfile.read
    end
    end
    end
    end

    Regards
    Florian
     
    Florian Aßmann, Aug 24, 2007
    #8
  9. Uday Thokala

    Tom Reilly Guest

    Here is a small example to write something at the beginning of a file
    which works fine so long as the length of this item doesn't change.

    #-----------------------------------------------
    #timer to track time I work on medicine
    #version 1.3 8/12/07
    # sleep added
    # total time computed and displayed

    rw = "r+"
    $stdout.sync = true
    begin
    fo = File.new("time_study.txt",rw)
    rescue
    rw = "w+"
    retry
    end
    old_chapter = fo.read(3)
    if old_chapter == nil
    fo.write("00\t *** \t \n")
    p "Start a new file"
    else
    puts old_chapter
    end



    fo.seek(0,IO::SEEK_SET)
    time_start = Time.now

    prev_chapter = fo.read(2)
    puts "Start at chapter #{prev_chapter}"
    puts "Enter chapter to start"
    fo.seek(0,IO::SEEK_SET)
    chapter = gets.chomp
    fo.write("#{chapter}")
    time_end = Time.now
    fo.seek(0,IO::SEEK_END)
    fo.write("#{time_start.to_i} #{time_end.to_i} #{(time_end -
    time_start)}\n")
    fo.seek(0,IO::SEEK_SET)
    total_time = 0.0
    fo.each do |x|
    xa = x.split
    total_time += xa[2].to_f
    end
    puts "Total time Hours = #{total_time / 3600.0}"
    sleep 10
    fo.close
     
    Tom Reilly, Aug 27, 2007
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. bmlclemson08

    Beginning programmer... I need some help.

    bmlclemson08, Feb 5, 2006, in forum: C Programming
    Replies:
    8
    Views:
    292
    Michael Mair
    Feb 5, 2006
  2. HYRY
    Replies:
    10
    Views:
    632
    Bruno Desthuilliers
    Sep 26, 2007
  3. Sarika Patil
    Replies:
    2
    Views:
    145
    Heesob Park
    Mar 17, 2009
  4. Jesse B.
    Replies:
    9
    Views:
    249
    Jesse B.
    Mar 27, 2010
  5. PerlFAQ Server
    Replies:
    0
    Views:
    400
    PerlFAQ Server
    Feb 24, 2011
Loading...

Share This Page