Ein Verzeichnis (alle Ordner und Dateien) mit findfirst und findnext auslesen

  • Im folgenden Beispiel wird der Inhalt eines Verzeichnisses (c:) in einer ListBox dargestellt.
  • Die Hilfsfunktionen ConvertTimeToStr(), ConvertDateToStr() und ConvertAttribToStr() extrahieren Fileinformationen aus dem Struct dirinfo und generieren daraus fertige AnsiStrings.
  • u.U. sollte man noch den Header dir.h einbinden
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    struct ffblk dirinfo;

    // zum 1. Directoryeintrag in c: springen und alle Filetypen suchen
    int result = findfirst("c:\\*.*", &dirinfo, FA_NORMAL | FA_RDONLY | FA_HIDDEN | FA_SYSTEM | FA_DIREC | FA_ARCH);

    // solange Einträge da sind, in der Listbox ausgeben
    while (result == 0)
    {
        ListBox1->Items->Add(ConvertTimeToStr(dirinfo.ff_ftime)) +", "+ ConvertDateToStr(dirinfo.ff_fdate)) +", "+ ConvertAttribToStr(dirinfo.ff_attrib)));
        result = findnext(&dirinfo);
    }
}

AnsiString __fastcall TForm1::ConvertTimeToStr(int ffTime)
{
    return IntToStr(ffTime & 0x1F) + ":" + IntToStr(ffTime & 0x3F) + ":" + IntToStr(2 * (ffTime & 0x1F));
}

AnsiString __fastcall TForm1::ConvertDateToStr(int ffDate)
{
    return IntToStr(ffDate & 0x1F) + ":" + IntToStr(ffDate & 0xF) + ":" + IntToStr((ffDate & 0x7F) + 1980);
}

AnsiString __fastcall TForm1::ConvertAttribToStr(int ffAttrib)
{
    AnsiString sResult = "";
    if ((ffAttrib & FA_DIREC) != 0 ) sResult = sResult + "D";
    if ((ffAttrib & FA_RDONLY) != 0 ) sResult = sResult + "R";
    if ((ffAttrib & FA_HIDDEN) != 0 ) sResult = sResult + "H";
    if ((ffAttrib & FA_SYSTEM) != 0 ) sResult = sResult + "S";
    if ((ffAttrib & FA_ARCH) != 0 ) sResult = sResult + "A";
    if ((ffAttrib & FA_NORMAL) != 0 ) sResult = sResult + "N";
    return sResult;
}

FileStreams lesen und schreiben

Die Datensätze (struct) werden in eine Datei geschrieben und daraus ein beliebiger Datensatz zurückgelesen.

  • Im Beispielprogramm werden zwei Buttons verwendet, hinter denen sich das Schreiben bzw. Lesen verbirgt
  • Edit1 beinhaltet die Nummer des zu lesenden Datensatzes
  • Die gelesenen TestDaten werden in einem Memofeld ausgegeben
  • Daten, die in dem Struct ‘Daten’ vom Typ data stehen, werden in eine Datei ‘datafile.dat’ im aktuellen Verzeichnis geschrieben
  • soll die Datei später in einem anderen Zusammenhang geöffnet werden, so muss im TFileStream-Konstruktor statt fmCreate fmOpenRead, fmOpenWrite oder fmOpenReadWrite verwendet werden!!
  • Unit1.h
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
struct data
{
    char Name[15]; // 15 Zeichen langer Name -> kein (!!!) AnsiString verwenden!!!
    bool bWert;
    DWORD dwWert;
    float fWert;
    int iWert;
};

class TForm1 : public TForm
{
__published: // Von der IDE verwaltete Komponenten

    TButton *Button1;
    TMemo *Memo1;
    TButton *Button2;
    TEdit *Edit1;
    void __fastcall Button1Click(TObject *Sender);
    void __fastcall Button2Click(TObject *Sender);

private: // Anwender-Deklarationen
public:  // Anwender-Deklarationen

    data *Daten; //Zeiger auf eine Datenstruktur
    __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
  • Unit1.cpp
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    float Temp; // temporäre Zwischenvariable für float-Wert
    int i;
    AnsiString Name;

    Daten = new data; // Neues Datenstruktur-Objekt
    TFileStream *Datei = new TFileStream(".datafile.dat", fmCreate);

    // 100 Testwerte schreiben
    for (i=1;i<=100;i++)
    {
        Name = "Testname" + IntToStr(i);   // Namen zusammenbauen
        strcpy(Daten->Name, Name.c_str()); // und nach Daten->Name übergeben

        Daten->bWert = i%2 ? true : false; // bool-Wert übergeben
        Daten->dwWert = i;
        Temp = i;
        Daten->fWert = Temp/2;             // float-Wert übergeben
        Daten->iWert = i;                  // int-Wert übergeben

        Datei->Write(Daten, sizeof(data)); // struct "Daten" in die Datei schreiben
    }

    delete Daten;
    delete Datei;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
    Daten = new data;
    TFileStream *Datei = new TFileStream(".datafile.dat", fmOpenRead);

    // Datensatzzeiger auf den entsprechenden Datensatz setzen
    // in Edit1 steht die Nummer des zu lesenden Datensatzes
    Datei->Seek(Edit1->Text.ToIntDef(1) * sizeof(data), soFromBeginning);

    // Daten aus der Datei in das struct "Daten" einlesen
    Datei->Read(Daten, sizeof(data));

    // Testdaten ausgeben
    Memo1->Lines->Clear();
    Memo1->Lines->Add(Daten->Name);

    if (Daten->bWert) Memo1->Lines->Add("true");
    else Memo1->Lines->Add("false");

    Memo1->Lines->Add(IntToStr(Daten->dwWert));
    Memo1->Lines->Add(FloatToStr(Daten->fWert));
    Memo1->Lines->Add(IntToStr(Daten->iWert));

    delete Daten;
    delete Datei;
}

INI-Dateien erstellen/bearbeiten

#include "inifiles.hpp" //wichtig!!!

void __fastcall TForm1::IniAction(AnsiString IniData)
{
    AnsiString sIniFileName;
    AnsiString IniData;

    sIniFileName = ExtractFilePath(ParamStr(0)) + "IniDatei.ini";

    TIniFile* IniFile = new TIniFile(sIniFileName);
    if (IniFile != NULL)
    {
        IniFile -> UpdateFile();

        // IniData lesen:
        IniData = IniFile -> ReadString("ReadSection", "Key", "Defaultwert");

        // IniData schreiben:
        IniFile -> WriteString("WriteSection", "Key", IniData);

        delete IniFile;
        IniFile = NULL;
    }
}

Datenbanktabellen (SQLQuery-Abfragen) in eine CSV-Datei schreiben

void __fastcall TForm1::SaveToCSV(TQuery *Abfrage)
{
    TStringList *Spaltenbezeichner, *Ausgabe;
    AnsiString Bezeichner, Inhalt;

    Spaltenbezeichner = new TStringList;
    Ausgabe = new TStringList;

    // ermittle die Spaltenbezeichner
    Abfrage->GetFieldNames(Spaltenbezeichner);

    for (int Spalte=0; Spalte < Spaltenbezeichner->Count; Spalte++)
    {
        Bezeichner += Spaltenbezeichner->Strings[Spalte] + &quot;;&quot;;
    }

    // schreibe die Bezeichner ins AusgabeStringlistenObjekt
    Ausgabe->SetText(Bezeichner.c_str());
    delete Spaltenbezeichner;

    Abfrage->First();

    // ermittle die Einträge aus aktuellem Datensatz
    for (int Zeile=0; Zeile < Abfrage->RecordCount; Zeile++)
    {
        for (int Spalte = 0; Spalte < Abfrage->Fields->Count; Spalte++)
        {
            //gehe zur nächsten Zeile des Abfrageobjekts
            //schreibe Zeile in String durch ; getrennt
            Inhalt += Abfrage->Fields->Fields[Spalte]->AsString + &quot;;&quot;;
        }

        // schreibe Zeile in AusgabeStringlistenobjekt
        Ausgabe->Append(Inhalt);

        // leere String -> für Werte aus neuer Zeile
        Inhalt = &quot;&quot;;

        // gehe zu nächstem Datensatz
        Abfrage->Next();
    }

    // speichere Inhalt als CSV-Datei
    Ausgabe->SaveToFile(&quot;c:\\Ausgabedatei.csv&quot;);

    Application->MessageBox(&quot;Datei wurde erfolgreich gespeichert&quot;, &quot;Hinweis&quot;, MB_OK);
    delete Ausgabe;
}

Prozess mit CreateProcess starten und auf Beendigung warten

void __fastcall StartProcess()
{
    AnsiString sPrgName = "c:winnt
otepad.exe";

    AnsiString sWorkDir = "c:winnt";

    TProcessInformation prozessinfo;
    TStartupInfo startinfo;

    startinfo.cb = sizeof(TStartupInfo);
    setmem(&startinfo,sizeof(TStartupInfo),0);

    if (CreateProcess(NULL, sPrgName.c_str(), NULL, NULL, false, CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS, NULL, sWorkDir.c_str(), &startinfo, &prozessinfo) == true)
    {
        //Speicher freigeben
        CloseHandle(prozessinfo.hThread);

        //Warteschleife, die PROZESSINFO abfragt
        while(WaitForSingleObject(prozessinfo.hProcess, 100) == WAIT_TIMEOUT)
        Application->ProcessMessages();

        //hier angekommen ist das Programm durch den Benutzer beendet worden
        Application->MessageBox("Programm geschlossen!","",MB_OK);

        //Speicher freigeben
        CloseHandle(prozessinfo.hProcess);
    }
}

