2010-09-08 79 views
5

我正在嘗試寫入第N個位置的文件。我已經嘗試了下面的例子,但它在最後寫道。請幫助實現這一點。perl:在第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

您是否嘗試過使用不追加的模式?例如:open(my $ fh,'<+',「try.txt」)或者死掉$ !; (這也是open()的一個更「現代」的用法,參見http://perldoc.perl.org/functions/open.html) – 2010-09-08 11:36:15

+0

@ØyvindSkaar它是'「+ <」'not'「<+」 '。 – 2010-09-08 11:40:26

+0

@chas right you .. – 2010-09-08 11:42:57

回答

3

您正在以讀寫附加模式打開文件。嘗試打開該文件在讀寫模式:

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

另外,還要注意利用這三種說法open,詞法文件句柄,並$!的。

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

上面打印的代碼:

12345CP190 
+0

Hi Chas有沒有可能在第N個位置附加字符,即將第N個字符移到N + 1 N + 1到N + 2等等 – vrbilgi 2010-09-08 12:03:40

+0

@ user430294:並非如此。您必須在N之後實際閱讀內容,然後將其寫回另一個位置。 – 2010-09-08 12:19:43

+0

@ user430294不,文件不會以這種方式工作。 – 2010-09-08 12:57:54

2

這對我的作品

use strict; 
use warnings; 

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

seek($fh, 3, 0); 

print $fh "WH00t?"; 

這也是一個更 「現代」 使用的open(),見http://perldoc.perl.org/functions/open.html

該文件將被關閉,當$ fh超出範圍..

+0

@Skaar你的解決方案工作正常。但它正在替換文件中存在的字符。我想在第N個位置附加內容,即將第N個字符移到N + 1 N + 1到N + 2等等。 – vrbilgi 2010-09-08 11:58:08

+0

嗯..你可以讀它,然後再寫出來..也許有人有一個更好的解決方案..但我認爲「追加模式」(>>)只意味着它開始寫在文件的末尾,這樣不是你想要的。 – 2010-09-08 12:41:30

4

如果我理解正確的話,如果文件內容是

123456789

要改變,要

1234CP157689

你不能做到這一點使用提供給open(不管編程語言)模式。

您需要打開源文件和另一個臨時文件(請參閱File::Temp。從源讀取插入點並將內容寫入臨時文件,寫入要插入的內容,然後寫入剩餘部分源文件到臨時文件,關閉源和rename臨時到源。

如果你要做到這一點使用seek,這兩個文件必須以二進制模式打開。

下面是使用的例子面向行的輸入和文本模式:

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

「插入」一個字符串到一個函數中可以(大部分)完成。請參閱內置函數輕鬆使用的truncate

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我喜歡這樣!該文件需要在Windows平臺的bin模式下嗎? – dawg 2010-09-08 21:23:28

-1

如果你的文件是用來爲導向,你可以插入行或與核心模塊Tie::File方便地修改各行這將允許該文件被視爲一個數組和Perl字符串和數組操作線或記錄修改內存中的文件。用這種方法可以安全地操作大於RAM的大文件。

下面是一個例子:

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 

輸出:

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

Tie::File與該文件的修改都在適當位置製成,作爲陣列被修改。您可以在您的文件的第一行使用Tie::File來根據您的要求修改和插入。你可以把sleep陣列MODS之間,並在文件中使用tail -n +0 -f,如果你想觀看的文件更改...

另外,如果你的文件是合理的大小,要像對待字符,你可以閱讀將整個文件存入內存,對數據進行字符串操作,然後將修改後的數據寫回。試想一下:

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 

輸出:

12345INSERTED6789 
2 
3 
4 
5 
6 
7 
8 
9 

如果你把文件作爲字符,提防在Windows下,在文本模式下的文件有一個關於新線\r\n。如果以二進制模式打開,這是兩個字符。

+0

爲什麼隨機投票? – dawg 2010-09-09 02:52:15

相關問題