The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME / NOMBRE

perlopentut - recetas sencillas para abrir archivos y tuberías en Perl

ADVERTENCIA: ESTE DOCUMENTO NO ESTÁ REVISADO.
Se incluye en la distribución como borrador útil e informativo, pero su lectura puede resultar dura para l@s perler@s con mayor sensibilidad lingüística.

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 filehandle (identificador de archivo). Un identificador de archivo es un nombre interno para un archivo externo. Es trabajo de la función open hacer la asociación entre el nombre interno y el nombre externo, y es trabajo de la función 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 STDIN, STDOUT, STDERR y 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, STDOUT y STDERR son controladores de salida, y STDIN y ARGV son controladores de entrada. Están en letras mayúsculas porque son reservadas para Perl, como lo son el array @ARGV y el hash %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:

OK = open(IDENTIFICADOR, MODO, RUTA_AL_ARCHIVO)

donde:

OK

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

IDENTIFICADOR

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

MODO

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

RUTA_AL_ARCHIVO

es el nombre externo del archivo que quiere abrir.

La mayor parte de la complejidad de la función open reside en los muchos posibles valores que puede tomar el parámetro 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 perlfaq5 para ver cómo bloquear.

Abrir archivos de texto

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 "<" 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 $controlador con una referencia al controlador.

Ahora puede usar funciones como readline, read, getc y 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 readline devuelve 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 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: $!";
    }

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 open para que no tenga indicarlo en cada ocasión, puede usar el pragma 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 "<" 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 "ASCII", "ISO-8859-1", "ISO-8859-15", "Windows-1252", "MacRoman" e incluso "UTF-16LE". Vea perlunitut para más información sobre codificaciones.

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 ">>" para abrir un archivo actual en modo añadir. ">>" 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 print, printf, say, write, o 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 ">" 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 print, printf, say, write, o 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 perlfaq5 para más detalles.

Abrir archivos binarios

Si el archivo que se va a abrir contiene datos binarios en lugar de caracteres de texto, entonces el argumento MODO a 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 "<", ">>", o ">":

    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 binmode una codificación explícita para cambiarlo al vuelo. Esto no es exactamente modo "binario", pero seguimos usando 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 read en lugar de tamaño variable 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: $!";

Abrir tuberías

Se anunciará.

Apertura de archivos en bajo nivel vía sysopen

Se anunciará. O borrará.

VEA TAMBIÉN

Se anunciará.

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.

TRADUCTORES

  • Joaquín Ferrero (Tech Lead)

  • Enrique Nell (Language Lead)