Einzelnen Beitrag anzeigen

Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#24

Re: Datei von Datei exportieren?

  Alt 12. Okt 2004, 03:20
So, voll funktionstüchtiges Demo im Anhang. Die relevanten Routinen sind wiederverwendbar und es wird nur demonstriert, wie man sie einsetzt. Erklärungen befinden sich im Quellcode, die hardgecodeten Stellen sind markiert.

Delphi-Quellcode:
{************************************************************

  Demoprogramm für die Funktionen zum Einlesen der
  Indexdatei und zum extrahieren einer Dstei aus der
  Quelldatei.

  Anmerkungen:
  ============

  Die Funktion ReadIndexFile liest die Indexdatei aus
  und gibt ein Array vom Typ TFileInfos zurück.
  TFileInfos ist ein dynamisches Array vom Typ TIdxFile.

  Die Prozedur ExtractFile extrahiert aus einer beliebigen
  Quelldatei eine Byte-Sequenz und schreibt sie in die
  angegebene Datei. Der Typ der Quelldatei ist beliebig.

  Die TODO's markieren die Stellen im Demoprogramm, die
  hardgecodet sind. Wie man sieht befinden sie sich nur
  in den Stellen im Quellcode, wo die Funktionsweise
  der relevanten Routinen demonstriert werden.
  Die relevanten Routinen sind also wiederverwendbar.

  Willst du nun alle Dateien extrahieren, liest du die
  Indexdatei ein, gehst sie in einer Schleife durch und
  rufst die Prozedur ExtravtFile mit den entsprechenden
  Parametern auf. Aufpassen musst du nur bei der letzten
  Datei, da es dort keinen Nachfolger gibt:

  IdxFile := FileInfoArray[IDX];
  IdxFileNext := FileInfoArray[IDX+1];  // <-- !!!

  Eine Lösung wäre einen zweiten Record zu definieren,
  der auch die Dateigröße behinhaltet und dessen Feld für
  die Dateigröße gleich so mit der Dateigröße zu füllen,
  wie es beim Anzeigen der Indexdatei im Listview gemacht
  wird:

  NewItem.SubItems.Add(IntToStr(FileInfoArray[i + 1].OffSet -
    FileInfoArray[i].OffSet));


  Schlussbemerkung:
  =================

  @Newbie44:
  Ich bin der Meinung dass es sauber programmiert ist. Du
  kannst dir ja mal im Quellcode ankucken, wie man Fehler
  behandelt und sauber abfängt. Wie du siehst, haben sie
  einen relativ hohen Anteil am Quellcode, aber das ist
  nötig, um eben alle auftretenden Fehler abfangen zu
  können. Es gibt nichts unschöneres, als einen Programm-
  absturz, weil eine Datei nicht geöffnet oder geschrieben
  werden konnte und damit muss man immer rechnen.

  Ich hoffe, du hast was gelernt, wenn du den Quellcode
  genauer studiert hast.

************************************************************}
Die interessaneten Routinen schon mal hier im Posting:

Delphi-Quellcode:
// vermuteter Aufbau der Indexdatei:
type
  TIdxFile = record
    Filename: array[0..19] of Char;
    OffSet: DWord;
  end;
  PIdxFile = ^TIdxFile;

  TFileInfos = array of TIdxFile;

// [..]

////////////////////////////////////////////////////////////////////////////////
//
// ExtractFile
//
// Extrahier eine Datei aus SrcFile nach DestFile
// Wirft Exceptions EReadError bzw. EWriteError beim Lesen bzw. Schreiben
//

procedure ExtractFile(SrcFile, DestFile: string; Offset: Int64; FileSize:
  Integer);
var
  ms: TMemoryStream;
  fs: TFileStream;
  Buffer: PByteArray;
resourcestring
  rsEReadError = 'Fehler beim Lesen der Datei %s';
  rsEWriteError = 'Fehler beim Schreiben in die Datei %s';
begin
  ms := TMemoryStream.Create;
  fs := TFileStream.Create(DestFile, fmCreate);
  try
    // Datei laden und Dateizeiger positionieren
    ms.LoadFromFile(SrcFile);
    ms.Seek(OffSet, soFromBeginning);
    // Speicher für Buffer anfordern
    GetMem(Buffer, FileSize);
    try
      try
        // Bytes aus SrcFile nach DestFile kopieren
        ms.ReadBuffer(Buffer^, FileSize);
        fs.WriteBuffer(Buffer^, FileSize);
      except
        on E: EReadError do
          raise E.Create(rsEReadError);
        on E: EWriteError do
          raise E.Create(rsEWriteError);
      end;
    finally
      FreeMem(Buffer, FileSize);
    end;
  finally
    FreeAndNil(ms);
    FreeAndNil(fs);
  end;
end;

////////////////////////////////////////////////////////////////////////////////
//
// ReadIndexFile
//
// Indexdatei einlesen
// Wirft eine Exception EReadError bei Lesefehler
//

function ReadIndexFile(Filename: string): TFileInfos;
var
  fs: TFileStream;
  i: Integer;
resourcestring
  rsEReadError = 'Fehler beim einlesen der Datei %s';
begin
  i := 0;
  fs := TFileStream.Create(Filename, fmOpenRead);
  try
    // 2 Bytes nach vorne springen, da steht noch was, aber ich weiß nicht was,
    // Eventuell eine Signatur oder so
    fs.Seek(2, soFromBeginning);
    // Größe des dynamisches Array setzten (Dateigröße / Recordgröße = Anzahl Datensätze)
    SetLength(result, fs.Size div sizeof(TIdxFile));
    // so lange lesen bis wir am Ende sind
    while fs.Position < fs.Size do
    begin
      try
        fs.ReadBuffer(result[i], sizeof(TIdxFile));
        Inc(i);
      except
        on E: EReadError do
          raise E.Create(Format(rsEReadError, [Filename]));
      end;
    end;
  finally
    FreeAndNil(fs);
  end;
end;
Angehängte Dateien
Dateityp: zip demo_157.zip (736,6 KB, 8x aufgerufen)
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat