Подтвердить что ты не робот

Как очистить файл на Perl?

У меня есть Perl script, который добавляет новую строку к существующему файлу каждые 3 секунды. Кроме того, есть приложение С++, которое читает из этого файла.

Проблема в том, что приложение начинает читать файл после завершения script, и дескриптор файла закрыт. Чтобы этого избежать, я хочу, чтобы флеш после каждой строки добавлял, но я новичок в Perl и не знаю, как это сделать.

4b9b3361

Ответ 1

Try:

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

Это было фактически опубликовано как способ автоматической очистки в раннем вопросе моего вопроса, в котором говорилось о общепризнанном плохом способе достижения этого: -)

Ответ 2

TL/DR: используйте IO::Handle и метод flush, например:

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

Во-первых, вам нужно решить, как "покраснеть" вам это нужно. Может быть довольно много слоев буферизации:

  • Внутренний буфер Perl в дескрипторе файла. Другие программы не могут видеть данные, пока они не покинут этот буфер.

  • Буферизация уровня файловой системы "грязных" блоков файлов. Другие программы все еще могут видеть эти изменения, они кажутся "написанными", но они будут потеряны, если ОС или машина сработает.

  • Буферная запись записи на уровне диска. ОС думает, что они записаны на диск, но на самом деле диск хранит их в энергозависимой памяти на диске. Если ОС выйдет из строя, данные не будут потеряны, но если сбой питания произойдет, возможно, если диск не сможет записать его первым. Это большая проблема с дешевыми потребительскими SSD.

Это становится еще более сложным, когда задействованы SAN, удаленные файловые системы, RAID-контроллеры и т.д. Если вы пишете через каналы, там также должен быть рассмотрен буфер для труб.

Если вы просто хотите очистить буфер Perl, вы можете close создать файл, print строку, содержащую "\n" (так как она кажется, что Perl flushes на символах новой строки) или использовать метод IO::Handle flush.

Вы также можете использовать perl faq использовать binmode или играть с $|, чтобы сделать файл дескриптором небуферизованным. Это не то же самое, что сброс буферизованной дескриптора, поскольку в очереди с буферизацией записывается то, что выполнение одного флеша имеет гораздо более низкую стоимость исполнения, чем запись в небуферизованный дескриптор.

Если вы хотите сбросить буфер обратной записи файловой системы, вам нужно использовать системный вызов типа fsync(), откройте файл в режиме O_DATASYNC или используйте один из многочисленных других параметров. Это мучительно сложно, о чем свидетельствует тот факт, что PostgreSQL имеет свой собственный инструмент для тестирования методов синхронизации файлов.

Если вы хотите убедиться, что это действительно, честно говоря, честно на жестком диске в постоянном хранилище, вы должны очистить его до файловой системы в своей программе. Вам также необходимо настроить контроллер жесткого диска/SSD/RAID/SAN/все, что действительно нужно, когда запрашивает ОС. Это может быть на удивление сложным и довольно специфичным для ОС/аппаратного обеспечения. "plug-pull" тестирование настоятельно рекомендуется, чтобы убедиться, что вы действительно поняли его.

Ответ 3

От 'man perlfaq5':

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

Если вы просто хотите сбросить stdout, вы можете просто сделать:

$| = 1;

Но проверьте FAQ для получения подробной информации о модуле, который дает вам более удобную абстракцию, например IO::Handle.

Ответ 4

Все решения, предлагающие установку autoflush, игнорируют основной факт, что большинство современных ОС являются буферизацией ввода-вывода файлов независимо от того, что делает Perl.

Только возможность принудительного использования данных на диске заключается в закрытии файла.

Я пойман в ловушку с той же дилеммой, где у нас есть проблема с вращением записываемого журнала.

Ответ 6

Чтобы автоматически очистить вывод, вы можете установить autoflush/ $|, как описано другими, прежде чем вы будете выводить на дескриптор файла.

Если вы уже вышли в дескриптор файла и должны убедиться, что он попадает в физический файл, вам нужно использовать методы IO:: Handle flush и sync.

Ответ 7

Вот ответ, реальный ответ.

STOP, поддерживающий дескриптор открытого файла для этого файла в течение всего процесса.

START абстрагирование операции с файлом-добавлением в подраздел, который открывает файл в режиме добавления, записывает на него, закрывает его.

#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;
}

процесс наблюдения за файлом встретит закрытый файл, который будет изменяться всякий раз, когда вызывается функция.

Ответ 8

Альтернативным подходом было бы использовать named pipe между вашей программой Perl script и С++, вместо файла, re в настоящее время используется.

Ответ 9

У меня была та же проблема с единственной разницей в написании одного и того же файла снова и снова с новым контентом. Эта ассоциация "$ | = 1" и autoflush работала для меня:

 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!

Удачи. Н