perl 二进制文件读写

来源:互联网 发布:win7 windows组件向导 编辑:程序博客网 时间:2024/05/21 05:18
 

use strict;

my $gifname = "C:\\Documents and Settings\\Administrator\\My Documents\\My Pictures\\1.jpg";
my $gifOutname = "d:\\1111.dat";
my $buff;
open(GIF, $gifname)         or die "can't open $gifname: $!";
open(GIFOUT, ">$gifOutname")         or die "can't open $gifOutname: $!";
binmode(GIF);
binmode(GIFOUT);
read(GIF, $buff, 1);
my $hex = unpack("H*", $buff);
print "ok" if $hex eq "ff";
$hex = "00";
my $outVar = pack("H*", $hex);
print GIFOUT $outVar;
close(GIF);
close(GFIOUT);

 

 

根本不用 pack/unpack,
直接 $ch eq "\x97" 就可以了。
再或者 ord($ch) == 0x97 也行。

use strict;

my $gifname = "C:\\Documents and Settings\\All Users\\Documents\\My Pictures\\示例图片\\Blue hills.jpg";
my $gifOutname = "d:\\1111.dat";
my $buff;
open(GIF, $gifname)         or die "can't open $gifname: $!";
open(GIFOUT, ">$gifOutname")         or die "can't open $gifOutname: $!";
binmode(GIF);
binmode(GIFOUT);
read(GIF, $buff, 2);
my $hex = unpack("H*", $buff);
print "ok" if $hex eq "ffd8";
print "ok2" if $buff eq "\xff\xd8";
$hex = "\x00";
#my $outVar = pack("H*", $hex);
print GIFOUT $hex;
close(GIF);
close(GFIOUT);

 

 

今天主要介绍用perl文件如何对二进制文件进行读写。

     一、写二进制文件

     下面是一个非常简单的读文本写二进制的例子,从一个文本文件中读入数字,然后转成二进制存储。#!perl -w
# Usage: convert.pl [source file] [destination file]
#    If we donot provide source file, STDIN will be used as source.
#    If we donot provide destination file, a file named a.out will be used as output.

open SOR,"$txtfile";
open OUTF, ">$destfile" or die "Can't open $destfile for writing!\n";
binmode(OUTF);
while ()
{
    for $chunk (split(/ /, $_))
    {
        print OUTF pack("H2", $chunk); #use pack function to write data in binary format
    }
}
close(OUTF);
      在这里用到了pack函数,文件以binmode方式打开后,文本数据需要用pack函数进行转化成二进制格式再存入二进制文件中。d表示用双精浮点打包,长度是8字节。f是单精浮点,长度是4字节。h的意思是说按底字节在前,高字节在后的结构转换。如果要高字节在前,就用H。H后面的2表示是一个字节,8就表示4个字节。
       二、读二进制文件
      写的时候用pack,很自然就想到,读文件的时候是不是要用unpack呢?还真是这样。还是看一个简单的例子:
#!/usr/local/bin/perl
open (FF, '<000001.dat') or die "no such file\n";
binmode (FF);
read (FF, $bindata, 8);
close (FF);
my ($id, $name) = unpack ('la*', $bindata);
print $id, $name
;
需要注意的是,读二进制文件时不能用<>,所以只能用read来读入数据,然后可以根据数据的结构进行解包。
 
 
 

用perl处理二进制文件需要用到pack()和unpack()函数。前者将文本数据写成二进制,后者将二进制数据读成文本。

遭遇悲惨硬盘事故后,恢复出的jpg文件后面有很多垃圾数据,使得文件超常的大。所以写了perl脚本去除这些数据,代码无参考价值,但可以使用。

jpg文件的开头总是0xffd8,结尾则是0xffd9。在实际浏览文件的时候,发现正常文件有两个0xffd9。估计是exif的扩展?但是有的文件又只有一个0xffd9,因此for循环的结束条件为找到两个0xffd9,或者文件扫描完毕。 当搜索找到0xffd9的时候,$i的值实际是指向0xff,因此文件长度应该为$i+2。

#!/usr/bin/perl
#file name: tryJpg.pl jpgFile.jpg
#file try to handle jpg files.

$fileName=$ARGV[0];
print("file name is $fileName\n");

open(HJPG, '<', "$fileName")
or die "Could not open the jpg file $fileName:$!\n";

undef $/;

$str_jpg=<HJPG>; #the whole file is put into a string.
$len_jpg=length($str_jpg); #size of the jpg file.
(@ary_jpg)=unpack("C$len_jpg", $str_jpg);
$time_jpg=0;
print("file length of $fileName is $len_jpg\n");

