Как использовать свойство / переменную класса в качестве дескриптора файла печати в Perl? - PullRequest
5 голосов
/ 30 января 2012

Я хочу сделать то же самое, что и

open MYFILE, ">", "data.txt";
print MYFILE "Bob\n";

, но вместо этого в переменной класса, такой как

sub _init_tmp_db
{
    my ($self) = @_;

    open $$self{tmp_db_fh}, ">", "data.txt";
    print $$self{tmp_db_fh} "Bob\n";
}

Это дало мне такую ​​ошибку: «Строка найдена там, где ожидался оператор рядом» Боб\ n "'

что мне делать?

Ответы [ 4 ]

6 голосов
/ 30 января 2012

Из справочной страницы печати :

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

Вы должны использовать:

print { $$self{tmp_db_fh} } "Bob\n";

Этот код не будет работать под use strict. Чтобы это исправить, просто используйте переменную my:

open my $fh, ">", "data.txt" or die $!;
$$self{tmp_db_fh} = $fh;
print { $$self{tmp_db_fh} } "Bob\n";
4 голосов
/ 30 января 2012

Вместо этого следует использовать модуль IO :: File.

use IO::File;
my $file = IO::File->new;
$file->open("> data.txt");

print_something($file);

sub print_something {
  my ($file) = @_;
  $file->print("hello world\n");
} 

Или в вашем примере функция:

use IO::File;
# ...
sub _init_tmp_db
{
    my ($self) = @_;

    $self{tmp_db_fh} = IO::File->new;
    $self{tmp_db_fh}->open(">", "data.txt");
    $self{tmp_db_fh}->print"Bob\n";
}

(заметьте, вы все еще можете звонить не на основе ->, но я написал выше используя более традиционные -> вызовы типа open ().)

0 голосов
/ 30 января 2012

Это легко решить, создав переменную для дескриптора файла:

sub _init_tmp_db {
    my $self = shift;

    my $fh;
    open $fh, ">", "data.txt"
    $self->{temp_db_fh} = $fh;

    # Sometime later...

    $fh = $self-{temp_db_hf};
    print $fh "Bob\n";
}

Это проблема, потому что синтаксический анализ синтаксиса print и ранняя небрежность синтаксиса. Оператор print на самом деле имеет два отдельных формата: Формат № 1 - это то, что вы просто передаете его на печать. Формат # 2 говорит, что первый элемент может быть дескриптором файла, а остальное - это материал, который вы хотите напечатать в дескрипторе файла. Если print не может легко определить, что первый параметр является дескриптором файла, произойдет сбой.

Если вы посмотрите на другие языки, они будут использовать параметр для передачи дескриптора файла и, возможно, материал для печати. Или в объектно-ориентированных языках они перегрузят >> для параметра дескриптора файла. Они будут выглядеть примерно так:

print "This is my statement", file=file_handle;

или

print "This is my statement" >> file_handle;

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


Вы сказали класс в своем названии. Я предполагаю, что вы заинтересованы в написании полноценного объектно-ориентированного пакета для этого. Вот быстрый пример. Обратите внимание на метод write метод Я извлекаю дескриптор файла в переменную и использую переменную в операторе print.

#! /usr/bin/env perl
#
use strict;
use warnings;


#######################################################
# MAIN PROGRAM
#
my $file = File->new;

$file->open("OUTPUT") or
    die "Can't open 'OUTPUT' for writing\n";

$file->write("This is a test");
#
#######################################################

package File;
use Carp;


sub new {
    my $class = shift;

    my $self = {};
    bless $self, $class;

    return $self;
}

sub open {
    my $self = shift;
    my $file = shift;

    my $fh;
    if (defined $file) {
        $self->{FILE} = $file;
        open ($fh, ">", $file) and $self->_fh($fh);
    }
    return $self->_fh;
}

sub _fh {
    my $self = shift;
    my $fh   = shift;

    if (defined $fh) {
        $self->{FH} = $fh;
    }
    return $self->{FH};
}

sub write {
    my $self = shift;
    my $note = shift;

    my $fh = $self->_fh;
    print $fh $note . "\n";
    return
}
0 голосов
/ 30 января 2012

Файловые дескрипторы могут быть только скалярами.

Но $$self{tmp_db_fh} является либо открытым файловым дескриптором (для data.txt), тогда это будет работать:

sub _init_tmp_db
{
  my ($self) = @_;

  my $filehandle = $$self{tmp_db_fh} ;
  print $filehandle "Bob\n";
}

, либо вы откроете файловый дескриптор внутри_init_tmp_db

sub _init_tmp_db
{
  my ($self) = @_;

  open my $filehandle , ">", "data.txt" or die "Cannot open data.txt" ;
  print $filehandle "Bob\n";
}

Но предоставление строки в $$self{tmp_db_fh} (например, 'FILEHANDLE') не будет работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...