美萍网管大师数据库资料存取方法

美萍网管大师是一款不错的网吧管理软件,但是其数据库却不是美萍惯用的Acess。这让需要从美萍存取数据变得异常的困难。

经笔者研究,网管大师主要有以下两个数据文件:scon.rec(保存用户上网消费记录),member81.cfg(记录用户信息)。其中scon.rec官方有提供数据记录格式。格式如下:

Type SconRecFile=Record
    RecType:Integer;                //此项记录的类型(0计时 1限时 2会员 3通宵)
    RecDate:TDateTime;           //此项记录的日期
    BeginTime:TDateTime;        //上机开始时间
    EndTime:TDateTime;           //上机结束时间
    RecMinTime:Integer;           //上机总用时(以分钟为单位)
    ComputerNum:Integer;      //此机机号
    Price:Real;                          //费率
    Money1:Real;                     //上机费用  负值代表费用转移了
    Money2:Real;                     //附加费用  负值代表费用转移了
    Money3:Real;                     //实收金额  负值代表费用转移了
    Manager:String[16];          //管理者名字
    Username:String[16];        //使用者名字
    Memo:String[100];            //备注
End;

根据以上数据,用Delphi读取数据时错误,发现以上格式有误。通过UE查看scon.rec发现每个数据包是196byte,但是依据以上的数据结构计算出来会占用(Integer:4Byte,TDateTime:8Byte,Real:8Byte;String[16]:是短字串,共17byte,第一个byte保存字串长度,后面16byte保存字串内容,string[100]类似,以上数据结构总长度:203Byte。也许是版本原因造成的差异)。经过仔细分析,发现数据结构应该是这样的:

  Type SconRecFile = packed Record
    RecType:Integer;              //此项记录的类型(0计时 1限时 2会员 3通宵)
    RecDate:TDateTime;          //此项记录的日期
    BeginTime:TDateTime;       //上机开始时间
    EndTime:TDateTime;          //上机结束时间
    RecMinTime:Integer;         //上机总用时(以分钟为单位)
    ComputerNum:Integer;     //此机机号
    Price:real48;                     //费率
    Money1:real48;                //上机费用  负值代表费用转移了
    Money2:real48;                //附加费用  负值代表费用转移了
    Money3:real48;                //实收金额  负值代表费用转移了
    Manager:String[16];         //管理者名字
    Username:String[16];       //使用者名字
    Memo:String[101];           //备注
  end;

差异如以上红字部分所示。(real48占用6byte)

根据以上数据结构,用Delphi写如下的代码便可读取scon.rec中的数据出来。

unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Memo1: TMemo; Button1: TButton; Edit1: TEdit; Label1: TLabel; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; SconRecFile = packed Record RecType:Integer; //此项记录的类型 RecDate:TDateTime; //此项记录的日期 BeginTime:TDateTime; //上机开始时间 EndTime:TDateTime; //上机结束时间 RecMinTime:Integer; //上机总用时(以分钟为单位) ComputerNum:Integer; //此机机号 Price:real48; //费率 Money1:real48; //上机费用 负值代表费用转移了 Money2:real48; //附加费用 负值代表费用转移了 Money3:real48; //实收金额 负值代表费用转移了 Manager:String[16]; //管理者名字 Username:String[16]; //使用者名字 Memo:String[101]; //备注 end; var Form1: TForm1; F:file of SconRecFile; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); var TestType:SconRecFile; i:LongInt; begin AssignFile(F,'scon.rec'); Reset(F); Memo1.Lines.Clear; while not eof(F) do begin Read(F,TestType); Memo1.Lines.Add('Filepos:'+inttostr(FilePos(f))); Memo1.Lines.Add('记录类型:'+IntToStr(TestType.RecType)); Memo1.Lines.Add('记录日期:'+dateToStr(TestType.RecDate)); Memo1.Lines.Add('上机开始时间:'+TimeToStr(TestType.BeginTime)); Memo1.Lines.Add('上机结束时间:'+TimeToStr(TestType.EndTime)); Memo1.Lines.Add('上机总用时:'+IntToStr(TestType.RecMinTime)+'分钟'); Memo1.Lines.Add('此机机号:'+IntToStr(TestType.ComputerNum)); Memo1.Lines.Add('费率:'+FormatFloat('0.00',TestType.Price)); Memo1.Lines.Add('上机费用:'+FormatFloat('0.00',TestType.Money1)); Memo1.Lines.Add('附加费用:'+FormatFloat('0.00',TestType.Money2)); Memo1.Lines.Add('实收金额:'+FormatFloat('0.00',TestType.Money3)); Memo1.Lines.Add('管理者名字:'+TestType.Manager); Memo1.Lines.Add('使用者名字:'+TestType.Username); Memo1.Lines.Add('备注:'+TestType.Memo); Memo1.Lines.Add('-------------------------------'); end; CloseFile(F); end; end.

