Perl语言程序设计_输入与输出

无论哪种编程语言,输入与输出都至关重要。个人感觉无论《Learning Perl》还是《Programming Perl》中,对输入与输出的讲解稍显随意,因此在这里整理相关要点,方便自己复习。

Perl语言中的输入与输出可以分成三类:从控制台输入或者输出;对文件进行输入或者输出操作;程序运行过程中输出报错或者警告信息。

来自控制台的输入与输出

读取标准输入

Perl语言中常用操作符<STDIN>实现对输入流的读取。在标量上下文中,<STDIN>会返回标准输入中的下一行,如果标准输入的下一行是文件结尾,那么<STDIN>会返回undef。因此,如果<STDIN>操作符被用在循环的判定条件中,那么当它读到文件结尾时会直接跳出循环。在列表上下文中,<STDIN>会返回一个列表,其中包含所有的输入内容,每个列表元素代表一行输入内容。

除了使用<STDIN>读取输入流之外,还可以使用钻石操作符<>完成读取操作。钻石操作符的优势在于,它能让程序在处理调用参数的时候,提供类似于Unix工具程序的功能。在两种情况下,钻石操作符会从标准输入流采集数据,一种是不提供任何调用参数的时候,另一种是把连字符(-)当作参数的时候。

用print输出

print操作符会读取后续列表中的所有元素,然后把每一项依次送到标准输出。在默认情况下,print操作符是不会往参数列表中添加任何符号的,换言之,print @arrray;这个指令会一个接一个地打印出数组中的所有元素,且各个元素之间不会有空格。如果希望数组的各个元素之间用空格隔开,那么可以采用数组的内插形式,例如print "@array";这种写法。此时,print操作符会打印一个字符串,而这个字符串是数组@array在双引号中内插形成的,它会在数组的各个元素(除了第一个元素)的前面加上一个空格。

一般来讲,为了节约时间、提高效率,程序会先将输出结果送到缓冲区。假如需要程序立刻输出,甚至可以放弃一部分效率的话,那么需要每次print时立刻刷新缓冲区。通常情况下,如果文件句柄连接的是终端,则Perl采用的是行缓冲模式,每逢换行符会将缓冲区的数据输出;如果文件句柄连接的是文件,则会等到缓冲区满或者程序结束的时候一起输出。如果要关掉缓冲模式,可以使用下列代码:

$| = 1;
$fh -> autoflush(1);

 由于print处理的是待打印的字符串列表,因此它的参数会在列表上下文中被执行。

用printf输出

在C语言中,我们可以使用printf函数来产生格式化过的输出结果。而在Perl语言中,printf函数具有相似的功能。printf操作符的参数包括“格式字符串”和“要输出的数据列表”两部分。“格式字符串”的用途是告诉程序要输出什么内容,以及要输出的变量在整个内容中的位置;“要输出的数据列表”则告诉程序这些变量分别是什么。例如:

$name = XXX;
$score = 100;
print ("The score of %s is %d.\n", $name, $score);

在上述例子中,%s和%d都称之为“转换”。每种转换均以百分号开头,然后以某个字母结尾,这些字母代表着独特的含义,且百分号与字母之间也可以有其他有效字符。要输出的数据列表中的元素的个数应当与转换的数据相同,否则程序无法正常运行。printf常用的转换格式如下表所示:

printf中常用转换格式
转换格式 转换格式的意义
%g 按照需求自动选择数字表达形式(浮点数、整数或者指数、科学记数法)
%d 十进制整数,它会舍去小数点之后的数字
%x 十六进制
%o 八进制
%s 字符串格式
%f 浮点数,会按照需要进行四舍五入
%% 输出百分号,而非输出列表中的元素

在百分号与字母之间可以加入数字,其意义为输出的宽度。例如%6d表示输出宽度为6的十进制整数,假设输出的是23,则视觉效果为“    23”(即23前有四个空格);如果加入的是负数,则表示左对齐;如果在%和f中间加入小数,则分别表示小数点前的宽度与小数点后的宽度,例如%2.2f表示小数点前有2位,小数点后有2位。

此外,数组也可以当成printf的参数,只是这种用法不是非常的常用。数组中可以包含任意数目的元素,而格式字符串只能用到固定数目的元素。只有两者数目相等的时候才可以讲数组作为printf的参数。例如:

@items = qw( A B C);
$format = "The first three letters in Englich are:\n".("%2s\n" x @items);
printf ($format, @items);

#*输出结果:
The first three letters in Englich are:
A
B
C
*#

用say来输出

Perl语言在5.10版本中正式加入了say这个函数,其用法与printf基本相同,但是会在打印每行内容时自动加上换行符。say是Perl 5.10的新特性,因此只能在启用了Perl 5.10新特性的情况下使用。

对文件进行输入和输出操作

Perl语言可以直接从文件中读取数据,或者往文件中写入数据。对此文件句柄是不可缺少的一个环节。文件句柄就是程序里代表Perl进程与外界之间的I/O联系的名称。给文件句柄起名字就如同给Perl的其他标识符起名字一样,必须以字母、数字及下划线组成,且不能以数字开头。比较推荐的做法是采用全大写字母来命名句柄,这样可以避免与将要引入的保留字冲突,避免程序出错。在Perl语言中有6个特殊的文件句柄名称是预先保留的,分别为:STDIN、STDOUT、STDERR、DATA、ARGV和ARGOUT。

文件句柄的打开

