2015-07-05 15 views
5

Recentemente ho imparato Ruby. Ho riscontrato un problema mentre sto scrivendo una sottoclasse di File.Ruby IO - Input/output di file indirettamente

class MyFile < File 

end 

file_path = "text_file" 

file = MyFile.open(file_path) do | file | 
    file.each_line do | line | 
     puts line 
    end 
    file.close 
end 

risultato:

line 1 
line 2 
line 3 

se voglio uscita chiamando un metodo:

class MyFile < File 
    def foo 
     self.each_line do | line | 
      puts line 
     end 
    end 
end 

file_path = "text_file" 

my_file = MyFile.open(file_path) do | file | 
    file.foo 
    file.close 
end 

Risultato:

/Users/veightz/Developer/RubyCode/io_error.rb:4:in `write': not opened for writing (IOError) 
    from /Users/veightz/Developer/RubyCode/io_error.rb:4:in `puts' 
    from /Users/veightz/Developer/RubyCode/io_error.rb:4:in `block in foo' 
    from /Users/veightz/Developer/RubyCode/io_error.rb:3:in `each_line' 
    from /Users/veightz/Developer/RubyCode/io_error.rb:3:in `foo' 
    from /Users/veightz/Developer/RubyCode/io_error.rb:20:in `block in <main>' 
    from /Users/veightz/Developer/RubyCode/io_error.rb:19:in `open' 
    from /Users/veightz/Developer/RubyCode/io_error.rb:19:in `<main>' 

poi aggiungo metodo nuovo bar

class MyFile < File 
    def foo 
     self.each_line do | line | 
      puts line 
     end 
    end 

    def bar 
     self.each_line do | line | 
      p line 
     end 
    end 
end 

my_file = MyFile.open(file_path) do | file | 
    file.bar 
    file.close 
end 

Risultato:

"line 1\n" 
"line 2\n" 
"line 3\n" 

così, sono così confuso su IO in Ruby.Why puts line in foo non può funzionare bene.

risposta

6

C'è un puts method in IO e IO è una superclasse di File. Ciò significa che questo:

puts line 

è in realtà piuttosto che self.putsKernel#puts in quanto è praticamente ovunque che si utilizza puts. Da qui il messaggio di errore "non aperto per la scrittura".

È necessario un ricevitore esplicito per ottenere lo stesso effetto di Kernel#puts; Kernel#puts è equivalente a $stdout.puts modo che si desidera:

file.each_line do | line | 
    $stdout.puts line 
end 

La versione p line funziona bene, perché non esiste un metodo IO#p o File#p, p è Kernel#p proprio come è ovunque.

Ricorda che non abbiamo funzioni in Ruby come le altre lingue hanno funzioni globali. I metodi che si utilizzano come una funzione sono quasi sempre metodi in Kernel.

0

È anche possibile utilizzare $> "flusso di output predefinito" per reindirizzare l'output di metodi come Kernel # puts ... che è l'unico lavoro di $>.

def foo 
    self.each_line do | line | 
    $>.puts line 
    end 
end 

ho aggiunto un metodo più che mostra come si può anche prendere in prestito "richiedono" altre gemme (gemma per esempio pretty-stampato) e l'uso di class << slef .... Quindi, lei ha detto "Di recente ho imparato Ruby ": |

Il seguente funziona come previsto.

#!/usr/bin/env ruby 

require 'pp' 

class MyFile < File 
class << self 

    def foo 
     each_line do | line | 
      $>.puts line 
     end 
    end 



    def bar 
     each_line do | line | 
      p line 
     end 
    end 


    def bam 
    each_line do | line | 
      pp line 
     end 
    end 

end 

file_path = "/Users/path/ofdirectory_to/somefile.txt" 

my_file = MyFile.open(file_path) do | file | 

    file.bam 
    file.foo 
    file.bar 
    File.close 
end 

Nota: l'uso di NameOfClass < < auto ...Wana maggiori informazioni SO question

Ciò che sembra btter:

uscita non-abbastanza-stampato da p è:

#<PP:0x81fedf0 @genspace=#<Proc:0x81feda0>, @group_queue=#<PrettyPrint::GroupQueue:0x81fed3c @queue=[[#<PrettyPrint::Group:0x81fed78 @breakables=[], @depth=0, @break=false>], []]>, @buffer=[], @newline="\n", @group_stack=[#<PrettyPrint::Group:0x81fed78 @breakables=[], @depth=0, @break=false>], @buffer_width=0, @indent=0, @maxwidth=79, @output_width=2, @output=#<IO:0x8114ee4>> 

uscita pretty-stampato da PP è:

#<PP:0x81fedf0 
@buffer=[], 
@buffer_width=0, 
@genspace=#<Proc:0x81feda0>, 
@group_queue= 
    #<PrettyPrint::GroupQueue:0x81fed3c 
    @queue= 
    [[#<PrettyPrint::Group:0x81fed78 @break=false, @breakables=[], @depth=0>], 
    []]>, 
@group_stack= 
    [#<PrettyPrint::Group:0x81fed78 @break=false, @breakables=[], @depth=0>], 
@indent=0, 
@maxwidth=79, 
@newline="\n", 
@output=#<IO:0x8114ee4>, 
@output_width=2> 

Per ulteriori circa pp vai qui Ruby-Doc

Problemi correlati