2012-09-25 15 views
36

¿Cuándo se considera adecuado utilizar Ruby's StringIO en lugar de usar StringIO?¿Cuáles son las ventajas de utilizar StringIO en Ruby en lugar de String?

Creo que entiendo la diferencia fundamental entre ellos, como se destaca por "What is ruby's StringIO class really?", que StringIO permite leer y escribir desde/a una cadena en una secuencia orientada a la secuencia. Pero, ¿qué significa esto prácticamente?

¿Cuál es un buen ejemplo de uso práctico para usar StringIO cuando simplemente usar String realmente no lo cortaría?

Respuesta

59

Básicamente, hace que una cadena parezca un objeto IO, de ahí el nombre StringIO.

La clase StringIO tiene read y write métodos, por lo que se puede pasar a partes de su código que fueron diseñadas para leer y escribir desde archivos o sockets. Es bueno si tiene una cadena y desea que se vea como un archivo para probar su código de archivo.

def foo_writer(file) 
    file.write "foo" 
end 

def test_foo_writer 
    s = StringIO.new 
    foo_writer(s) 
    raise "fail" unless s.string == "foo" 
end 
+3

Interesante. ¿Hay alguna ventaja (con respecto al uso de memoria) en el uso de StringIO en comparación con String? –

+3

Probablemente no. Si observa el código fuente, parece que solo mantiene una referencia a un objeto String internamente, por lo que usará un poco más de memoria que una cadena normal: https://github.com/ruby/ruby/blob/trunk/ext /stringio/stringio.c –

+2

Si bien no hay una ventaja de memoria si está usando 'StringIO', si diseña sus funciones para objetos IO puede hacer cosas como leer desde un archivo y, de lo contrario, operaciones de pipe juntas. Entonces, una función que toma un objeto IO puede usar menos memoria si se usa con una clase apropiada. Por lo tanto, esto le permite operar en un String o un objeto IO posiblemente más eficiente de la misma manera. –

23

me gusta mucho StringIO para el caso de uso de añadir línea por línea de texto sin tener que utilizar "\n" una y otra vez. Por ejemplo, en lugar de esto:

s = '' 
s << "\n" << "some text on a new line" 
s << "\nthis is pretty awkward" 
s = "#{s}\neven more ugly!" 

que pueda hacer esto

s = StringIO.open do |s| 
    s.puts 'adding newlines with puts is easy...' 
    s.puts 'and simple' 
    s.string 
end 

que es mucho más limpio. No es necesario utilizar la forma de bloque de String.IO, puede crear un objeto como el siguiente: s = StringIO.new pero, independientemente, asegúrese de tener en cuenta que se accede a la cadena actual a través del método StringIO#string.

+1

Normalmente uso' Array # << 'y luego' Array # join' para este tipo de cosas, aunque usar 'StringIO' es una gran técnica. – jc00ke

+2

@ jc00ke Yo también. Ahora que estoy más familiarizado con Ruby, mis hábitos dan como resultado un código que favorece al ** lector ** ... Para entender mejor lo que quiero decir, considere lo siguiente: Para el codificador, usar 'Array' como usted describe es conveniente para * write * in, sure, pero cuando * reading * code, el nombre de clase 'StringIO' es un ** far ** better indicator of purpose. Sin mencionar 'Array' es una estructura de datos fundamentalmente diferente. Además, la necesidad de usar 'Array # join' implica un exceso de código 'baggage' y, lo que es peor, ¡complejidad! Por ejemplo, su argumento está configurado por defecto a un global que está sujeto a cambios. –

Cuestiones relacionadas