for($i=0; $i<$len_jpg && $time_jpg<2; $i=$i+1){
if($ary_jpg[$i]==255 && $ary_jpg[$i+1]==217){
print("when 0xffd9 is found, i=$i\n");
$time_jpg=$time_jpg+1;
$len_new=$i+2;
}

}
print("there are $time_jpg 0xffd9. len_new=$len_new.\n");
for($i=0; $i<=$len_new; $i=$i+1){
$ary_new[$i]=$ary_jpg[$i];

}

open(HNEW, '>new'."$fileName")
or die "could not open the new file: $!\n";
binmode HNEW;
print(HNEW pack("C$len_new", @ary_new));

print("done.\n");
close(HJPG);
close(HNEW);

解决文件修改的问题使用了挖隧道一样的方式。这个perl脚本没有使用多个参数的能力,每次调用只能处理一个文件。对多文件的处理则寄希望于shell的能力。下面的shell脚本调用上面的perl脚本完成多文件的处理。

#!/bin/bash
fileNum=$#
echo "There are $fileNum jpg files to be handled."
for fileName in "$@"
do
perl ../tryJpg.pl $fileName
echo "$fileName has been corrected."
done

echo "all files done."

如果对一个目录中的所有jpg文件执行操作,

#!/bin/bash

for file in *.jpg
do
perl /media/f_document/aboutJPEG/tryJpg.pl $file
echo "$file is done"
done

echo "all files done."

 
 
 

第十一章  文件系统

by flamephoenix

一、文件输入/输出函数
  1、基本I/O函数
    1)open函数
    2)用open重定向输入
    3)文件重定向
    4)指定读写权限
    5)close函数
    6)print, printf和write函数
    7)select函数
    8)eof函数
    9)间接文件变量
  2、跳过和重读数据
  3、系统读写函数
  4、用getc读取字符
  5、用binmode读取二进制文件
二、目录处理函数
  1、mkdir
  2、chdir
  3、opendir
  4、closedir
  5、readdir
  6、telldir
  7、seekdir
  8、rewinddir
  9、rmdir
三、文件属性函数
  1、文件重定位函数
  2、链接和符号链接函数
  3、文件许可权函数
  4、其他属性函数
四、使用DBM文件

    本章所讲的函数多数使用了UNIX操作系统的特性,在非UNIX系统中,一些函数可能没有定义或有不同的工作方式,使用时请查看Perl联机文档。
一、文件输入/输出函数
    本节讲述从文件中读取信息和向文件写入信息的内置库函数。
1、基本I/O函数
    一些I/O函数在前面的章节中已有讲述,如
  • open:允许程序访问文件
  • close:终止文件访问
  • print:文件写入字符串
  • write:向文件写入格式化信息
  • printf:格式化字符串并输出到文件
  •     这里简单回顾一下,再讲一些前面未提到的函数。
    1)open函数
        open函数将文件变量与某文件联系起来,提供访问文件的接口,例如:open(MYVAR, "/u/file"); 如果文件打开成功,则返回非零值,否则返回零。缺省地,open打开文件用以读取其内容,若想打开文件以写入内容,则在文件名前加个大于号:open(MYVAR, ">/u/file"); 向已有的文件末尾添加内容用两个大于号:open(MYVAR, ">>/u/file"); 若想打开文件作为数据导向的命令,则在命令前加上管道符(|):open(MAIL, "|mail dave");
    2)用open重定向输入
        可以把打开的文件句柄用作向程序输入数据的命令,方法是在命令后加管道符(|),如:
        open(CAT, "cat file*|");
        对open的调用运行命令cat file* ,此命令创建一个临时文件,这个文件的内容是所有以file打头的文件的内容连接而成,此文件看作输入文件,可用文件变量CAT访问,如:
        $input = ;
        下面的例子使用命令w的输出来列出当前登录的所有用户名。
    1 : #!/usr/local/bin/perl
    2 :
    3 : open (WOUT, "w|");
    4 : $time = <WOUT>;
    5 : $time =~ s/^ *//;
    6 : $time =~ s/ .*//;
    7 : ; # skip headings line
    8 : @users = ;
    9 : close (WOUT);
    10: foreach $user (@users) {
    11:   $user =~ s/ .*//;
    12: }
    13: print ("Current time: $time");
    14: print ("Users logged on:\n");
    15: $prevuser = "";
    16: foreach $user (sort @users) {
    17:   if ($user ne $prevuser) {
    18:     print ("\t$user");
    19:     $prevuser = $user;
    20:   }
    21: }
        结果输出如下:
    Current time: 4:25pm
    Users logged on:
      dave
      kilroy
      root
      zarquon
        w命令列出当前时间、系统负载和登录的用户,以及每个用户的作业时间和当前运行的命令,如:
      4:25pm  up 1 day,  6:37,  6 users,  load average: 0.79, 0.36, 0.28User     tty       login@  idle   JCPU   PCPU whatdave     ttyp0     2:26pm           27      3 wkilroy   ttyp1     9:01am  2:27   1:04     11 -cshkilroy   ttyp2     9:02am    43   1:46     27 rnroot     ttyp3     4:22pm     2               -cshzarquon  ttyp4     1:26pm     4     43     16 cc myprog.ckilroy   ttyp5     9:03am         2:14     48 /usr/games/hack
        上例中从w命令的输出中取出所需的信息:当前时间和登录的用户名。第3行运行w命令,此处对open的调用指定w的输出用作程序的输入,用文件变量WOUT来访问该输入。第4行读取第一行信息,即:
        4:25pm up 1 day, 6:37, 6 users, load average: 0.79, 0.36, 0.28
        接下来的两行从这行中抽取出时间。首先,第5行删除起始的空格,然后第6行删去除时间和结尾换行符之间的所有字符,存入变量$time。
        第7行从WOUT读取第二行,这行中无有用信息,故不作处理。第8行把剩下的行赋给数组@users,然后第9行关闭WOUT,终止运行w命令的进程。
        @users中的每个元素都是一行用户信息,因为本程序只需要每行的第一个单词,即用户名,故10~12行去掉除换行符外的其它字符,这一循环结束后,@users中只剩下用户名的列表。
        第13行输出存贮在$time中的时间,注意这时print不需要加上换行符,因为$time中有。16~21行对@users中的用户名排序并输出。因为同一个用户可以多次登录,所以用$preuser存贮输出的最后一个用户名,下次输出数组元素$user时,如果其与$preser相等,则不输出。
    3)文件重定向
        许多UNIX shell可以把标准输出文件(STDOUT)和标准错误文件(STDERR)都重定向到同一个文件,例如在Bourne Shell(sh)中,命令
        $ foo > file1 2>&1
        运行命令foo并把输出到标准输出文件和标准错误文件的内容存贮到文件file1中。下面是用Perl实现这一功能的例子:
    1: #!/usr/local/bin/perl
    2:
    3: open (STDOUT, ">file1") || die ("open STDOUT failed");
    4: open (STDERR, ">&STDOUT") || die ("open STDERR failed");
    5: print STDOUT ("line 1\n");
    6: print STDERR ("line 2\n");
    7: close (STDOUT);
    8: close (STDERR);
        运行后,文件file1中的内容为:
         line 2
         line 1
        可以看到,这两行并未按我们想象的顺序存贮,为什么呢?我们来分析一下这段程序。
        第3行重定向标准输出文件,方法是打开文件file1将它与文件变量STDOUT关联,这也关闭了标准输出文件。第4行重定向标准错误文件,参数>&STDOUT告诉Perl解释器使用已打开并与STDOUT关联的文件,即文件变量STDERR指向与STDOUT相同的文件。第5、6行分别向STDOUT和STDERR写入数据,因为这两个文件变量指向同一个文件,故两行字符串均写到文件file1中,但顺序却是错误的,怎么回事呢?
        问题在于UNIX对输出的处理上。当使用print(或其它函数)写入STDOUT等文件时,UNIX操作系统真正所做的是把数据拷贝到一片特殊的内存即缓冲区中,接下来的输出操作继续写入缓冲区直到写满,当缓冲区满了,就把全部数据实际输出。象这样先写入缓冲区再把整个缓冲区的内容输出比每次都实际输出所花费的时间要少得多,因为一般来说,I/O比内存操作慢得多。
        程序结束时,任何非空的缓冲区都被输出,然而,系统为STDOUT和STDERR分别维护一片缓冲区,并且先输出STDERR的内容,因此存贮在STDERR的缓冲区中的内容line 2出现在存贮在STDOUT的缓冲区中的内容line 1之前。
        为了解决这个问题,可以告诉Perl解释器不对文件使用缓冲,方法为:
         1、用select函数选择文件
         2、把值1赋给系统变量$|
        系统变量$|指定文件是否进行缓冲而不管其是否应该使用缓冲。如果$|为非零值则不使用缓冲。$|与系统变量$~和$^协同工作,当未调用select函数时,$|影响当前缺省文件。下例保证了输出的次序:
    1 : #!/usr/local/bin/perl
    2 :
    3 : open (STDOUT, ">file1") || die ("open STDOUT failed");
    4 : open (STDERR, ">&STDOUT") || die ("open STDERR failed");
    5 : $| = 1;
    6 : select (STDERR);
    7 : $| = 1;
    8 : print STDOUT ("line 1\n");
    9 : print STDERR ("line 2\n");
    10: close (STDOUT);
    11: close (STDERR);
        程序运行后,文件file1中内容为:
         line 1
         line 2
        第5行将$|赋成1,告诉Perl解释器当前缺省文件不进行缓冲,因为未调用select,当前的缺省文件为重定向到文件file1的STDOUT。第6行将当前缺省文件设为STDERR,第7行又设置$|为1,关掉了重定向到file1的标准错误文件的缓冲。由于STDOUT和STDERR的缓冲均被关掉,向其的输出立刻被写到文件中,因此line 1出现在第一行。
    4)指定读写权限
        打开一个既可读又可写的文件方法是在文件名前加上"+>",如下:
         open (READWRITE, "+>file1");
        此语句打开既可读又可写的文件file1,即可以重写其中的内容。文件读写操作最好与库函数seek和tell一起使用,这样可以跳到文件任何一点。
        注:也可用前缀"+<"指定可读写权限。
    5)close函数
        用于关闭打开的文件。当用close关闭管道,即重定向的命令时,程序等待重定向的命令结束,如:
         open (MYPIPE, "cat file*|");
         close (MYPIPE);
        当关闭此文件变量时,程序暂停运行,直到命令cat file*运行完毕。
    6)print, printf和write函数
        print是这三个函数中最简单的,它向指定的文件输出,如果未指定,则输出到当前缺省文件中,如:
         print ("Hello, there!\n");
         print OUTFILE ("Hello, there!\n");
        第一句输出到当前缺省文件中,若未调用select,则为STDOUT。第二句输出到由文件变量OUTFILE指定的文件中。
        printf函数先格式化字符串再输出到指定文件或当前缺省文件中,如:
         printf OUTFILE (“You owe me %8.2f", $owing);
        此语句取出变量$owing的值并替换掉串中的%8.2f,%8.2f是域格式的例子,把$owing的值看作浮点数。
        write函数使用输出格式把信息输出到文件中,如:
         select (OUTFILE);
         $~ = "MYFORMAT";
         write;
        关于printf和write,详见《第x章 格式化输出》。
    7)select函数
        select函数将通过参数传递的文件变量指定为新的当前缺省文件,如:
         select (MYFILE);
        这样,MYFILE就成了当前缺省文件,当对print、write和printf的调用未指定文件时,就输出到MYFILE中。
    8)eof函数
        eof函数查看最后一次读文件操作是否为文件最后一个记录,如果是,则返回非零值,如果文件还有内容,返回零。
        一般情况下,对eof的调用不加括号,因为eof和eof()是等效的,但与<>操作符一起使用时,eof和eof()就不同了。现在我们来创建两个文件,分别叫做file1和file2。file1的内容为:
         This is a line from the first file.
         Here is the last line of the first file.
        file2的内容为:
         This is a line from the second and last file.
         Here is the last line of the last file.
        下面就来看一下eof和eof()的区别,第一个程序为:
    1: #!/usr/local/bin/perl
    2:
    3: while ($line = <>) {
    4:   print ($line);
    5:   if (eof) {
    6:     print ("-- end of current file --\n");
    7:   }
    8: }
        运行结果如下:
    $ program file1 file2
    This is a line from the first file.
    Here is the last line of the first file.
    -- end of current file --
    This is a line from the second and last file.
    Here is the last line of the last file.
    -- end of current file --
    $
        下面把eof改为eof(),第二个程序为:
    1: #!/usr/local/bin/perl
    2:
    3: while ($line = <>) {
    4:   print ($line);
    5:   if (eof()) {
    6:     print ("-- end of output --\n");
    7:   }
    8: }
        运行结果如下:
    $ program file1 file2
    This is a line from the first file.
    Here is the last line of the first file.
    This is a line from the second and last file.
    Here is the last line of the last file.
    -- end of output --$
        这时,只有所有文件都读过了,eof()才返回真,如果只是多个文件中前几个的末尾,返回值为假,因为还有要读取的输入。
    9)间接文件变量
        对于上述各函数open, close, print, printf, write, select和eof,都可以用简单变量来代替文件变量,这时,简单变量中所存贮的字符串就被看作文件变量名,下面就是这样一个例子,此例很简单,就不解释了。需要指出的是,函数open, close, write, select和eof还允许用表达式来替代文件变量,表达式的值必须是字符串,被用作文件变量名。
    1: #!/usr/local/bin/perl
    2:
    3: &open_file("INFILE", "", "file1");
    4: &open_file("OUTFILE", ">", "file2");
    5: while ($line = &read_from_file("INFILE")) {
    6:   &print_to_file("OUTFILE", $line);
    7: }
    8:
    9: sub open_file {
    10:   local ($filevar, $filemode, $filename) = @_;
    11:
    12:   open ($filevar, $filemode . $filename) ||
    13:     die ("Can't open $filename");
    14: }
    15: sub read_from_file {
    16:   local ($filevar) = @_;
    17:
    18:   <$filevar>;
    19: }
    20: sub print_to_file {
    21:   local ($filevar, $line) = @_;
    22:
    23:   print $filevar ($line);
    24: }
    2、跳过和重读数据

    函数名seek调用语法seek (filevar, distance, relative_to);解说在文件中向前/后移动,有三个参数:
    1、filevar,文件变量
    2、distance,移动的字节数,正数向前移动,负数往回移动
    3、reletive_to,值可为0、1或2。为0时,从文件头开始移动,为1时,相对于当前位置(将要读的下一行)移动,为2时,相对于文件末尾移动。
    运行成功返回真(非零值),失败则返回零,常与tell函数合用。

    函数名tell调用语法tell (filevar);解说返回从文件头到当前位置的距离。
    注意:
    1、seek和tell不能用于指向管道的文件变量。
    2、seek和tell中文件变量参数可使用表达式。

    3、系统读写函数

    函数名read调用语法read (filevar, result, length, skipval);解说read函数设计得与UNIX的fread函数等效,可以读取任意长度的字符(字节)存入一个简单变量。其参数有四个:
    1、filevar:文件变量
    2、result:存贮结果的简单变量(或数组元素)
    3、length:读取的字节数
    4、skipval:可选项,指定读文件之前跳过的字节数。
    返回值为实际读取的字节数,如果已到了文件末尾,则返回零,如果出错,则返回空串。

    函数名sysread调用语法sysread (filevar, result, length, skipval);解说更快的读取数据,与UNIX函数read等效,参数与read相同。

    函数名syswrite调用语法syswrite (filevar, data, length, skipval);解说更快的写入数据,与UNIX函数write等效,参数:
    1、filevar:将要写入的文件
    2、data:存贮要写入数据的变量
    3、length:要写入的字节数
    4、skipval写操作之前跳过的字节数。

    4、用getc读取字符

    函数名getc调用语法$char = getc (infile);解说从文件中读取单个字符。

    5、用binmode读取二进制文件

    函数名binmode调用语法binmode (filevar);解说当你的系统(如类DOS系统)对文本文件和二进制文件有所区别时使用。必须在打开文件后、读取文件前使用。

    二、目录处理函数

    函数名mkdir调用语法mkdir (dirname, permissions);解说创建新目录,参数为:
    1、dirname:将要创建的目录名,可以为字符串或表达式
    2、permissions:8进制数,指定目录的访问权限,其值和意义见下表,权限的组合方法为将相应的值相加。

    值权限4000  运行时设置用户ID  2000运行时设置组ID1000粘贴位0400拥有者读权限0200拥有者写权限0100拥有者执行权限0040组读权限0020组写权限0010组执行权限0004所有人读权限0002所有人写权限0001所有人执行权限

    函数名chdir调用语法chdir (dirname);解说改变当前工作目录。参数dirname可以为字符串,也可以为表达式。

    函数名opendir调用语法opendir (dirvar, dirname);解说打开目录,与下面几个函数合用,可查看某目录中文件列表。参数为:
    1、dirvar:目录变量,与文件变量类似
    2、dirname:目录名,可为字符串或表达式
    成功返回真值,失败返回假。
    注:程序中可用同名的目录变量和文件变量,根据环境确定取成分。

    函数名closedir调用语法closedir (mydir);解说关闭打开的目录。

    函数名readdir调用语法readdir (mydir);解说赋给简单变量时,每次赋予一个文件或子目录名,对数组则赋予全部文件和子目录名。

    函数名telldir调用语法location = telldir (mydir);解说象在文件中前后移动一样,telldir和下面的seekdir用于在目录列表中前后移动。

    函数名seekdir调用语法seekdir(mydir, location);解说location必须为telldir返回的值。

    函数名rewinddir调用语法rewinddir (mydir);解说将读取目录的位置重置回开头,从而可以重读目录列表。

    函数名rmdir调用语法rmdir (dirname);解说删除空目录。成功则返回真(非零值),失败返回假(零值)。

    三、文件属性函数
    1、文件重定位函数

    函数名rename调用语法rename (oldname, newname);解说改变文件名或移动到另一个目录中,参数可为字符串或表达式。

    函数名unlink调用语法num = unlink (filelist);解说删除文件。参数为文件名列表,返回值为实际删除的文件数目。
    此函数之所以叫unlink而不叫delete是因为它实际所做的是删除文件的链接。

    2、链接和符号链接函数

    函数名link调用语法link (newlink, file);解说创建现有文件的链接--硬链接,file是被链接的文件,newlink是被创建的链接。
    成功返回真,失败返回假。
    当删除这两个链接中的一个时,还可以用另一个来访问该文件。

    函数名symlink调用语法symlink (newlink, file);解说创建现有文件的符号链接,即指向文件名,而不是指向文件本身。参数和返回值同上。
    当原文件被删除(如:被unlinke函数删除),则被创建链接不可用,除非再创建一个与原被链接的文件同名的文件。

    函数名readlink调用语法filename = readlink (linkname);解说如果linkname为符号链接文件,返回其实际指向的文件。否则返回空串。

    3、文件许可权函数

    函数名chmod调用语法chmod (permissions, filelist);解说改变文件的访问权限。参数为:
    1、permissions为将要设置的权限,其含义见上述mkdir中权限表
    2、filelist为欲改变权限的文件列表

    函数名chown调用语法chown (userid, groupid, filelist);解说改变文件的属主,有三个参数:
    1、userid:新属主的(数字)ID号
    2、groupid:新的组(数字)ID号,-1为保留原组
    3、filelist:欲改变属主的文件列表

    函数名umask调用语法oldmaskval = umask (maskval);解说设置文件访问权限掩码,返回值为当前掩码。

    4、其它属性函数

    函数名truncate调用语法truncate (filename, length);解说将文件的长度减少到length字节。如果文件长度已经小于length,则不做任何事。其中filename可以为文件名,也可以为文件变量

    函数名stat调用语法stat (file);解说获取文件状态。参数file可为文件名也可为文件变量。返回列表元素依次为:

  • 文件所在设备
  • 内部参考号(inode)
  • 访问权限
  • 硬链接数
  • 属主的(数字)ID
  • 所属组的(数字)ID
  • 设备类型(如果file是设备的话)
  • 文件大小(字节数)
  • 最后访问时间
  • 最后修改时间最后改变状态时间
  • I/O操作最佳块大小
  • 分配给该文件的块数
  • 函数名lstat调用语法lstat (file);解说与stat类似,区别是将file看作是符号链接。

    函数名time调用语法currtime = time();解说返回从1970年1月1日起累计秒数。

    函数名gmtime调用语法timelist = gmtime (timeval);解说将由time, stat 或 -A 和 -M 文件测试操作符返回的时间转换成格林威治时间。返回列表元素依次为:

  • 分钟
  • 小时,0~23
  • 日期
  • 月份,0~11(一月~十二月)
  • 年份
  • 星期,0~6(周日~周六)
  • 一年中的日期,0~364
  • 是否夏令时的标志
    详见UNIX的gmtime帮助。
  • 函数名localtime调用语法timelist = localtime (timeval);解说与gmtime类似,区别为将时间值转换为本地时间。

    函数名utime调用语法utime (acctime, modtime, filelist);解说改变文件的最后访问时间和最后更改时间。例如:
    $acctime = -A "file1";
    $modtime = -M "file1";
    @filelist = ("file2", "file3");
    utime ($acctime, $modtime, @filelist);

    函数名fileno调用语法filedesc = fileno (filevar);解说返回文件的内部UNIX文件描述。参数filevar为文件变量。

    函数名fcntl
    flock调用语法fcntl (filevar, fcntlrtn, value);
    flock (filevar, flockop);解说详见同名UNIX函数帮助。

    四、使用DBM文件
       Perl中可用关联数组来访问DBM文件,所用函数为dbmopen和dbmclose,在Perl5中,已用tie和untie代替。

    函数名dbmopen调用语法dbmopen (array, dbmfilename, permissions);解说将关联数组与DBM文件相关联。参数为:
    1、array:所用关联数组
    2、dbmfilename:将打开的DBM文件名
    3、访问权限,详见mkdir

    函数名dbmclose调用语法dbmclose (array);解说关闭DBM文件,拆除关联数组与之的关系。

     

    上一章下一章 目录

     

     

     

    perl 处理二进制文件

    2008年12月13日 星期六 11:16

    打开文件
    open FH, "binaryfile" or die $!;
    binmode(FH);
    # 读取文件内容... ...
    close FH;

    read() vs sysread()
    read()
    使用标准IO缓冲
    必须读取到指定的字节才会返回
    不能进行多路复用和无阻塞IO
    适合本地文件
    sysread()
    不使用标准IO缓冲
    只要读取到1个及以上的字节就返回
    可以多路复用和无阻塞IO
    适合网络通讯

    little-endian和big-endian
    big-endian
    高位在前
    pack("N", 32)   ---> 0x00000020
    little-endian
    低位在前
    pack("L", 32)   ---> 0x20000000

    常规写法
    my $buf;
    seek FH, 38, 0 or die $!;
    read FH, $buf, 12 or die $!;
    my ($size, $type, $version, $flag) =
            unpack("NA4cB24", $buf);

    pack()和unpack()
    pack()
    二进制串 = pack("模板", 值1, 值2, 值3, ......);
    unpack()
    数组 = unpack("模板", 二进制串);
    unpack('C/a', "\04Gurusamy") ---> Guru
    unpack('N', chr(0) . $packed_int_24)

    其他工具
    my $cur_pos = tell FH;
    my $is_end = eof FH;

    另一种方式
    my $filesize = -s $filename;
    my $content;
    read FH, $content, $filesize;
    my buf = substr($content, 36, 12);
    my ($size, $type, $version, $flag) =
            unpack("NA4cB24", $buf);
    ......
    谢谢
    Any questions?
    -------------------------------------------------
    请问各位大虾,如何用Perl读取二进制文件,多谢!

    binmod
    binmod FILEHANDLE, DISCIPLINES
    binmod FILEHANDLE

    这个函数为 FILEHANDLE 安排具有 DISCIPLINES 参数声明的语意的属性。如果省略了 DISCIPLINES,
    那么给该文件句柄提供二进制(或者“raw”)语意。如果 FILEHANDLE 是一个表达式,那么将根据
    情况把其值当作文件句柄或者一个指向文件句柄的引用。

    binmode 函数应该是在调用完 open 之后,但在对该文件句柄做任何 I/O 之前调用。重置一个文件句柄的
    该模式的唯一方法是重新打开该文件,因为各种不同的纪律(模式)会把一点一滴的数据各自存放在不同
    的缓冲区里。这个限制可能在将来会放松。

    在古老的年代,binmode 主要是用于那些运行时间库区分文本和二进制文件的操作系统上。在那些系统上,
    binmode 的作用是关闭缺省的文本语意。不过,自从增加了 Unicode 的先进性之后,在所有系统上的所有
    程序都一定有一些可识别的区别,即使是在 Unix 和 Mac 系统上也如此。现在,只有一种二进制文件存在
    了(至少 Perl 是这么认为的),但是有许多种文本文件,但 Perl 也愿意用一种方法来处理这些文本文件。
    所以 Perl 对于 Unicode 文本只有一种内部格式,UTF-8。因为有许多不同类型的文本文件,所以文本文件
    在输入时常需要转换成 UTF-8,而在输出时常需要转换回某些传统的字符集,或者 Unicode 的一些其他表现
    形式。你可以用纪律(DISCIPLINES)告诉 Perl 如何精确地(或者不精确地)做这些转换。(注:更准确
    地说,你将能用纪律做这些事情,但是我们写本书的时候还在实现这些东西。)

    比如,一个为 ":text" 的纪律将告诉 Perl 做一般性的文本处理而不用告诉 Perl 是做具体的哪种文本处理。
    但象 ":utf8" 和 ":latin1" 这样的纪律就告诉 Perl 读和写哪种文本格式。另一方面,":raw" 纪律告诉 Perl
    把它的肥手从数据上拿开,不对数据做任何额外处理。有关纪律如何运转(或者将如何运转)的更多内容,
    请参考 open 函数。这个讨论的其余部分描述没有 DISCIPLINES 参数的时候,binmode 干的事情,也就
    是说,binmode 的历史含义,也就等效于:

    binmode FILEHANDLE, ":raw";

    除非你另外指明了,否则 Perl 将把你新打开的文件以文本模式读写。文本模式意味着 (换行/新行)
    将是你的内部的行终止符。所有系统都用 做内部的行终止符,但是它真正代表的东西是因系统而异,
    因设备而异,甚至是因文件而异的,具体情况取决于你如何访问该文件。在这样的一种传统的系统里,
    (包括 MS-DOS 和 VMS),你的程序看做 的东西可能不是物理上存储在磁盘上的东西。比如,
    该操作系统可能把在文本文件里存储成 cMcJ 序列,到你在程序里显示为 这样的东西,而当输出
    到文件中去的时候,又把你的程序里的 转换回 cMcJ 序列。binmode 关闭在这些系统上的这种
    转换工作。

    如果没有 DISCIPLINES 参数,binmode 在 Unix 或者 Mac OS 里没有什么作用,它们都用 结束
    每一行,并且把它表现为单个字符。(不过,这个字符可能是不一样的:Unix 使用 xJ 而老一些的
    Mac 使用 c。没关系。)

    下面的例子演示了 Perl 脚本如何从一个 GIF 图象文件里读取数据并把它打印到标准输出上去。在有些
    系统上,如果不做 binmode 处理,那么它就会把显示数据篡改成与数据的物理存储形式不同的东西,
    所以你必须把下面程序里的两个句柄都准备成二进制模式。尽管你可以很容易地在 GIF 文件打开上
    使用 ":raw" 纪律,想在一个象 STDOUT 这样的提前打开了的文件句柄上做这件事可不那么容易:

    binmode STDOUT;
    open(GIF, "vim-power.gif") or die "Can't open vim-power.gif: $! ";
    binmode GIF;
    while (read(GIF, $buf, 1024)) {
    print STDOUT $buf;
    }
    http://www.unixresources.net/linux/clf/perl/archive/00/00/07/13/71369.html
    ---------------------------------------------------------------------------------------------------------
    perl写二进制文件要用pack  
    以前用过又忘记了,写下来留着备忘。
    下面是一个非常简单的读文本写二进制的例子,从一个文本文件中读入数字,然后转成二进制存储。
    例如:文本文件以空格分隔存放90 12 0b,二进制文件按顺序存放90 12 0b
    #!perl -w
    #
    # Usage: convert.pl [source file] [destination file]
    #    If we donot provide source file, STDIN will be used as source.
    #    If we donot provide destination file, a file named a.out will be used as output.
    if ($#ARGV != 1)
    {
        print "Use a.out as default output file.\n";
        $destfile = "a.out";
    }
    else
    {
        $destfile = $ARGV[1]; #using user defined output file
    }
    open OUTF, ">$destfile" or die "Can't open $destfile for writing!\n";
    binmode(OUTF);
    while (<>)
    {
        for $chunk (split(/ /, $_))
        {
            print OUTF pack("H2", $chunk); #use pack function to write data in binary format
        }
    }
    close(OUTF);
    http://blog.chinaunix.net/u/29291/showart_288097.html
    ------------------------------------------------------------------------------
    使用Perl在一个文件中查找一串二进制的字符(其中可能有0),如何处理?(要测试好的源代码)
    刚好有一个类似程序,可做参考:
    sub Search {
    # 参数: 文件路径, 查找数据
    # 如: myprg.exe, 0x45, 0x10, 0x84, 0, 0x55, ...
    my $buff;
    my $bytes_read;
    my @find = @_;
    my $filename = shift(@find);
    my @readc;
    my $alen = @find;
    my $i;
    my $j;
    my $thisc;
    my $found;
    my $poscount;
    return -1 if (!(-e $filename)); # 文件不存在
    return -2 if (!open(FH, "+<$filename")); # 文件打开错误
    binmode FH;
    $bytes_read = read(FH, $buff, $alen - 1);
    return -3 if ($bytes_read != $alen - 1); # 文件长度不足
    @readc = split("", $buff);
    foreach (@readc) {
    $_ = ord($_);
    }
    unshift(@readc, 0);
    $postcount = -1;
    while ($bytes_read = read(FH, $buff, 1024)) {
    for ($i = 0; $i < $bytes_read; $i++) {
    $thisc = ord(substr($buff, $i, 1));
    push(@readc, $thisc);
    shift(@readc);
    $poscount++;
    $found = 1;
    foreach ($j = 0; $j < $alen; $j++) {
    if ($found != 0) {
    if ($find[$j] != $readc[$j]) {
    $found = 0;
    }
    }
    last if ($found == 0);
    }
    last if ($found != 0);
    }
    last if ($found != 0);
    }
    if ($found != 0) {
    # $poscount 为查找到的位置(从 1 开始计数)
    close(FH);
    return $poscount;
    } else {
    close(FH);
    return -4; # 没有找到
    }
    }
    http://topic.csdn.net/t/20021203/23/1228460.html



     
     

     

    原创粉丝点击