序言
现在代码还在完善中,计划周六先总结,现在现放个思路和原码。
运行效果
filedata 类视图
代码
filedata
unit uDatafile;
interface
uses
SysUtils, Vcl.Dialogs, System.Classes;
type
StrArray = array of array of string;
type
Datafile = class
private
FRTotal, FCol, FstartRow: Integer;
FDataStr: StrArray;
bufList: Tstringlist;
function GetCol(s: string): Integer; //返回任意字符串的的列数
procedure GetDetail(); //获取 数据开始行 数据列数 数据总列数
public
constructor Create(filename: string);
destructor destroy;
procedure Getdata(readstart: Integer; readend: Integer); //可以读取任意一段的接口
//属性 都是只读
property RTotal: Integer read FRTotal;
property Col: Integer read FCol;
property StartRow: Integer read FstartRow;
property Datastr: StrArray read FDataStr;
end;
implementation
{ Datafile }
constructor Datafile.Create(filename: string);
begin
FRtotal := 0;
FCol := 0;
FstartRow := 0;
bufList := TStringList.Create;
bufList.LoadFromFile(filename);
GetDetail();
SetLength(FDataStr, FRTotal + 1, FCol);
end;
destructor Datafile.destroy;
begin
bufList.Free;
end;
function Datafile.GetCol(s: string): Integer;
var
List: TStringList;
begin
List := TStringList.Create;
//这样去判断其实也能精确 但是暂时够用了
ExtractStrings([';', ',', #9, ' '], [], PChar(s), List); //通过 拆分 list长度来就是字符串的列数
result := List.Count;
List.Free;
end;
procedure Datafile.GetDetail;
var
i, n: Integer;
s: array[0..2] of string; //用于判断连续的三行
ss, t1, t2: string;
begin
i := 0;
n := 0;
while i < 200 do
begin
//读取连续三行,保存到s 里面
for n := 0 to 2 do
begin
s[n] := bufList[i + n];
end;
//判断连续三行是否相等
if (GetCol(s[0]) = GetCol(s[1])) and (GetCol(s[0]) = GetCol(s[1])) and (GetCol(s[0]) = GetCol(s[1])) then
begin
ss := Trim(s[0]); //移除左边的空格哇
t1 := Copy(ss, 0, 1); //取出第一个字符
ss := Trim(s[2]);
t2 := Copy(ss, 0, 1);
if (t1 >= #48) and (t1 <= #57) and (t2 >= #48) and (t2 <= #57) then //判断他们是不是数字
begin
Fcol := GetCol(ss); //如果是数那么这段应该是就是数据的开始行
Break;
end;
end;
Inc(i, 1);
end;
FstartRow := i + 1; //咱们从零开始计数的 要加1
Frtotal := bufList.Count - FstartRow;
end;
procedure Datafile.Getdata(readstart, readend: Integer);
var
lt: TStringList;
i, n: Integer;
buf: string;
begin
if readstart > readend then
ShowMessage('开始行不能大于结束行')
else
begin
for i := 0 to (readend - readstart) do //我们当然是要循环readend - readstart次
begin
lt := TStringList.Create;
buf := bufList[i + readstart + Fstartrow - 1]; //减一的原因还是应为 从0开始计数
buf := Trim(buf);
if Pos(',', buf) <> 0 then
extractstrings([','], [], pchar(buf), lt)
else if Pos(';', buf) <> 0 then
extractstrings([';'], [], pchar(buf), lt)
else if Pos(#9, buf) <> 0 then
extractstrings([#9], [], pchar(buf), lt)
else
extractstrings([' '], [], pchar(buf), lt);
if lt.Count <= Fcol then //如果列数发生变化了有可能就是异常数据
begin
for n := 0 to lt.Count - 1 do
begin
buf := lt[n];
FDataStr[i + readstart, n] := buf;
//ShowMessage(FDataStr[i + readstart, n]);
end;
end;
lt.Free;
end;
end;
end;
end.
窗口主程序
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
uDatafile, Vcl.Grids, Vcl.ExtCtrls, Vcl.StdCtrls;
type
TMainForm = class(TForm)
pnlgrid: TPanel;
strngrd: TStringGrid;
grpMmo: TGroupBox;
Mmo: TMemo;
pnlPaint: TPanel;
pbDraw: TPaintBox;
grpbotton: TGroupBox;
grpChooseDraw: TGroupBox;
btnDraw0: TButton;
grpMouse: TGroupBox;
btn1: TButton;
btn2: TButton;
lbl: TLabel;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
const
filename: string = 'data.rec';
var
MainForm: TMainForm;
data: Datafile; //打开一个文件 建立一个对象
Fflag, Dflag: Integer; //分别标记打开文件和画图
procedure Topenfile();//打开文件,如果数据超过5000行那么就多线程打开
function openover(): integer;//判断数据是否读取完毕
procedure Fillgrid();//填充表格
implementation
{$R *.dfm}
procedure TMainForm.FormCreate(Sender: TObject);
begin
Fflag := 0;
Dflag := 0;
data := Datafile.Create(filename);
TOpenFile();
if openover() = 4 then
begin
//ShowMessage('文件读取完毕');
strngrd.RowCount := data.RTotal + 3;
strngrd.ColCount := data.Col + 1;
strngrd.Cells[0, 0] := '序号';
strngrd.Cells[1, 0] := '时间 (h)';
strngrd.Cells[2, 0] := '压力 (MPa)';
strngrd.Cells[3, 0] := '温度(degC)';
Fillgrid();
end;
end;
procedure Topenfile();
var
total, n: Integer;
begin
total := data.RTotal;
if total < 5000 then
begin
data.Getdata(0, data.RTotal);
Fflag := 4;
end
else
begin
n := total mod 4;
total := total - n;
TThread.CreateAnonymousThread(
procedure
begin
data.Getdata(0, total div 4);
Fflag := Fflag + 1;
end).Start;
TThread.CreateAnonymousThread(
procedure
begin
data.Getdata(total div 4 + 1, total div 2);
Fflag := Fflag + 1;
end).Start;
TThread.CreateAnonymousThread(
procedure
begin
data.Getdata(total div 2 + 1, (total div 4) * 3);
Fflag := Fflag + 1;
end).Start;
TThread.CreateAnonymousThread(
procedure
begin
data.Getdata((total div 4) * 3 + 1, total + n);
Fflag := Fflag + 1;
end).Start;
end;
end;
function openover(): integer;
begin
while Fflag <> 4 do
begin
;
end;
result := 4;
end;
procedure Fillgrid();
var
total, n: Integer;
begin
total := data.RTotal;
n := total mod 2;
total := total - n;
TThread.CreateAnonymousThread(
procedure
var i: Integer;
begin
for i := 0 to data.rtotal + n do
begin
mainform.strngrd.Cells[0, i + 1] := IntToStr(i);
mainform.strngrd.Cells[1, i + 1] := data.Datastr[i, 0];
mainform.strngrd.Cells[2, i + 1] := data.Datastr[i, 1];
mainform.strngrd.cells[3, i + 1] := data.Datastr[i, 2];
end;
end).Start;
end;
end.