2010-09-08 4 views
5

J'essaie d'écrire dans le fichier à la Nième POSITION. J'ai essayé avec l'exemple ci-dessous mais il écrit à la fin. S'il vous plaît, aidez-nous à y parvenir.perl: Écriture du fichier à la position 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

Avez-vous essayé d'utiliser un mode qui ne s'ajoute pas? tels que: open (my $ fh, '<+', "try.txt") ou die $ !; (c'est aussi une utilisation plus "moderne" de open(), voir http://perldoc.perl.org/functions/open.html) –

+0

@ Øyvind Skaar C'est "" + <"" pas "<+" '. –

+0

@chas droite vous êtes .. –

Répondre

3

Vous ouvrez le fichier en mode d'ajout en lecture-écriture. Essayez d'ouvrir le fichier en mode lecture-écriture:

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

Notez également l'utilisation de l'argument trois open, le descripteur de fichier lexical et $!.

#!/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; 

Le code ci-dessus impressions:

12345CP190 
+0

Salut Chas peut-il être possible d'ajouter le caractère à la Nième position ie déplacer le Nième caractère à N + 1 N + 1 à N + 2 et ainsi de suite – vrbilgi

+0

@ user430294: Pas vraiment. Vous devez lire le contenu après N et le réécrire dans une autre position. –

+0

@ user430294 Non, les fichiers ne fonctionnent pas de cette façon. –

2

cela fonctionne pour moi

use strict; 
use warnings; 

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

seek($fh, 3, 0); 

print $fh "WH00t?"; 

c'est aussi une utilisation plus d'open() "moderne", voir http://perldoc.perl.org/functions/open.html

Le fichier sera fermé lorsque $ fh sera hors de portée.

+0

@Skaar votre solution fonctionne bien. Mais il remplace le caractère présent dans le fichier. Je veux ajouter le contenu à la Nième position, c'est-à-dire déplacer le Nième caractère à N + 1 N + 1 à N + 2 et ainsi de suite. – vrbilgi

+0

hm .. vous pouvez le lire et ensuite l'écrire à nouveau .. peut-être que quelqu'un a une meilleure solution .. Mais je pense que "mode ajout" (>>) signifie seulement qu'il commence à écrire à la fin du fichier, de sorte que ce n'est pas ce que tu veux. –

4

Si je vous comprends bien, si le contenu du fichier sont

123456789

vous voulez changer cela à

1234CP157689

Vous ne pouvez pas réaliser que l'utilisation de modes fournis à open (quel que soit le langage de programmation).

Vous devez ouvrir le fichier source et un autre fichier temporaire (voir File::Temp). Lisez le point d'insertion à partir de la source et écrivez le contenu dans le fichier temporaire, écrivez ce que vous voulez insérer, puis écrivez le reste du fichier. fichier source dans le fichier temporaire, fermez la source et rename le temporaire à la source.

Si vous allez le faire en utilisant seek, les deux fichiers doit être ouvert en mode binaire.

Voici un exemple d'utilisation mode d'entrée et de texte orienté ligne:

#!/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

"Insérer" une chaîne dans une fonction peut (principalement) être fait sur place. Voir la fonction intégrée truncate légèrement utilisée.

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 J'aime ça! Le fichier doit-il être en mode bin pour la plate-forme Windows? – dawg

-1

Si votre fichier est ligne ou un enregistrement orienté, vous pouvez insérer des lignes ou modifier des lignes individuelles facilement avec le module de base Tie::File Cela permettra au fichier à traiter comme un tableau et la chaîne Perl et la manipulation des tableaux à utiliser pour modifier le fichier en mémoire. Vous pouvez travailler en toute sécurité sur des fichiers volumineux plus volumineux que votre RAM avec cette méthode.

Voici un exemple:

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 

Sortie:

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

Les modifications de fichiers avec Tie::File sont faits en place et que le tableau est modifié. Vous pouvez utiliser Tie::File juste sur la première ligne de votre fichier pour modifier et insérer comme vous l'avez demandé. Vous pouvez mettre sleep entre les mods de tableau et utiliser tail -n +0 -f sur le fichier et regarder le fichier changer si vous le souhaitez ...

Alternativement, si votre fichier est de taille raisonnable et que vous voulez le traiter comme des caractères, vous pouvez lire le fichier entier en mémoire, effectuez des opérations de chaîne sur les données, puis réécrivez les données modifiées. Considérez:

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 

Sortie:

12345INSERTED6789 
2 
3 
4 
5 
6 
7 
8 
9 

Si vous traitez des fichiers comme des caractères, méfiez-vous que sous Windows, les fichiers en mode texte ont une \r\n pour une nouvelle ligne. C'est deux caractères si elle est ouverte en mode binaire.

+0

Pourquoi le vote aléatoire vers le bas? – dawg

Questions connexes