2010-12-27 38 views
17

Tôi có tập lệnh Perl nối thêm một dòng mới vào tệp hiện có sau mỗi 3 giây. Ngoài ra, có một ứng dụng C++ đọc từ tập tin đó.Làm cách nào để xóa một tệp trong Perl?

Sự cố là ứng dụng bắt đầu đọc tệp sau khi hoàn tất tập lệnh và xử lý tệp được đóng. Để tránh điều này tôi muốn tuôn ra sau mỗi dòng nối thêm, nhưng tôi mới làm quen với Perl và không biết làm thế nào để làm điều đó.

+0

Trong perl "cơ bản" không có chức năng tuôn ra, nhưng nếu bạn gọi 'binmode $ filehandle', nó sẽ đặt định dạng': raw' và (như là một ảnh hưởng phụ) nó sẽ làm cho việc tuôn ra. Nó hoạt động độc đáo. Dù sao, nếu nó nằm trên un * x, bạn có thể tạo một đường ống có tên là hệ thống tập tin, và bạn có thể ghi trực tiếp vào nó. – TrueY

+0

Làm cho chương trình C++ của bạn đọc từ một đường ống ('/ dev/stdin' nếu nó đủ ngu ngốc để yêu cầu tên tệp) và kiểm tra xem nó có thực sự đọc một dòng tại một thời điểm không - làm ở bên viết. – reinierpost

Trả lời

25

Hãy thử:

use IO::Handle; 
$fh->autoflush; 

này đã thực sự được đăng như một cách để tự động xả nước trong an early question of mine, mà hỏi về cách xấu chấp nhận rộng rãi của việc đạt được :-)

+1

Cảm ơn bạn. Nhưng điều này không giúp tôi. Ngay cả sau khi xả sau mỗi dòng, chương trình C++ của tôi không thể đọc được dòng này, sau khi chúng được giải phóng. Nó chỉ đọc sau khi perl kết thúc công việc của nó. –

14

này Từ 'người đàn ông perlfaq5' :

$old_fh = select(OUTPUT_HANDLE); 
$| = 1; 
select($old_fh); 

Nếu bạn chỉ muốn tuôn stdout, bạn có thể có lẽ chỉ làm:

$| = 1; 

Nhưng hãy kiểm tra Câu hỏi thường gặp để biết chi tiết về mô-đun cung cấp cho bạn một trừu tượng đẹp hơn, như IO::Handle.

1

Để tự động tuôn đầu ra, bạn có thể đặt autoflush/$| như mô tả của những người khác trước khi bạn xuất ra các filehandle.

Nếu bạn đã xuất tệp thủ công và cần đảm bảo rằng tệp được chuyển đến tệp thực, bạn cần sử dụng các phương thức IO :: Handle flushsync.

-1

Tôi đã có cùng một sự cố với sự khác biệt duy nhất của việc viết cùng một tệp lặp đi lặp lại với nội dung mới. Liên kết "$ | = 1" và tự động làm việc này cho tôi:

open (MYFILE, '>', '/internet/web-sites/trot/templates/xml_queries/test.xml'); 
$| = 1; # Before writing! 
print MYFILE "$thisCardReadingContentTemplate\n\n"; 
close (MYFILE); 
MYFILE->autoflush(1); # After writing! 

Chúc may mắn. H

+3

afaik, đóng tập tin làm tuôn ra. MYFILE-> autoflush (1) phải làm gì ở đây? – PypeBros

2

Tất cả các giải pháp đề xuất đặt autoflush là bỏ qua thực tế cơ bản là hệ điều hành hiện đại nhất đang đệm tệp I/O bất kể Perl đang làm gì.

Bạn chỉ có khả năng buộc cam kết dữ liệu vào đĩa là bằng cách đóng tệp.

Tôi bị mắc kẹt với cùng một tình trạng khó xử tại nơi chúng tôi gặp vấn đề với xoay vòng nhật ký đang được ghi.

+3

"Bạn chỉ có khả năng buộc cam kết của dữ liệu vào đĩa là bằng cách đóng tệp". Đóng một tập tin không cam kết nó vào đĩa, hệ điều hành vẫn còn miễn phí để ghi lại bộ nhớ cache nó. Cách duy nhất được bảo đảm là gọi 'fsync()' hoặc hệ điều hành của bạn tương đương với bộ mô tả tập tin. Nếu không nó có thể bị mất trên hệ điều hành sụp đổ hoặc mất điện. –