Dateien über WINSHELLAPI kopieren oder bewegen

  • Aufruf:
// Quelle: Pfad + Dateiname(n) der Quelldatei(en)
// Ziel: Zielpfad
// Modus: 0 - Dateien kopieren, 1 - Dateien bewegen
if (!CopyMoveFiles("c:\\Temp*.*", "c:\\TempTest", 0))
    ShowMessage("Ausführung erfolgreich !");
else
    ShowMessage("Fehler aufgetreten !");
  • Code:
int TForm1::CopyMoveFiles(AnsiString slSourceDir, AnsiString slTargetDir, int Mode)
{
    SHFILEOPSTRUCT sh;
    ZeroMemory(&sh, sizeof(sh));

    sh.hwnd = NULL;

    sh.fFlags = FOF_NOCONFIRMATION | FOF_FILESONLY | FOF_NOCONFIRMMKDIR | FOF_SILENT;

    if (Mode == 0)

        sh.wFunc = FO_COPY; // Dateien kopieren

    else

        sh.wFunc = FO_MOVE; // Dateien bewegen

    slSourceDir+="\0";
    sh.pFrom = slSourceDir.c_str();
    slTargetDir+="\0";
    sh.pTo = slTargetDir.c_str();
    sh.hNameMappings = NULL;
    sh.lpszProgressTitle = NULL;

    return SHFileOperation (&sh); // Aktion durchführen
}

Dateigröße ermitteln

int iFileHandle;
int iFileLength;

if (OpenDialog1->Execute())
{
    iFileHandle = FileOpen(OpenDialog1->FileName, fmOpenRead);
    iFileLength = FileSeek(iFileHandle, 0, 2);
    FileClose(iFileHandle);
}

Anwendung ausführen

  • Aufruf-Beispiele:
AnsiString FileName = "c:windowscalc.exe";
RunApplication(FileName.c_str(), 0);

RunApplication("mailto:hallihallo@mail.de", 0);

RunApplication("http://www.google.de", 0);

RunApplication("meine.exe", "1 2 3");

RunApplication("net", "use");

RunApplication("format", "a: /s");
  • Code:
// führt per ShellExecute die Anwendung, die mit der Dateiendung von FileName
// assoziert ist aus, FileParam spezifiziert zusätzliche Aufrufparameter
void RunApplication(LPCTSTR FileName, LPCTSTR FileParam)
{
    int ret = (int) ShellExecute(0, &quot;open&quot;, FileName, FileParam, 0, SW_SHOWNORMAL);

    if (ret <= 32)
    {
        AnsiString msg;

        switch(ret)
        {
            case ERROR_FILE_NOT_FOUND, SE_ERR_FNF :
            msg = &quot;Die angegebene Datei '&quot; + AnsiString(FileName) + &quot;' wurde nicht gefunden!&quot;;
            break;

            case ERROR_PATH_NOT_FOUND, SE_ERR_PNF :
            msg = &quot;Der Pfad zur Datei '&quot; + AnsiString(FileName) + &quot;' wurde nicht gefunden!&quot;;
            break;

            case ERROR_BAD_FORMAT :
            msg = &quot;Die aufgerufene Anwendung ist ungültig oder beschädigt!&quot;;
            break;

            case SE_ERR_ACCESSDENIED, SE_ERR_SHARE :
            msg = &quot;Der Zugriff auf die Datei '&quot; + AnsiString(FileName) + &quot;' wurde vom Betriebssystem verweigert!&quot;;
            break;

            case SE_ERR_ASSOCINCOMPLETE, SE_ERR_NOASSOC :
            msg = &quot;Der angegebene Dateityp ist auf Ihrem Computer keiner Anwendung zugeordnet!&quot;;
            break;

            case 0, SE_ERR_OOM :
            msg = &quot;Zum Ausführen der Anwendung ist nicht genügend Arbeitsspeicher frei!&quot;;
            break;

            default : msg = &quot;Datei '&quot; + AnsiString(FileName) + &quot;' konnte nicht geöffnet werden!&quot;;
        }

        Application->MessageBox(msg.c_str(), &quot;Fehler&quot;, MB_OK + MB_ICONERROR);
    }
}