当我们需要用Perl语言打开其他文件的时候,可以使用open函数打开对应的文件句柄。open操作符有两种形式,分别为双参数与三参数,其中三参数写法最为推荐。第一个参数为句柄名称;第二个参数为模式;第三个参数为文件名本身。在open操作符里,我们可以使用任意一个标量表达式来替代文件名说明符。open操作符中用到的模式见下表。

open操作符中的模式
open操作符中的模式 该模式对应的意义
< 只读
> 创建新文件。如果已经存在同名的文件,则清除原有的内容并以新的内容取代
>> 以追加的方式打开。如果文件原本就存在,那么新的数据会添加到原有文件内容的后面;如果文件不存在,则创建新文件。
无模式符号 默认模式,读取数据

推荐三参数写法的另一个原因是,该写法有机会指定数据的编码方式。例如,假设已知文件时UTF-8编码的,则可以在文件操作模式后面加上冒号,然后写上编码名称。

open CONFIG, '<', 'dino';
open CONFIG, '<:encoding(UTF-8)', 'dino';

除了键入encoding(UTF-8)之外,还有一种简便写法,只要写上:UTF-8即可。但是两者并不是完全等同的,简写方式不会考虑输入或者输出的数据是否真的是UTF-8格式的,无论拿到什么数据,都会直接当作UTF-8编码字符串来处理,所以有时候会出现一些错误。

文件句柄的使用

一旦文件句柄以读取模式打开了之后,便可以从文件句柄中读取一行行数据,就像从STDIN读取标准输入流中的数据一样。以写入或添加模式打开的文件句柄可以在print或者printf函数中使用,只需要把文件句柄放在函数名和参数列表之间即可,文件句柄与参数列表之间没有逗号,只用空格分隔即可,且文件句柄是否在括号内都不会影响程序的执行。

print LOG "Captain's log, stardate 3.14159\n";#输出道文件句柄LOG
printf STDERR "%d percent complete.\n", $done/$total * 100;
printf (STDERR "%d percent complete.\n", $done/$total * 100);
printf STDERR ("%d percent complete.\n", $done/$total * 100);
#最后三行代码的意义是完全一样的

从Perl 5.6开始,文件句柄是可以存放在标量中的。换言之,文件句柄可以作为子程序的参数传递,或者放在数组、哈希中参与运算,同时也能够更方便地控制它的作用域。

在使用open操作符时,在原先文件句柄的位置用不含任何值得变量替换,那么文件句柄就会存放在该变量中。这里建议使用词法变量确保该变量是空的,以及在后面填上_fh来表明这个是用来存放文件句柄的变量。在之后的代码中,无论是循环中,还是输入输出中,都可以用这个变量名替换原先的句柄。需要注意的是,在使用printf或者print函数的时候,如果用变量替换文件句柄,那么变量后面是不需要加逗号的。Perl程序会通过这一差异自行判断该变量是作为文件句柄,还是作为输出的部分。如果误加了逗号,则会产生意料之外的错误。

改变默认的文件输出句柄

在默认的情况下,如果没有为print或者printf指定文件句柄,它会默认输出到STDOUT。如果想要改变默认的文件句柄,可以使用select操作符。例如:

select BEDROCK;
print "I hope Mr. Slate doesn't find out about this.\n";
print "Wilma!\n";
#后面这两行输出代码,都会输出到BEDROCK句柄对应的文件中。

为了不出现混淆或者混乱,建议在更改完文件句柄之后,将指定的默认文件句柄设回原先的默认值STDOUT。将数据输出到文件句柄的时候,默认情况下都会有缓冲处理。如果将特殊变量$|的值设置为1,就会使修改变量时所指定的默认文件句柄在每次进行输出操作后立刻刷新缓冲区。

文件句柄的关闭

当我们不再需要某个文件句柄的时候,直接用close操作符来关闭即可。例如:

close BEDROCK;

当我们关闭一个文件句柄的时候,相当于告诉操作系统,对该数据流的处理已经全部完成。另一方面,如果我们重新打开了一个文件句柄,那么Perl会自动关闭原先的文件句柄。Perl程序结束时,也会自动关闭所有的文件句柄。

报错与警告信息

用die处理致命错误

所有的Perl程序都能平稳运行是不现实的。在程序运行的过程中,难免会遇到很多错误,而有些情况下是需要立即终止程序的,对此,die操作符可以满足这一要求。die操作符会输出指定的信息到专门为这类信息准备的标准错误流中,并且让程序立即终止并返回不为零的退出码。举个例子:

if (! open LOG, '>>', 'logfile'){
    die "Cannot create logfile: $!";
}

在这个例子中,如果open失败,die就会终止程序的运行,然后提示:Cannot create logfile:。其中$!会对这个错误给予一个解释,例如找不到文件或者权限不足抑或是找不到文件路径等等。die操作符还有一个功能,就是它会自动将Perl程序名和行号附加在错误信息中,借此我们可以得知是程序中的哪个die操作符造成了程序的终止,进而排查出程序的问题所在。

用warn送出警告信息

warn操作符的功能就是产生类似于Perl的内置警告信息的信息,例如某个undef变量被当成已有值参与运算之类。warn与die之间的区别在于,它不会终止程序的运行。

自动检测致命错误

从Perl 5.10开始,autodie编译指令已经成为标准库的一部分。如果程序开头加上use autodie指令,程序就会在遇到致命错误的时候自动启动die。

展开阅读全文

没有更多推荐了,返回首页