2009-02-06 6 views

ответ

36

См. answer regarding openhandle() from Scalar::Util. Ответ, который я изначально написал здесь, был когда-то лучшим, что мы могли бы сделать, но теперь он сильно устарел.

+0

Он работает, спасибо :) – 2009-02-06 13:21:52

+10

вызывает ошибку: ... скажите() на неоткрытом дескрипторе ... – ekerner

+1

@ ekerner технически не ошибка, а предупреждение. – vladr

12

Зачем вам это нужно? Единственная причина, по которой я могу думать, это когда вы используете старые дескрипторы пакетов стиля (которые вы, кажется, делаете), и хотите предотвратить случайное сохранение одного дескриптора над другим.

Эта проблема может быть решена с помощью дескрипторов косвенных дескрипторов нового стиля.

open my $fh, '<', $filename or die "Couldn't open $filename: $!"; 
+0

О, отлично, приятно знать. Благодарю. – 2009-02-06 13:23:57

+0

matt: попробуйте Perl :: Критик для лучшего стиля –

+0

Пример: почему вы открыли дескриптор файла с 'open (FH," - | ")'. Вы хотите убедиться, что разветвленный процесс завершился успешно, что требует явно «закрыть FH», чтобы установить «$!» Или «$?» Соответствующим образом. Если это не удалось, вы хотите сделать ошибку; однако вы не хотите поднимать ошибку, если что-то еще закрыло 'FH' уже. – jon

8

Perl обеспечивает функцию fileno именно для этой цели.

EDIT Я стою исправлены с целью fileno(). Я предпочитаю более короткий тест

fileno FILEHANDLE

над

tell FH != -1

+1

Ну ... не совсем.Он предоставляет fileno для получения номера дескриптора системного файла. Определение того, является ли дескриптор файла открытым, является побочным эффектом (так же как и побочный эффект tell). – chaos

+1

И не вполне надежный побочный эффект. Возможно иметь дескриптор файла, открытый для чего-то другого, кроме filedescriptor, и в этом случае 'fileno' разумно возвращает undef. Примеры связаны с ручками и ручками, открытыми для скаляров. – hobbs

+1

tell (FH) выдает предупреждение с закрытой дескриптором файла. Использование fileno() - нет. –

0

Почему вы заботитесь, если он уже открыт? Вы пытаетесь поймать одновременное чтение?

Вам не нужно заботиться о закрытии файла. Либо он не открыт, а закрывается, потому что ему нечего закрывать, или файл открыт, а закрывает его. В любом случае, файл не открыт на этом дескрипторе файла. Просто закройте дескриптор файла, не заботясь о нем, если он не открыт. Вы видите там что-то странное?

+0

Пример: почему вы открыли дескриптор файла с открытым (FH, "- |"). Вы хотите убедиться, что процесс раздвоения преуспевает, что требует явно закрытого FH для установки $! или $? соответственно. Если это не удалось, вы хотите сделать ошибку; однако вы не хотите поднять ошибку, если что-то еще закрыло FH. – jon

+0

-1 для бесполезного ответа. Если вы хотите обсудить, действительно ли цель вопроса действительно желательна, я считаю, что лучше сделать это как комментарий. – jon

+0

Вы пропустите пункт. Есть некоторые вещи, в которых нас не волнует, если они потерпят неудачу, потому что мы закончили результат, который мы хотели в любом случае. Нам не нужно много работать, чтобы вызвать результат или проверить его, потому что мы получаем одно и то же. –

1

Телль производит предупреждение (так же стат, -s, -e, и т.д ..) с use warnings (-w)

perl -wle ' 
    open my $fh, "<", "notexists.txt"; 
    print "can stat fh" if tell $fh 
' 
tell() on closed filehandle $fh at -e line 1. 
-1 

альтернатив fileno($fh) и eof($fh) не производят предупреждения. Я нашел лучшую альтернативу, чтобы сохранить результат от open.

+0

'eof' имеет побочные эффекты. См. Его документы. – jon

21

Модуль Scalar::Util обеспечивает функцию openhandle() для этого. В отличие от fileno(), он обрабатывает дескрипторы файлов perl, которые не связаны с дескрипторами файлов ОС. В отличии от tell(), он не производит предупреждения при использовании закрытого дескриптора Из модуля documentation:

openhandle FH

Returns FH if FH may be used as a filehandle and is open, or FH is a tied handle. Otherwise "undef" is returned. 

    $fh = openhandle(*STDIN);   # \*STDIN 
    $fh = openhandle(\*STDIN);   # \*STDIN 
    $fh = openhandle(*NOTOPEN);   # undef 
    $fh = openhandle("scalar");   # undef 
+2

[open handle caveats] (http://stackoverflow.com/questions/3807231/how-can-i-test-if-i-can-write-to-a-filehandle/4200474#4200474) – daxim

+2

Это единственный реальный решение, спасибо. – ekerner

+1

Ответ tchrist на вопрос: ссылки @daxim довольно впечатляющие, но, похоже, отличаются от openhandle тем, что он скажет вам, что строка «STDIN» открыта (что, по-видимому, технически является, поскольку вы можете использовать ее для печать и т. д.). Теперь, действительно ли вы когда-нибудь захотите поощрять подобные вещи, это другой вопрос; Я бы хотел, чтобы отказ openhandle от «STDIN» был скорее чем-то особенным, чем ошибкой. –