这两天一直在研究UMD格式的转换问题,参考了
http://hi.baidu.com/lzlsha/blog/item/1f511929f60554fe98250a24.html的思路以及http://blog.csdn.net/Oxygenant/archive/2009/05/03/4146282.aspx的源码后终于成功的用Delphi写出了umd格式插件。
由于umd格式使用了zlib压缩,之前看到Delphi自带的zlib.pas文件和从www.zlib.net下载的大体变量一致,就直接使用了自带的文件,但是却总是没成功,后来才想到解压缩的问题,在网上搜索发现,Delphi自带的zlib是很旧的版本,在http://www.2ccc.com/article.asp?articleid=4269下载了最新的DelphiZlib v1.2.3,使用这里面的函数,终于成功的搞定了。最终保存的TXT为Unicode编码。
代码如下:
library umd;
uses
SysUtils,
Windows,
Classes,
ZLibEx;
{$R *.res}
var
MS:TMemoryStream;//读取文件流
Current:integer;//记录文件流位置
AdditionalCheck:Cardinal;//判断是章节名还是内容
filename2:string; //输出文件名
FS:TMemoryStream;//记录转换后数据,为Unicode编码
function GetTempDir: String;//获取系统临时目录
var
Buffer: array[0..MAX_PATH] of Char;
begin
GetTempPath(SizeOf(Buffer) - 1, Buffer);
Result := StrPas(Buffer);
end;
function GetTempName: String;//生成一个临时文件名
var
p,f: array[0..MAX_PATH] of Char;
begin
GetTempPath(MAX_PATH, p);
randomize;
GetTempFileName(p,'~umd',random(10000),f);
result:=f;
end;
procedureReadAdditional(id:smallint;check,length:Cardinal);//读取内容
var
seg:string;
DecompStream:TZDecompressionStream;
MS1:TMemoryStream;
Char:WideString;
begin
case id of
$84:begin
if AdditionalCheck<>checkthen//如果这两个不相等,表明是内容,否则是章节名
begin
setlength(seg,length);
MS.Read(seg[1],length);
MS1:=TMemoryStream.Create;
MS1.Write(seg[1],system.length(seg));
DecompStream:=TZDecompressionStream.Create(MS1);
FS.CopyFrom(DecompStream,DecompStream.Size);
Char:=WideString(#13);
FS.Write(Char,sizeof(Char));
MS1.Free;
end;
end;
end;
inc(current,length);
MS.Seek(current,soFromBeginning);
end;
procedure ReadSection(id:smallint; b:Byte; length:Byte);
begin
case id of
$84:MS.Read(AdditionalCheck,sizeof(AdditionalCheck));
end;
inc(current,length);
MS.Seek(current,soFromBeginning);
end;
function Parse:integer;
var
magicint:Cardinal;
ch:char;
id:smallint;
b,len:byte;
check,num6:Cardinal;
begin
MS.Read(magicint,4);
ifmagicint<>$de9a9b89 then
begin
result:=-1;
exit;
end;
inc(current,4);
MS.Read(ch,sizeof(ch));
while(ch='#')do
begin
inc(current,1);
Ms.Read(id,sizeof(id));inc(current,2);
MS.Read(b,sizeof(b));inc(current,1);
MS.Read(len,sizeof(len));inc(current,1);
len:=len-5;
ReadSection(id,b,len);
MS.Read(ch,sizeof(ch));
case idof
$f1:;
10:id:=$84;
end;
while(ch='$')do
begin
inc(current,1);
MS.Read(check,sizeof(check));inc(current,4);
MS.Read(num6,sizeof(num6));inc(current,4);
num6:=num6-9;
ReadAdditional(id,check,num6);
MS.Read(ch,sizeof(ch));
end;
end;
result:=0;
end;
function SaveToFile:integer;
var
TempWString:WideString;
i:integer;
head:Word;
begin
try
filename2:=GetTempname;
FS.Seek(0,0);
SetLength(TempWString,FS.Size div 2);
FS.Read(TempWString[1],FS.Size);
for i := 1to length(TempWString) do
if ord(TempWString[i])=$2029then//将umd的回车换成Windows的
TempWString[i]:=WideChar(#13);
FS.Clear;
head:=$FEFF;
FS.Write(head,2);
FS.Write(TempWString[1],length(TempWString)*2);
FS.SaveToFile(filename2);
except
result:=-1;
FS.Free;
exit;
end;
FS.Free;
result:=0;
end;
function PluginType(Ver:integer):PChar;//插件类型
begin
result:=pchar('FileOpen');
end;
function UrlPosition(Ver:integer):Pchar;//文件名位置
begin
result:=pchar('end');
end;
function UrlKeyWord(Ver:integer):Pchar;//后缀或前缀
begin
result:=pchar('.umd');
end;
functionReadExtFile(Filename:Pchar):Pchar;//读取开始
var
head:Word;
begin
MS:=TMemoryStream.Create;
FS:=TMemoryStream.Create;
head:=$FEFF;
FS.Write(head,2);
try
MS.LoadFromFile(Filename);
except
MS.Free;
result:=PChar('');
exit;
end;
MS.Seek(0,soFromBeginning);
if (Parse=-1)or(SaveToFile=-1) then
begin
result:=PChar('');
exit;
end;
result:=pchar(filename2);
MS.Free;
end;
exports
PluginType ,UrlPosition ,UrlKeyWord ,ReadExtFile;
begin
end.