=encoding utf8

=head1 NAME

perlopentut - Recetas sencillas para abrir archivos y tuberías en Perl   ***
DOCUMENTO SIN REVISAR ***

=head1 DESCRIPCIÓN

Cualquier cosa que haga de E/S en un archivo en Perl, lo debe hacer en Perl a
través de lo que se conoce como B<filehandle> (identificador de archivo). Un
identificador de archivo es un nombre interno para un archivo externo. Es
trabajo de la función C<open> hacer la asociación entre el nombre interno y
el nombre externo, y es trabajo de la función C<close> romper esa asociación.

Para su comodidad, Perl ajusta unos pocos identificadores de archivo que ya
están abiertos cuando corre el programa. Entre ellos están C<STDIN>,
C<STDOUT>, C<STDERR> y C<ARGV>. Ya que están pre-abiertos, puede usarlos
enseguida sin tener el problema de tener que abrirlos por usted mismo:

    print STDERR "Esto es un mensaje de depuración.\n";

    print STDOUT "Por favor, escriba algo: ";
    $respuesta = <STDIN> // die "¿Cómo que no hay entrada?";
    print STDOUT "¡Gracias!\n";

    while (<ARGV>) { ... }

Como puede ver en estos ejemplos, C<STDOUT> y C<STDERR> son controladores de
salida, y C<STDIN> y C<ARGV> son controladores de entrada. Están en letras
mayúsculas porque son reservadas para Perl, como lo son el array C<@ARGV> y el
hash C<%ENV>. Sus asociaciones externas fueron ajustadas por su shell.

Necesitará abrir cualquier otro identificador de archivo. A pesar de que hay
muchas variantes, la forma más común de llamar a la función open() de Perl
es la de tres argumentos y un valor de retorno:

C<    I<OK> = open(I<IDENTIFICADOR>, I<MODO>, I<RUTA_AL_ARCHIVO>)>

donde:

=over

=item I<OK>

será un valor definido si el open tuvo éxito, y C<undef> si falló;

=item I<IDENTIFICADOR>

debería ser una variable escalar indefinida que será rellenada por la
función C<open> si tuvo éxito;

=item I<MODO>

es el modo de acceso y la forma de codificación con qué abrir el archivo;

=item I<RUTA_AL_ARCHIVO>

es el nombre externo del archivo que quiere abrir.

=back

La mayor parte de la complejidad de la función C<open> reside en los muchos
posibles valores que puede tomar el parámetro I<MODO>.

Una última cosa antes de que le mostremos cómo usar open: abrir archivos en
Perl no les bloquea de forma automática (normalmente). Vea L<perlfaq5> para
ver cómo bloquear.

=head1 Abrir archivos de texto

=head2 Abrir archivos de texto para lectura

Si quiere leer desde un archivo de texto, primero ábralo en modo de solo
lectura, así:

    my $nombre_archivo = "/alguna/ruta/al/archivotexto/va/aqui";
    my $codificacion   = ":encoding(UTF-8)";
    my $controlador    = undef;     # se rellenará en caso de éxito

    open($controlador, "<  $codificacion", $nombre_archivo)
        || die "$0: no puedo abrir $nombre_archivo para lectura: $!";

Como en el shell, en Perl se usa C<< "<" >> para abrir el archivo en modo de
solo lectura. Si tiene éxito, Perl le reserva un nuevo identificador de
archivo y rellena en el anterior e indefinido argumento C<$controlador> con una
referencia al controlador.

Ahora puede usar funciones como C<readline>, C<read>, C<getc> y C<sysread> en
ese controlador. Probablemente la función de entrada más común es aquella
que parece un operador:

    $linea = readline($controlador);
    $linea = <$controlador>;     # lo mismo

Debido a que la función C<readline> devuelve C<undef> al final del archivo o
en caso de error, algunas veces verá que se usa de esta manera:

    $linea = <$controlador>;
    if (defined $linea) {
        # hacer algo con $linea
    }
    else {
        # $linea no es válida, así que sáltela
    }