0

Phương pháp thay thế sẽ là sử dụng named pipe giữa tập lệnh Perl và chương trình C++ của bạn, thay cho tệp bạn hiện đang sử dụng.

20

TL/DR: sử dụng IO::Handleflush phương pháp, ví dụ:

use IO::Handle; 
$myfile->flush(); 

Trước tiên, bạn cần phải quyết định như thế nào "đỏ mặt" bạn muốn nó. Có thể có một vài lớp đệm:

  • Bộ đệm trong của Perl trên bộ xử lý tệp. Các chương trình khác không thể xem dữ liệu cho đến khi nó rời khỏi bộ đệm này.

  • Đệm cấp hệ thống tệp của khối tệp "bẩn". Các chương trình khác vẫn có thể thấy những thay đổi này, chúng dường như được "viết", nhưng chúng sẽ bị mất nếu hệ điều hành hoặc máy bị treo.

  • Ghi bộ đệm ghi đè cấp độ đĩa. Hệ điều hành cho rằng chúng được ghi vào đĩa, nhưng đĩa thực sự chỉ lưu trữ chúng trong bộ nhớ dễ bay hơi trên ổ đĩa. Nếu hệ điều hành gặp sự cố, dữ liệu sẽ không bị mất, nhưng nếu mất điện thì có thể trừ khi đĩa có thể ghi ra trước. Đây là một vấn đề lớn với SSD tiêu dùng rẻ.

Sẽ phức tạp hơn nữa khi SAN, hệ thống tệp từ xa, bộ điều khiển RAID, vv tham gia. Nếu bạn đang viết qua đường ống thì cũng có bộ đệm ống để xem xét.

Nếu bạn chỉ muốn tuôn bộ đệm Perl, bạn có thể close file, print một chuỗi chứa "\n" (vì có vẻ như Perl xả vào dòng mới), hoặc use IO::Handle's flush method.

Bạn cũng có thể, mỗi the perl faq sử dụng binmode hoặc chơi với $| để làm cho tệp không được xử lý. Đây là không giống như điều khi xóa bộ đệm được đệm, vì việc xếp hàng loạt các bộ đệm được đệm sau đó thực hiện một lần xả đơn có chi phí hiệu suất thấp hơn nhiều so với việc ghi vào bộ xử lý không bị chặn.

Nếu bạn muốn xóa hệ thống tệp ghi đệm, bạn cần sử dụng lệnh gọi hệ thống như fsync(), mở tệp ở chế độ O_DATASYNC hoặc sử dụng một trong nhiều tùy chọn khác. Nó phức tạp một cách đau đớn, được chứng minh bằng thực tế là PostgreSQL has its own tool just to test file syncing methods.

Nếu bạn muốn chắc chắn rằng nó thực sự, thực sự, trung thực trên ổ đĩa cứng trong bộ nhớ vĩnh viễn, bạn phải tuôn ra nó vào hệ thống tệp trong chương trình của bạn. Bạn cũng cần phải cấu hình ổ đĩa cứng/SSD/RAID controller/SAN/bất cứ điều gì để thực sự tuôn ra khi hệ điều hành yêu cầu nó. Điều này có thể phức tạp đáng ngạc nhiên để làm và khá OS/phần cứng cụ thể. Thử nghiệm "plug-pull" được khuyến khích mạnh mẽ để đảm bảo bạn thực sự đã thực hiện đúng.

1

Đây là câu trả lời, câu trả lời thực sự.

STOP duy trì xử lý tệp đang mở cho tệp này trong suốt quá trình xử lý.

BẮT ĐẦU trừu tượng hoạt động chắp thêm tệp của bạn vào một phụ mở tệp ở chế độ nối thêm, ghi vào nó, đóng nó.

#appends a new line to the existing file 
sub append_new_line{ 
    my $linedata = shift; 
    open my $fh, '>>', $fnm or die $!; # $fnm is file-lexical or something 
    print $fh $linedata,"\n"; # flavor to taste 
    close $fh; 
} 

quá trình quan sát tệp sẽ gặp phải tệp đóng được sửa đổi bất cứ khi nào hàm được gọi.

Các vấn đề liên quan