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.
{
for $chunk (split(/ /, $_))
{
print OUTF pack("H2", $chunk); #use pack function to write data in binary format
}
}
在这里用到了pack函数,文件以binmode方式打开后,文本数据需要用pack函数进行转化成二进制格式再存入二进制文件中。d表示用双精浮点打包,长度是8字节。f是单精浮点,长度是4字节。h的意思是说按底字节在前,高字节在后的结构转换。如果要高字节在前,就用H。H后面的2表示是一个字节,8就表示4个字节。
#!/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);
#!/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."
第十一章 文件系统