Puede también hacer un simple C<die> en un valor indefinido, de esta manera:

    $linea = <$controlador> // die "no hubo entrada";

Sin embargo, si es un evento normal el recibir de sopetón un EOF, no querrá
simplemente salir por el simple hecho de que se acabó la entrada de datos. En
lugar de eso, probablemente solo querrá salir del bucle de entrada. Puede
entonces comprobar si fue un error real el que provocó que el bucle terminase,
y actuar en consecuencia:

    while (<$controlador>) {
        # hacer algo con los datos en $_
    }
    if ($!) {
        die "error inexperado mientras leemos $nombre_archivo: $!";
    }

B<Una nota sobre codificación>: Tener que especificar cada vez la
codificación de texto parece un poco molesto. Para ajustar una codificación
por defecto para C<open> para que no tenga indicarlo en cada ocasión, puede
usar el pragma C<open>:

    use open qw< :encoding(UTF-8) >;

Una vez hecho esto, puede omitir sin problemas la parte de la codificación en
el modo de apertura:

    open($controlador, "<", $nombre_archivo)
        || die "$0: no puedo abrir $nombre_archivo para lectura: $!";

Pero nunca use el sencillo C<< "<" >> sin haber puesto primero una
codificación por defecto. Si no, Perl no puede saber cuál de los muchos,
muchos, muchos sabores posibles de archivos de texto tiene usted, y Perl no
tendrá ni idea de cómo mapear correctamente los datos de su archivo en
caracteres reales con los que pueda trabajar. Otros formatos comunes de
codificación son C<"ASCII">, C<"ISO-8859-1">, C<"ISO-8859-15">,
C<"Windows-1252">, C<"MacRoman"> e incluso C<"UTF-16LE">. Vea L<perlunitut>
para más información sobre codificaciones.

=head2 Abrir archivos de texto para escritura

Cuando quiera escribir a un archivo, primero tiene que decidir qué hacer sobre
los contenidos actuales de ese archivo. Aquí tiene dos opciones básicas:
preservar o sobreescribir.

Si quiere preservar cualquier contenido actual, entonces quiere abrir el
archivo en modo añadir. Como en el shell, en Perl usa C<<< ">>" >>> para abrir
un archivo actual en modo añadir. C<<< ">>" >>> crea el archivo si realmente
no existe.

    my $controlador    = undef;
    my $nombre_archivo = "/alguna/ruta/al/archivotexto/va/aqui";
    my $codificacion   = ":encoding(UTF-8)";

    open($controlador, ">> $codificacion", $nombre_archivo)
        || die "$0: no puedo abrir $nombre_archivo para añadir: $!";

Ahora puede escribir a ese identificador de archivo usando cualquiera de
C<print>, C<printf>, C<say>, C<write>, o C<syswrite>.

Como se ha indicado antes, si el archivo no existe, entonces el modo añadir lo
creará por usted. Pero si el archivo ya existe, sus contenidos están a salvo
de cualquier daño porque estará añadiendo nuevo texto pasado el final del
texto anterior.

Por otro lado, a veces querrá sobre escribir cualquier cosa que pudiera estar
allí. Para vaciar un archivo antes de empezar a escribir en él, puede abrirlo
en modo de solo escritura:

    my $controlador    = undef;
    my $nombre_archivo = "/alguna/ruta/al/archivotexto/va/aqui";
    my $codificacion   = ":encoding(UTF-8)";

    open($controlador, ">  $codificacion", $nombre_archivo)
        || die "$0: no puedo abrir $nombre_archivo en modo de solo escritura: $!";

Aquí, de nuevo, Perl trabaja justo como el shell en que el C<< ">" >>
sobreescribe un archivo existente.

Así como el modo añadir, cuando abre el archivo en modo de solo escritura,
puede ahora escribir a ese identificador de archivo usando cualquiera de
C<print>, C<printf>, C<say>, C<write>, o C<syswrite>.

