perl 二进制文件读写

use strict;my $gifname = "C:\\Documents and Settings\\Administrator\\My Documents\\My Pictures\\1.jpg";my $gifOutname = "d:\\1111.dat";
摘要由CSDN通过智能技术生成
 

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
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值