Einzelnen Beitrag anzeigen

magnusp

Registriert seit: 1. Apr 2017
3 Beiträge
 
#9

AW: Generics Type feststellen?

  Alt 1. Apr 2017, 18:26
Danke für die Hilfe! Falls das mal jemand benötigt hier meine Version (mit ein bischen Generics)

Code:
Type
  TCustomCSVFile<T> = Class
  private
    fRowCount: Integer;
    fColCount: Integer;
    fData: Array Of Array Of T;
    function GetData(ACol, ARow: Integer): T;
    procedure SetData(ACol, ARow: Integer; const Value: T);
  protected
    procedure TrimData(AData: TStringList);
    function CalcColCount(AData: TStringList): Integer;
    procedure SetDataRow(ARow, MaxCol: Integer; const Data: TStringDynArray); virtual; abstract;
    function GetDataRow(ARow: Integer): String; virtual; abstract;
  public
    procedure Clear; virtual; abstract;
    procedure LoadFromFile(FileName: String);
    procedure SaveToFie(FileName: String);
    procedure DimData(ColCount, RowCount: Integer);

    property RowCount: Integer read fRowCount;
    property ColCount: Integer read fColCount;
    property Data[ACol, ARow: Integer]: T read GetData write SetData;
  End;

  TDoubleCSVFile = Class(TCustomCSVFile<Double>)
  protected
    procedure SetDataRow(ARow, MaxCol: Integer; const Data: TStringDynArray); override;
    function GetDataRow(ARow: Integer): String; override;
  End;

  TIntegerCSVFile = Class(TCustomCSVFile<Integer>)
  protected
    procedure SetDataRow(ARow, MaxCol: Integer; const Data: TStringDynArray); override;
    function GetDataRow(ARow: Integer): String; override;
  End;
Die Implementierung sieht dann (ungetestet) wie folgt aus:

Code:

{ TCustomCSVFile }

procedure TCustomCSVFile<T>.DimData(ColCount, RowCount: Integer);
begin
  SetLength(fData, ColCount, RowCount);
end;

procedure TCustomCSVFile<T>.LoadFromFile(FileName: String);
var
  LTmp: TStringList;
  i, LEnd: Integer;
  sa: TStringDynArray;
  j: Integer;
begin
  LTmp := TStringList.Create;
  try
    LTmp.LoadFromFile(FileName);
    TrimData(LTmp);
    fColCount := CalcColCount(LTmp);
    fRowCount := LTmp.Count;
    if (fColCount > 0) And (fRowCount > 0) then
    begin
      DimData(fColCount, fRowCount);
      for i := 0 to fRowCount-1 do
      begin
        sa := SplitString(LTmp[i], ',');
        LEnd := Min(fColCount, Length(sa));
        SetDataRow(i, LEnd, sa);
      end;
    end
    else
      Clear;

  finally
    LTmp.Free;
  end;
end;

procedure TCustomCSVFile<T>.SaveToFie(FileName: String);
var
  LTmp: TStringList;
  i, j: Integer;
begin
  LTmp := TStringList.Create;
  try
    for i := 0 to Length(fData)-1 do
    begin
      LTmp.Add(GetDataRow(i));
    end;

    LTmp.SaveToFile(FileName);
  finally
    LTmp.Free;
  end;
end;

function TCustomCSVFile<T>.GetData(ACol, ARow: Integer): T;
begin
  Result := fData[ACol, ARow];
end;

procedure TCustomCSVFile<T>.SetData(ACol, ARow: Integer; const Value: T);
begin
  fData[ACol, ARow] := Value;
end;

function TCustomCSVFile<T>.CalcColCount(AData: TStringList): Integer;
var
  sa: TStringDynArray;
begin
  // use the first row (after TrimData)
  sa := SplitString(AData[0], ',');
  Result := Length(sa);
end;

procedure TCustomCSVFile<T>.TrimData(AData: TStringList);
var
  i: Integer;
  Ln: string;
begin
  for i := AData.Count-1 downto 0 do
  begin
    Ln := Trim(AData[i]);
    if (Length(Ln) > 0) And (((Ln[1] >= '0') And (Ln[1]<='9')) Or (Ln[1]='+') Or (Ln[1]='-')) then
    begin
      AData[i] := Ln;
    end
    else
      AData.Delete(i);
  end;
end;

{ TDoubleCSVFile }

function TDoubleCSVFile.GetDataRow(ARow: Integer): String;
var
  i: Integer;
  sa: TStringDynArray;
  LFmtSet: TFormatSettings;
begin
  LFmtSet := TFormatSettings.Create();
  LFmtSet.DecimalSeparator := '.';
  SetLength(sa, High(fData[ARow]));
  for i := 0 to High(fData[ARow]) do
  begin
    sa[i] := FloatToStr(fData[ARow, i], LFmtSet);
  end;
  Result.Join(',', sa);
end;

procedure TDoubleCSVFile.SetDataRow(ARow, MaxCol: Integer; const Data: TStringDynArray);
var
  i: Integer;
  LFmtSet: TFormatSettings;
begin
  LFmtSet := TFormatSettings.Create();
  LFmtSet.DecimalSeparator := '.';
  for i := 0 to MaxCol-1 do
  begin
    fData[ARow, i] := StrToFloatDef(Data[i], 0.0, LFmtSet )
  end;
end;

{ TIntegerCSVFile }

function TIntegerCSVFile.GetDataRow(ARow: Integer): String;
var
  i: Integer;
  sa: TStringDynArray;
begin
  for i := 0 to High(fData[ARow]) do
  begin
    sa[i] := IntToStr(fData[ARow, i]);
  end;
  Result.Join(',', sa);
end;

procedure TIntegerCSVFile.SetDataRow(ARow, MaxCol: Integer; const Data: TStringDynArray);
var
  i: Integer;
begin
  for i := 0 to MaxCol-1 do
  begin
    fData[ARow, i] := StrToIntDef(Data[i], 0);
  end;
end;
  Mit Zitat antworten Zitat