可以依次数据格式做统计。

另外一个重要的数据表是用户信息。记录在member81.cfg文件中,官方没有公布此数据的格式,但是经过笔者用UE等工具仔细分析,还是发现了一些端倪。此文件也是无头文件,里面全部记录的都是data。其数据结构如下:

  MemRecFile = packed Record
    Usercode:string[20];                 //用户名
    Userpw:string[20];                    //密码(长度猜测,不一定对)
    other:array[0..29] of char;        //其它信息1
    osamt:single;                            //余额
    sumamt:single;                         //累计金额
    Memo:array [0..283] of char;    //其它信息2
  end;
因为时间所限,只将比较重要的信息(用户,密码,余额,总金额)的位置找出,其它信息相信也可轻松的找出来。

其中密码是加密的,其它信息估计都是是明文的。

根据以上结构,笔者写了以下的存取(读取/修改)此文件的代码:

unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Memo1: TMemo; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private { Private declarations } function getpassword(crystr:string):string; public { Public declarations } end; MemRecFile = packed Record Usercode:string[20]; //用户名 Userpw:string[20]; //密码 other:array[0..29] of char; //未知信息 osamt:single; //余额 sumamt:single; //累计金额 Memo:array [0..283] of char; //其他信息 end; var Form1: TForm1; F:file of MemRecFile; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); var TestType:MemRecFile; begin AssignFile(F,'member81.cfg'); Reset(F); Seek(F,500); Memo1.Lines.Clear; while not eof(F) do begin Read(F,TestType); Memo1.Lines.Add('Filepos:'+inttostr(FilePos(f))); Memo1.Lines.Add('使用者:' +TestType.Usercode); Memo1.Lines.Add('密码:' +getpassword(TestType.Userpw)); Memo1.Lines.Add('当前余额:' +formatfloat('0.00',TestType.osamt)); Memo1.Lines.Add('累计金额:' +formatfloat('0.00',TestType.sumamt)); Memo1.Lines.Add('-------------------------------'); end; CloseFile(F); end; procedure TForm1.Button2Click(Sender: TObject); var TestType:MemRecFile; begin //示例:修改某一笔数据的金额(充值30元) AssignFile(F,'member81.cfg'); Reset(F); Seek(F,555); Read(F,TestType); Seek(F,555); TestType.osamt:=TestType.osamt + 30; TestType.sumamt:=TestType.sumamt + 30; Write(F,TestType); CloseFile(F); end; function TForm1.getpassword(crystr:string):string; var i:integer; mychr: char; begin result:=''; for i:=1 to length(crystr) do begin case crystr[1] of #32:mychr:='i'; '1':mychr:='x'; '2':mychr:='{'; '3':mychr:='z'; '4':mychr:='}'; '5':mychr:='|'; '6':mychr:=chr(127); '7':mychr:='~'; '8':mychr:='q'; '9':mychr:='p'; '0':mychr:='y'; 'a':mychr:='('; 'b':mychr:='+'; 'c':mychr:='*'; 'd':mychr:='-'; 'e':mychr:=','; 'f':mychr:='/'; 'g':mychr:='.'; 'h':mychr:='!'; 'i':mychr:=#32; 'j':mychr:='#'; 'k':mychr:='"'; 'l':mychr:='%'; 'm':mychr:='$'; 'n':mychr:=''''; 'o':mychr:='&'; 'p':mychr:='9'; 'q':mychr:='8'; 'r':mychr:=';'; 's':mychr:=':'; 't':mychr:='='; 'u':mychr:='<'; 'v':mychr:='?'; 'w':mychr:='>'; 'x':mychr:='1'; 'y':mychr:='0'; 'z':mychr:='3'; '`':mychr:=')'; '{':mychr:='2'; '}':mychr:='4'; '|':mychr:='5'; chr(127):mychr:='6'; '~':mychr:='7'; '(':mychr:='a'; '+':mychr:='b'; '*':mychr:='c'; '-':mychr:='d'; ',':mychr:='e'; '/':mychr:='f'; '!':mychr:='h'; '#':mychr:='j'; '"':mychr:='k'; '%':mychr:='l'; '$':mychr:='m'; '''':mychr:='n'; '&':mychr:='o'; ';':mychr:='r'; ':':mychr:='s'; '=':mychr:='t'; '<':mychr:='u'; '?':mychr:='v'; '>':mychr:='w'; ')':mychr:='`'; else mychr:='X' end; result := result +mychr; end; end; end.

 

以上仅抛转引玉,错误在所难免,仅供参考。

你可能感兴趣的:(Delphi)