![]() |
INI ASCII/ANSI oder Unicode ?
Hallo alle,
gibt es einen Weg einfach festzustellen ob eine bestimmte/vorhandene Datei als ASCII/ANSI oder UTF Datei abgespeichert wurde ? Ich habe ein kleines Programm geschrieben, das für ein älteres Programm einige Sachen prüft. Nun hat sich herausgestellt, das Leute a) eine INI Datei geöffnet, editiert und gespeichert haben und b) dann aus unerklärlichen Gründen UTF benutzt haben wodurch die INI Datei nicht mehr vom Programm zu gebrauchen war. Habe schon ein bisschen gesucht aber noch nix gefunden. Habe mal mit Ultraedit 2 Dateien geöffnet die ich vorher mit Notepad als ANSI bzw. UTF gespeichert habe und Ultraedit erkennt es. Im HEX Editor konnte ich sehen das bei der UTF Datei die ersten Stellen FF FE 64 00 beinhalten sowie nach(oder vor) jedem Zeichen ein 00 steht während in einer ANSI/ASCI Datei nur die einzelnen Zeichen zu finden sind. Würde es reichen nur die ersten 2 Stellen auf FF und FE zu Testen ? |
Re: INI ASCII/ANSI oder Unicode ?
Hallo,
kurz und schmerzlos: ![]() Die Tnt-Controls (wie auch immer die inzwischen heißen) können damit übrigens automatisch umgehen. Gruß xaromz |
Re: INI ASCII/ANSI oder Unicode ?
Wenn du nur überprüfen möchtest, ob die Datei eine "normale" Text-Datei im ANSI-Format ist, kannst du die untere Funktion verwenden. Wenn du zusätzlich noch herrausfinden möchtest, welches Format exakt vorliegt, könntest du einen Blick in die
![]()
Delphi-Quellcode:
////////////////////////////////////////////////////////////////////////////////
// Konstanten: //////////////////////////////////////////////////////////////////////////////// const FILE_OPEN_FAILED = -2; const FILE_NOT_FOUND = -1; const FILE_IS_NOT_BINARY = 0; const FILE_IS_BINARY = 1; //////////////////////////////////////////////////////////////////////////////// // Dateien: Gibt die Größe einer Datei zurück (auch über 4 GB) //////////////////////////////////////////////////////////////////////////////// function GetFileSize(const FileName: String): Int64; var FileHandle: Cardinal; Data: WIN32_FIND_DATA; begin Result := -1; FileHandle := FindFirstFile(PChar(FileName), Data); try if FileHandle > 0 then begin Int64Rec(Result).Hi := Data.nFileSizeHigh; Int64Rec(Result).Lo := Data.nFileSizeLow; end; finally Windows.FindClose(FileHandle); end; end; //////////////////////////////////////////////////////////////////////////////// // Dateien: Prüft, ob eine Datei binäre Zeichen enthält //////////////////////////////////////////////////////////////////////////////// function IsBinaryFile(const FileName: String): Integer; const MAX_BUFFER = 4096; // Clustergröße ValidControlChars: Set of Byte = [9, 10, 12, 13]; // typische Textsteuerzeichen var Buffer: Array[1..MAX_BUFFER] of Byte; FilePosition, FileSize: Int64; FileHandle, FileBlocks, LastBlock, BufferSize: Integer; i, j: Integer; begin Result := FILE_IS_NOT_BINARY; FilePosition := 0; if FileExists(FileName) then begin FileHandle := FileOpen(FileName, fmOpenRead or fmShareDenyNone); try if FileHandle > 0 then begin FileSize := GetFileSize(FileName); // Dateigröße in Byte ermittln FileBlocks := FileSize div MAX_BUFFER; // Anzahl max. Blöcke LastBlock := FileSize mod MAX_BUFFER; // Größe des Rest-Block // Letzten Block hinzufügen if LastBlock <> 0 then Inc(FileBlocks); // Blöcke einlesen for i := 0 to FileBlocks -1 do begin if Result = FILE_IS_BINARY then Break; // Aktuelle Dateiposition anpassen FileSeek(FileHandle, FilePosition, 0); Inc(FilePosition, MAX_BUFFER); if FilePosition <= FileSize then BufferSize := MAX_BUFFER else BufferSize := LastBlock; FileRead(FileHandle, Buffer[1], BufferSize); for j := 1 to BufferSize do begin if Buffer[j] < 32 then begin if not (Buffer[j] in ValidControlChars) then begin Result := FILE_IS_BINARY; Break; end; end; end; {\for: j} end; {\for: i} end else Result := FILE_OPEN_FAILED; finally FileClose(FileHandle); end; end else Result := FILE_NOT_FOUND; end; |
Re: INI ASCII/ANSI oder Unicode ?
Danke !!!
Beide Ansätze sind nachvollziehbar. Werde erstmal den Code ausprobieren (ja, ja ich bin faul :P ). Wenn er das tut was ich benötige werde ich das Rad bestimmt nicht neu erfinden :P |
Re: INI ASCII/ANSI oder Unicode ?
Bin erst heute dazu gekommen den Code zu testen. Bei einer Text-Datei die im Ansi Format abgespeichert wurde bekomme ich 0 zurück. Bei der gleichen Datei als Unicode gespeichert bekomme ich 1 zurück. Gleiche Datei als UTF-8 bekomme ich 0 zurück.
Alles mit dem Code Beispiel von Bigg. Habe bei Überprüfung des Thread Titels aber auch gemerkt das die Frage nicht ganz korrekt ist :lol: Da ich nur Ansi gebrauchen kann und kein UTF/Unicode :) Werde mir mal das ganze genauer ansehen. |
Re: INI ASCII/ANSI oder Unicode ?
Hallo,
Zitat:
Gruß xaromz |
Re: INI ASCII/ANSI oder Unicode ?
Da ich mir die Text Datei im HEX Editor angesehen habe würde es also reichen am Anfang der Datei zu prüfen:
EF BB (BF) => UTF 8 FE FF, FF FE, 00 00 FE FF => auch nicht ANSI ( :-D ) Oder sehe ich das Falsch ? Ich habe in meinem Programm schon einen Byte Check. Der prüft aber nur eine Stelle (zb. Offset: 0 EF). Könnte ich auch gleich Offset 0 EF BB prüfen ?
Delphi-Quellcode:
Bernd
function checkpatchuneven(exefile: string;offset: Integer; svalue: string):string;
var // p: string; Ft: file; tmp: byte; begin //showmessage('File to check: '+exefile); //showmessage('Offset to check: '+offset); //showmessage('Value to check: '+svalue); Assignfile(Ft, exefile); FileMode := 0; //Read Only Reset(Ft, 1); Seek(Ft, offset); blockread(Ft, tmp, Sizeof(tmp)); //Temp is the result in decimal number and Sizeof is the just the size of the number. closefile(Ft); if IntToHex(tmp,2)<> svalue then begin //showmessage('Active'); Result := 'Activated'; end else begin //showmessage('Not Active'); Result := 'Not Activated'; end; end; |
Re: INI ASCII/ANSI oder Unicode ?
Hallo,
folgende Routine verwende ich (stammt von den TntUnicode-Controls):
Delphi-Quellcode:
Eine komplette Datei lesen kannst Du so:
type
TStreamCharSet = (csAnsi, csUnicode, csUnicodeSwapped, csUtf8); const UNICODE_BOM = WideChar($FEFF); UNICODE_BOM_SWAPPED = WideChar($FFFE); UTF8_BOM = AnsiString(#$EF#$BB#$BF); function DetectCharacterSet(const Stream: TStream): TStreamCharSet; var ByteOrderMark: WideChar; BytesRead: Integer; Utf8Test: array[0..2] of AnsiChar; begin // Byte Order Mark ByteOrderMark := #0; if (Stream.Size - Stream.Position) >= SizeOf(ByteOrderMark) then begin BytesRead := Stream.Read(ByteOrderMark, SizeOf(ByteOrderMark)); if (ByteOrderMark <> UNICODE_BOM) and (ByteOrderMark <> UNICODE_BOM_SWAPPED) then begin ByteOrderMark := #0; Stream.Seek(-BytesRead, soFromCurrent); if (Stream.Size - Stream.Position) >= Length(Utf8Test) * SizeOf(AnsiChar) then begin BytesRead := Stream.Read(Utf8Test[0], Length(Utf8Test) * SizeOf(AnsiChar)); if Utf8Test <> UTF8_BOM then Stream.Seek(-BytesRead, soFromCurrent); end; end; end; if ByteOrderMark = UNICODE_BOM then Result := csUnicode else if ByteOrderMark = UNICODE_BOM_SWAPPED then Result := csUnicodeSwapped else if Utf8Test = UTF8_BOM then Result := csUtf8 else Result := csAnsi; end;
Delphi-Quellcode:
Diese Funktion liefert Dir einen WideString mit dem Dateiinhalt bzw. einen Leerstring bei einem Fehler.
procedure StrSwapByteOrder(Str: PWideChar);
var P: PWord; begin P := PWord(Str); while (P^ <> 0) do begin P^ := MakeWord(HiByte(P^), LoByte(P^)); Inc(P); end; end; function ReadFile(const FileName: WideString): WideString; var Stream: TStream; DataLeft: Integer; StreamCharSet: TStreamCharSet; SW: WideString; SA: AnsiString; begin SW := ''; Stream := TFileStream.Create(FileName, fmOpenRead); try StreamCharSet := DetectCharacterSet(Stream); DataLeft := Stream.Size - Stream.Position; case StreamCharSet of csAnsi: begin SetLength(SA, DataLeft div SizeOf(AnsiChar)); Stream.Read(PAnsiChar(SA)^, DataLeft); SW := SA; end; csUnicode, csUnicodeSwapped: begin if DataLeft < SizeOf(WideChar) then SW := '' else begin SetLength(SW, DataLeft div SizeOf(WideChar)); Stream.Read(PWideChar(SW)^, DataLeft); if StreamCharSet = csUnicodeSwapped then StrSwapByteOrder(PWideChar(SW)); end; end; csUtf8: begin SetLength(SA, DataLeft div SizeOf(AnsiChar)); Stream.Read(PAnsiChar(SA)^, DataLeft); SW := UTF8Decode(SA); end; end; finally Stream.Free; end; Result := SW; end; Gruß xaromz |
Re: INI ASCII/ANSI oder Unicode ?
Vielen Dank ! Falls ich noch Fragen dazu habe werde ich wieder melden ;) Habe jetzt nämlich ein anderes Problem :-D
|
Re: INI ASCII/ANSI oder Unicode ?
Wenn die Funktion IsBinaryFile() = 0 liefert, ist die Datei im ANSI-Format.
Eine solche Datei sollte sich dann problemlos im Texteditor anzeigen lassen. Hat der Benutzer allerdings das Zeilenumbruchformat verstellt z.B. auf LF (UNIX), dann sieht es im Notepad natürlich nicht grade leserlich aus. edit: Ich sehe grad, die Funktion liefert, wie von Bernd geschrieben bei UTF8 kodierten Dateien nicht das gewüntschte Ergebnis. Vielleicht solltest du dann lieber auf die SynUnicode.pas zurückgreifen. Dort sind Funktionen enthalten, die das exakt feststellen können. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:03 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz