Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi [TFileStream] Widestring Dateinamen (https://www.delphipraxis.net/130044-%5Btfilestream%5D-widestring-dateinamen.html)

necromundo 2. Mär 2009 11:23


[TFileStream] Widestring Dateinamen
 
Hallo zusammen!

Ich habe hier eine Funktion, die einen Hash für eine Datei berechnen soll und dort wird ein Stream erzeugt wie hier:
Delphi-Quellcode:
Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
Nun soll FileName aber ein Widestring sein. solange keine Unicode-Zeichen im dateinamen vorkommen, funktioniert auch alles richtig! aber wenn, kommt ein EFOpenFileError.
Wie kann ich einen TFileStream erzeugen mit einem widestring-dateinnamen?? :gruebel:

vg, benny

himitsu 2. Mär 2009 11:25

Re: [TFileStream] Widestring Dateinamen
 
entweder du steigst auf Delphi2009 um (dort ist es Unicode)
oder du nutzt Fremdkomponente (z.B. von JEDI)
oder du leitest dir eine neue Klasse ab und überschreibst dieses .Create.


[add]
keine Ahnung ob's so richtig ist, aber es kompiliert zumindest :angel2:
Delphi-Quellcode:
Uses RTLConsts;

Type
  TFileStreamX = Class(TFileStream)
  Public
    Constructor Create(Const FileName: WideString; Mode: Word);                  Overload;
    Constructor Create(Const FileName: WideString; Mode: Word; Rights: Cardinal); Overload;
    Destructor Destroy; Override;
  End;

Constructor TFileStreamX.Create(Const FileName: WideString; Mode: Word);
  Begin
    Create(Filename, Mode, 0);
  End;

Constructor TFileStreamX.Create(Const FileName: WideString; Mode: Word; Rights: Cardinal);
  Const AccessMode: Array[0..2] of LongWord = (GENERIC_READ, GENERIC_WRITE, GENERIC_READ or GENERIC_WRITE);
    ShareMode: Array[0..4] of LongWord = (0, 0, FILE_SHARE_READ, FILE_SHARE_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE);

  Begin
    If Mode = fmCreate Then Begin
      Inherited Create(CreateFileW(PWideChar(FileName), GENERIC_READ or GENERIC_WRITE,
        0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0));
      If FHandle < 0 Then
        Raise EFCreateError.CreateResFmt(@SFCreateErrorEx, [ExpandFileName(FileName), SysErrorMessage(GetLastError)]);
    End Else Begin
      If ((Mode and 3) <= fmOpenReadWrite) and ((Mode and $F0) <= fmShareDenyNone) Then Begin
        Inherited Create(CreateFileW(PWideChar(FileName), AccessMode[Mode and 3],
          ShareMode[(Mode and $F0) shr 4], nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0));
      End Else Inherited Create(0);
      If FHandle < 0 Then
        Raise EFOpenError.CreateResFmt(@SFOpenErrorEx, [ExpandFileName(FileName), SysErrorMessage(GetLastError)]);
    end;
  End;

Destructor TFileStreamX.Destroy;
  Begin
    If FHandle >= 0 Then FileClose(FHandle);
    Inherited Destroy;
  End;

necromundo 2. Mär 2009 12:30

Re: [TFileStream] Widestring Dateinamen
 
hey,
danke erstmal für die schnelle antwort!

aber ich kann mit dem codeschnipsel leider noch nicht viel anfangen! wenn ich eine klasse ableiten will (hast du doch hiermit gemacht, ne), dann kann ich die ja in eine seperate datei schreiben und über uses einbinden, stimmts?
wie sieht so eine klasse.pas komplett aus?

himitsu 2. Mär 2009 13:11

Re: [TFileStream] Widestring Dateinamen
 
Zitat:

Zitat von necromundo
wenn ich eine klasse ableiten will (hast du doch hiermit gemacht, ne)

jupp, hab ich :angel:

Zitat:

Zitat von necromundo
dann kann ich die ja in eine seperate datei schreiben und über uses einbinden, stimmts?
wie sieht so eine klasse.pas komplett aus?

einfach denn Code in eine Unit packen und abspeichern :angel2:

hier als UnicodeFileStream.pas
Delphi-Quellcode:
Unit UnicodeFileStream;

Interface
  Uses RTLConsts, Windows, SysUtils, Classes;

  Type TFileStreamX = Class(TFileStream)
    Public
      Constructor Create(Const FileName: WideString; Mode: Word);                  Overload;
      Constructor Create(Const FileName: WideString; Mode: Word; Rights: Cardinal); Overload;
      Destructor Destroy; Override;
    End;

Implementation
  Constructor TFileStreamX.Create(Const FileName: WideString; Mode: Word);
    Begin
      Create(Filename, Mode, 0);
    End;

  Constructor TFileStreamX.Create(Const FileName: WideString; Mode: Word; Rights: Cardinal);
    Const AccessMode: Array[0..2] of LongWord = (GENERIC_READ, GENERIC_WRITE, GENERIC_READ or GENERIC_WRITE);
      ShareMode: Array[0..4] of LongWord = (0, 0, FILE_SHARE_READ, FILE_SHARE_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE);

    Begin
      If Mode = fmCreate Then Begin
        Inherited Create(CreateFileW(PWideChar(FileName), GENERIC_READ or GENERIC_WRITE,
          0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0));
        If FHandle < 0 Then
          Raise EFCreateError.CreateResFmt(@SFCreateErrorEx, [ExpandFileName(FileName), SysErrorMessage(GetLastError)]);
      End Else Begin
        If ((Mode and 3) <= fmOpenReadWrite) and ((Mode and $F0) <= fmShareDenyNone) Then Begin
          Inherited Create(CreateFileW(PWideChar(FileName), AccessMode[Mode and 3],
            ShareMode[(Mode and $F0) shr 4], nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0));
        End Else Inherited Create(0);
        If FHandle < 0 Then
          Raise EFOpenError.CreateResFmt(@SFOpenErrorEx, [ExpandFileName(FileName), SysErrorMessage(GetLastError)]);
      end;
    End;

  Destructor TFileStreamX.Destroy;
    Begin
      If FHandle >= 0 Then FileClose(FHandle);
      Inherited Destroy;
    End;

End.
aber wie gesagt ... ob alles richtig ist, hab ich jetzt nicht getestet :stupid:

necromundo 2. Mär 2009 13:20

Re: [TFileStream] Widestring Dateinamen
 
ach so, okay, das habe ich jetzt gemacht, aber er findet bei mir die rtlconsts nicht!
gehören die zu einem paket? oder wo kann ich die herbekommen?
ich benutze übrigens delphi 5! ;)

Luckie 2. Mär 2009 13:39

Re: [TFileStream] Widestring Dateinamen
 
Delphi-Quellcode:
Inherited Create(CreateFileW(PWideChar(FileName), GENERIC_READ or GENERIC_WRITE,
          0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0));
        If FHandle < 0 Then
          Raise EFCreateError.CreateResFmt(@SFCreateErrorEx, [ExpandFileName(FileName), SysErrorMessage(GetLastError)]);
Sollte MSDN-Library durchsuchenCreateFile fehlschlagen ist der Rückgabewert nicht kleiner null, sondern INVALID_HANDLE_VALUE:
Zitat:

If the function fails, the return value is INVALID_HANDLE_VALUE. To get extended error information, call GetLastError.

himitsu 2. Mär 2009 14:19

Re: [TFileStream] Widestring Dateinamen
 
ich weiß, aber immerhin ist Integer(INVALID_HANDLE_VALUE) kleiner 0 :stupid:

nja, ich hab das so aus Delphi rauskopiert und nur den Unicode-Teil geändert :angel:

Luckie 2. Mär 2009 14:24

Re: [TFileStream] Widestring Dateinamen
 
Nun ja, ich bevorzuge die Konstanten und halte mich lieber an die Dokumentation.

himitsu 2. Mär 2009 14:26

Re: [TFileStream] Widestring Dateinamen
 
[add]
hab's mal geändert, aber wie gesagt, so wurde es halt in D7 gemacht :roll:
[/add]

RTLConst ist eigentlich von Delphi (zumindestens war die vorhin beim Delphi 7 dabei).
Eigentlich ist diese Datei nur drin, da ich die Konstanten bei den Exceptions so gelassen hatte.

Weiß zufällig wer, wo in D5 die nötigen Resourcestrings liegen?

Nja, erstmal ohne die RTLConsts, aber dafür mit direkt eingebauten Exception-Strings in deutsch.
Delphi-Quellcode:
Unit UnicodeFileStream;

Interface
  Uses Windows, SysUtils, Classes;

  Type TFileStreamX = Class(TFileStream)
    Public
      Constructor Create(Const FileName: WideString; Mode: Word);                  Overload;
      Constructor Create(Const FileName: WideString; Mode: Word; Rights: Cardinal); Overload;
      Destructor Destroy; Override;
    End;

Implementation
  Constructor TFileStreamX.Create(Const FileName: WideString; Mode: Word);
    Begin
      Create(Filename, Mode, 0);
    End;

  Constructor TFileStreamX.Create(Const FileName: WideString; Mode: Word; Rights: Cardinal);
    Const AccessMode: Array[0..2] of LongWord = (GENERIC_READ, GENERIC_WRITE, GENERIC_READ or GENERIC_WRITE);
      ShareMode: Array[0..4] of LongWord = (0, 0, FILE_SHARE_READ, FILE_SHARE_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE);

    Begin
      If Mode = fmCreate Then Begin
        Inherited Create(CreateFileW(PWideChar(FileName), GENERIC_READ or GENERIC_WRITE,
          0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0));
        If FHandle = INVALID_HANDLE_VALUE Then
          Raise EFCreateError.CreateFmt('Datei "%s" kann nicht erstellt werden. %s',
            [ExpandFileName(FileName), SysErrorMessage(GetLastError)]);
      End Else Begin
        If ((Mode and 3) <= fmOpenReadWrite) and ((Mode and $F0) <= fmShareDenyNone) Then Begin
          Inherited Create(CreateFileW(PWideChar(FileName), AccessMode[Mode and 3],
            ShareMode[(Mode and $F0) shr 4], nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0));
        End Else Inherited Create(0);
        If FHandle = INVALID_HANDLE_VALUE Then
          Raise EFOpenError.CreateFmt('Datei %s kann nicht geöffnet werden. %s',
            [ExpandFileName(FileName), SysErrorMessage(GetLastError)]);
      end;
    End;

  Destructor TFileStreamX.Destroy;
    Begin
      If FHandle >= 0 Then FileClose(FHandle);
      Inherited Destroy;
    End;

End.

Luckie 2. Mär 2009 14:30

Re: [TFileStream] Widestring Dateinamen
 
Die hardcodierten Zeichenketten sind natürlich nicht gerade optimal. Aber eine erste Verbesserung wäre es sie als Ressourcenstrings zu deklarieren.


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:25 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz