2010-09-08 12 views
5

Estoy tratando de escribir en el archivo en la POSICIÓN enésima. Lo he intentado con el ejemplo siguiente pero escribe al final. Por favor, ayuda para lograr esto.perl: Escribir archivo en la posición N °

#!/usr/bin/perl 

open(FILE,"+>>try.txt") 
or 
die ("Cant open file try.txt"); 

$POS=5; 

    seek(FILE,$POS,0); 

    print FILE "CP1"; 
+1

¿Ha intentado utilizar un modo que no se agrega? tales como: open (my $ fh, '<+', "try.txt") o die $ !; (este es también un uso más "moderno" de open(), ver http://perldoc.perl.org/functions/open.html) –

+0

@ Øyvind Skaar Es '" + <"' not '" <+ " '. –

+0

@chas a la derecha eres ... –

Respuesta

3

Está abriendo el archivo en modo de lectura y escritura. Trate de abrir el archivo en modo de lectura y escritura:

my $file = "try.txt"; 
open my $fh, "+<", $file 
    or die "could not open $file: $!"; 

Además, tenga en cuenta el uso de los tres argumentos open, el gestor de archivo de léxico, y $!.

#!/usr/bin/perl 

use strict; 
use warnings; 

#create an in-memory file 
my $fakefile = "1234567890\n"; 
open my $fh, "+<", \$fakefile 
    or die "Cant open file: $!"; 

my $offset = 5; 

seek $fh, $offset, 0 
    or die "could not seek: $!"; 

print $fh "CP1"; 

print $fakefile; 

El código anterior imprime:

12345CP190 
+0

Hola Chas es posible agregar el personaje en la enésima posición, es decir, mover el carácter Nth a N + 1 N + 1 a N + 2 y así sucesivamente – vrbilgi

+0

@ user430294: No realmente. Tienes que leer el contenido después de N y luego escribirlo en otra posición. –

+0

@ user430294 No, los archivos no funcionan de esa manera. –

2

esto funciona para mí

use strict; 
use warnings; 

open(my $fh, '+<', 'foo.txt') or die $!; 

seek($fh, 3, 0); 

print $fh "WH00t?"; 

esto es también un uso más "moderna" de open(), consulte http://perldoc.perl.org/functions/open.html

El archivo se cerrará cuando $ fh quede fuera del alcance.

+0

@Skaar su solución está funcionando bien. Pero está reemplazando el personaje presente en el archivo. Quiero adjuntar el contenido en la enésima posición, es decir, mover el N-ésimo carácter a N + 1 N + 1 a N + 2 y así sucesivamente. – vrbilgi

+0

hm .. podrías leerlo y luego escribirlo de nuevo ... quizás alguien tenga una mejor solución ... Pero creo que "agregar modo" (>>) solo significa que comienza a escribir al final del archivo, por lo que no es lo que quieres –

4

Si he entendido bien, si el contenido del archivo son

123456789

que desea cambiar eso a

1234CP157689

No se puede lograr que el uso de los modos suministrados a open (independientemente del lenguaje de programación).

Debe abrir el archivo fuente y otro archivo temporal (consulte File::Temp. Lea hasta el punto de inserción del origen y escriba el contenido en el archivo temporal, escriba lo que desea insertar y luego escriba el resto del archivo de origen en el archivo temporal, cierre la fuente y rename el temporal a la fuente.

Si va a hacer esto utilizando seek, ambos archivos se debe abrir en modo binario.

Aquí hay un ejemplo usando línea de entrada y modo de texto:

#!/usr/bin/perl 

use strict; use warnings; 
use File::Temp qw(:POSIX); 

my $source = 'test.test'; 
my $temp = tmpnam; 

open my $source_h, '<', $source 
    or die "Failed to open '$source': $!"; 

open my $temp_h, '>', $temp 
    or die "Failed to open '$temp' for writing: $!"; 

while (my $line = <$source_h>) { 
    if ($line =~ /^[0-9]+$/) { 
     $line = substr($line, 0, 5) . "CP1" . substr($line, 5); 
    } 
    print $temp_h $line; 
} 

close $temp_h 
    or die "Failed to close '$temp': $!"; 

close $source_h 
    or die "Failed to close '$source': $!"; 

rename $temp => $source 
    or die "Failed to rename '$temp' to '$source': $!"; 
2

"Insertar" una cadena en una función puede (en su mayoría) hacerse en su lugar. Consulte la función incorporada truncate ligeramente utilizada.

open my $fh, '+<', $file or die $!; 
seek $fh, 5, 0; 
$/ = undef; 
$x = <$fh>; # read everything after the 5th byte into $x 
truncate $fh, 5; 
print $fh "CPI"; 
print $fh $x; 
close $fh; 
+0

+1 Me gusta eso! ¿El archivo debe estar en modo bin para la plataforma de Windows? – dawg

-1

Si el archivo es la línea o registro orientado, puede insertar líneas o modificar las líneas individuales fácilmente con el módulo principal Tie::File Esto permitirá que el archivo sea tratado como una matriz y cadena de Perl y la manipulación de matrices para ser utilizado para modificar el archivo en la memoria. Puede operar con seguridad en archivos de gran tamaño más grandes que su RAM con este método.

Aquí es un ejemplo:

use strict; use warnings; 
use Tie::File; 

#create the default .txt file: 
open (my $out, '>', "nums.txt") or die $!; 
while(<DATA>) { print $out "$_"; } 
close $out or die $!; 

tie my @data, 'Tie::File', "nums.txt" or die $!; 

my $offset=5; 
my $insert="INSERTED"; 

#insert in a string: 
$data[0]=substr($data[0],0,$offset).$insert.substr($data[0],$offset) 
    if (length($data[0])>$offset); 

#insert a new array element that becomes a new file line:  
splice @data,$offset,0,join(':',split(//,$insert)); 

#insert vertically: 
$data[$_]=substr($data[$_],0,$offset) . 
      substr(lc $insert,$_,1) . 
      substr($data[$_],$offset) for (0..length($insert)); 

untie @data; #close the file too... 

__DATA__ 
123456789 
234567891 
345678912 
456789123 
567891234 
678912345 
789123456 
891234567 
912345678 

de salida:

12345iINSERTED6789 
23456n7891 
34567s8912 
45678e9123 
56789r1234 
I:N:St:E:R:T:E:D 
67891e2345 
78912d3456 
891234567 
912345678 

Las modificaciones de archivos con Tie::File se hacen en su lugar y como se modifica la matriz. Puede usar Tie::File solo en la primera línea de su archivo para modificar e insertar como lo solicitó. Puede poner sleep entre los modos de matriz y usar tail -n +0 -f en el archivo y ver el cambio de archivo si lo desea ...

Alternativamente, si su archivo es de un tamaño razonable y desea tratarlo como caracteres, puede leer todo el archivo en la memoria, realice operaciones de cadena en los datos, luego vuelva a escribir los datos modificados. Considere:

use strict; use warnings; 

#creat the default .txt file: 
open (my $out, '>', "nums.txt") or die $!; 
while(<DATA>) { print $out "$_"; } 
close $out or die $!; 

my $data; 
open (my $in, '<', "nums.txt") or die $!; 
{ local $/=undef; $data=<$in>; } 
close $in or die $!; 

my $offset=5; 
my $insert="INSERTED"; 

open (my $out, '>', "nums.txt") or die $!; 
print $out substr($data,0,$offset).$insert.substr($data,$offset); 
close $out or die $!; 

__DATA__ 
123456789 
2 
3 
4 
5 
6 
7 
8 
9 

Salida:

12345INSERTED6789 
2 
3 
4 
5 
6 
7 
8 
9 

Si usted trata a los archivos como caracteres, ten en cuenta que en Windows, los archivos en modo de texto tienen un \r\n para una nueva línea. Eso es dos caracteres si se abre en modo binario.

+0

¿Por qué votar al azar? – dawg

Cuestiones relacionadas