¿Qué hay sobre el modo de solo lectura?  Quizás pretenda hacer que no
existe, porque abriendo archivos de texto en modo de solo lectura es muy
probable que no es lo que le querría hacer. Vea L<perlfaq5> para más
detalles.

=head1 Abrir archivos binarios

Si el archivo que se va a abrir contiene datos binarios en lugar de caracteres
de texto, entonces el argumento C<MODO> a C<open> es un poco más diferente. En
vez de especificar la codificación, le dice a Perl que sus dato son bytes
crudos.

    my $nombre_archivo = "/alguna/ruta/a/un/archivo/binario/va/aqui";
    my $codificacion   = ":raw :bytes"
    my $controlador    = undef;     # se rellenará en caso de éxito

Y entonces puede abrir, como antes, eligiendo entre C<<< "<" >>>, C<<< ">>"
>>>, o C<<< ">" >>>:

    open($controlador, "<  $codificacion", $nombre_archivo)
        || die "$0: no puedo abrir $nombre_archivo para lectura: $!";

    open($controlador, ">> $codificacion", $nombre_archivo)
        || die "$0: no puedo abrir $nombre_archivo para añadir: $!";

    open($controlador, ">  $codificacion", $nombre_archivo)
        || die "$0: no puedo abrir $nombre_archivo en modo de solo escritura: $!";

Alternativamente, puede cambiar a modo binario en un identificador de archivo
actual, de esta manera:

    binmode($controlador)  || die "no puedo pasar el controlador a modo binario";

Esto es especialmente útil para los controladores que Perl realmente ya ha
abierto.

    binmode(STDIN)         || die "no puedo pasar STDIN  a modo binario";
    binmode(STDOUT)        || die "no puedo pasar STDOUT a modo binario";

Puede también pasar C<binmode> una codificación explícita para cambiarlo al
vuelo. Esto no es exactamente modo "binario", pero seguimos usando C<binmode>
para cambiarlo:

  binmode(STDIN,  ":encoding(MacRoman)") || die "no puedo pasar STDIN a modo binario";
  binmode(STDOUT, ":encoding(UTF-8)")    || die "no puedo pasar STDOUT a modo binario";

Una vez que tiene su archivo binario abierto apropiadamente en el modo
correcto, puede usar las mismas funciones Perl de E/S que utilizó en archivos
de texto. Sin embargo, puede desear usar la lectura de tamaño fijo C<read> en
lugar de tamaño variable C<readline> para su entrada.

Aquí hay un ejemplo de cómo copiar un archivo binario:

    my $TAMANOBUFER = 64 * (2 ** 10);
    my $nombre_ent  = "/algun/archivo/entrada";
    my $nombre_sal  = "/algun/archivo/salida";

    my($in_fh, $out_fh, $bufer);

    open($in_fh,  "<", $nombre_ent)
        || die "$0: no puedo abrir $nombre_ent para lectura: $!";
    open($out_fh, ">", $nombre_sal)
        || die "$0: no puedo abrir $nombre_sal para escritura: $!";

    for my $fh ($in_fh, $out_fh)  {
        binmode($fh)    || die "falló binmode";
    }

    while (read($in_fh, $bufer, $TAMANOBUFER)) {
        unless (print $out_fh $bufer) {
            die "no puedo escribir a $nombre_sal: $!";
        }
    }

    close($in_fh)       || die "no puedo cerrar $nombre_ent: $!";
    close($out_fh)      || die "no puedo cerrar $nombre_sal: $!";

=head1 Abrir tuberías

Se anunciará.

=head1 Apertura de archivos en bajo nivel vía sysopen

Se anunciará. O borrará.

=head1 VEA TAMBIÉN

Se anunciará.

=head1 AUTOR Y COPYRIGHT

Copyright 2013 Tom Christiansen.

Esta documentación es libre; puede redistribuirla o modificarla bajo los
mismos términos que el propio Perl.


=head1 TRADUCTORES

=over

=item * Joaquín Ferrero (Tech Lead)

=item * Enrique Nell (Language Lead)

=back

