Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Cross-Platform-Entwicklung (https://www.delphipraxis.net/91-cross-platform-entwicklung/)
-   -   Delphi Ansi Encoding ohne Leerzeichen (https://www.delphipraxis.net/193481-ansi-encoding-ohne-leerzeichen.html)

QuickAndDirty 4. Aug 2017 15:59

Ansi Encoding ohne Leerzeichen
 
Hallo
Ich schicke aus einer Delphi APP ein Logfile an Einen Windows Rechner.
Diese Logfile soll in Notepad.exe dargestellt werden.

Delphi-Quellcode:
function TLog.Internal_GetEmailFile: String;
var alogtext:String;
begin
  result := '';
  Internal_ReadFile(alogtext);
  if tFile.Exists(fEmailFile) then
    Tfile.Delete(fEmailFile);
  TFile.WriteAllText(femailfile,UTF8Encode(aLogText), TEncoding.UTF8 );
  result := femailfile;
end;
Wie muss ich das Encoding beim Speichern einstellen damit nicht vor jedem Zeichen ein Leerzeichen steht?

MEissing 4. Aug 2017 16:06

AW: Ansi Encoding ohne Leerzeichen
 
TEncoding.ANSI

(Das war einfach :-))

himitsu 4. Aug 2017 16:22

AW: Ansi Encoding ohne Leerzeichen
 
PS: Das ist kein Leerzeichen, es ist eine 0.

Die 0 vom HighByte des Unicode, wenn da das Char maximal als #255 ist. :zwinker:



Aber wenn die 0 auch bei deinem TEncoding.UTF8 vorhanden war, dann stimmt bei dir noch was Anderes nicht.

QuickAndDirty 4. Aug 2017 16:28

AW: Ansi Encoding ohne Leerzeichen
 
Es war bei Tencoding.Ansi
und bei Tencoding.UTF8 vorhanden :(
WriteAllText Schreibt im UTF 8 fall sogar (laut source) eine BOM davor.

Es ist total seltsam

Uwe Raabe 4. Aug 2017 17:10

AW: Ansi Encoding ohne Leerzeichen
 
Das
Delphi-Quellcode:
Utf8Encode
ist doch völlig überflüssig (wenn nicht sogar schädlich!), denn
Delphi-Quellcode:
WriteAllText
erwartet dort einen
Delphi-Quellcode:
string
und übernimmt selbst das Encoding.

QuickAndDirty 7. Aug 2017 11:17

AW: Ansi Encoding ohne Leerzeichen
 
Ich habe es jetzt umgestellt auf folgendes Verfahren...

Delphi-Quellcode:
function TLog.Internal_GetEmailFile: String;
var alogtext:String;
   AnsiArr:Tbytes;
   UniCodeArr:tBytes;
begin
  result := '';
  Internal_ReadFile(alogtext);
  if tFile.Exists(fEmailFile) then
    Tfile.Delete(fEmailFile);
  unicodeArr := Tencoding.Unicode.GetBytes(aLogtext);
  AnsiArr := TEncoding.Convert(Tencoding.Unicode,Tencoding.ANSI, unicodeArr );
  Tfile.WriteAllBytes(femailfile,AnsiArr);

//  TFile.WriteAllText(femailfile,aLogText, TEncoding.ANSI );

  result := femailfile;
end;
....Notepad.exe gibt mir das mit chinesischen Zeichen wieder :(

Welches ist die native codierung von Strings und Dateien in Delphi Tokyo für Android apps?

Das ist ein Copy&Paste aus dem Ctrl+F7 aud aLogtext
Code:
'4.08.17 17:59:52 EnteredBackground'#012#000'4.08.17 17:59:53 WillBecomeInactive'#012#000'4.08.17 17:59:55 WillBecomeForeground'#012#000'4.08.17 17:59:55 BecameActive'#012#000'4.08.17 17:59:58 WillBecomeInactive'#012#000'4.08.17 18:00:00 EnteredBackground'#012#000'4.08.17 18:00:00 BecameActive'#012#000'4.08.17 18:00:00 WillBecomeInactive'#012#000'4.08.17 18:00:04 WillBecomeForeground'#012#000'4.08.17 18:00:04 BecameActive'#012#000'4.08.17 18:00:09 EnteredBackground'#012#000'4.08.17 18:00:09 WillBecomeInactive'#012#000'4.08.17 18:00:14 WillBecomeForeground'#012#000'4.08.17 18:00:14 BecameActive'#012#000'4.08.17 18:00:48 EnteredBackground'#012#000'4.08.17 18:00:54 WillBecomeInactive'#012#000'4.08.17 18:01:46 Log active'#012#000'4.08.17 18:01:46 App Start'#012#000'4.08.17 18:01:49 FinishedLaunching'#012#000'4.08.17 18:03:42 Log active'#012#000'4.08.17 18:03:42 App Start'#012#000'4.08.17 18:03:53 FinishedLaunching'#012#000'4.08.17 18:06:05 WillBecomeForeground'#012#000'4.08.17 18:06:05 BecameActive'#012#000'4.08.17 18:06:16 EnteredBackground'#012#000'4.08.17 18:06:17 WillBecomeInactive'#012#000'4.08.17 18:06:21 WillBecomeForeground'#012#000'4.08.17 18:06:21 BecameActive'#012#000'4.08.17 18:06:55 EnteredBackground'#012#000'4.08.17 18:07:02 WillBecomeInactive'#012#000'4.08.17 18:07:33 WillBecomeForeground'#012#000'4.08.17 18:07:33 BecameActive'#012#000'4.08.17 18:11:01 EnteredBackground'#012#000'4.08.17 18:11:01 WillBecomeInactive'#012#000'7.08.17 12:18:09 Log active'#012#000'7.08.17 12:18:09 App Start'#012#000'7.08.17 12:18:22 FinishedLaunching'#012#000'7.08.17 12:18:29 WillBecomeForeground'#012#000'7.08.17 12:18:30 BecameActive'#012
Also schon beim Lesen der Datei sind überflüssige #000 drin. Nur am ende ist keines drin. Ich weiß nicht wie die dort rein kommen, bzw wenn sie teil des zeilenumbruchs sind, warum am ende dann keine #000 steht.

QuickAndDirty 7. Aug 2017 12:00

AW: Ansi Encoding ohne Leerzeichen
 
Ok Diese Version funktioniert für Notepad.exe, leider sind dann die Zeilenumbrüche weg.
Sublime Text zeigt dann aber nur eine HExDump an.

Delphi-Quellcode:
function TLog.Internal_GetEmailFile: String;
var alogtext:String;
   AnsiArr:Tbytes;
   UTF8Arr:tBytes;
begin
  result := '';
  Internal_ReadFile(alogtext);
  if tFile.Exists(fEmailFile) then
    Tfile.Delete(fEmailFile);
  UTF8Arr := Tencoding.UTF8.GetBytes(aLogtext);
  AnsiArr := TEncoding.Convert(Tencoding.UTF8,Tencoding.ANSI, UTF8Arr );
  Tfile.WriteAllBytes(femailfile,AnsiArr);

//  TFile.WriteAllText(femailfile,aLogText, TEncoding.ANSI );

  result := femailfile;
end;
Zeilenumbrüche mache ich so mit linefeed...
Delphi-Quellcode:
  aText := Datetimetostr(now) + ' ' + aText + linefeed;
  FStream.Write(aText[1], length(aText) * Sizeof(aText[1]) );

QuickAndDirty 7. Aug 2017 12:34

AW: Ansi Encoding ohne Leerzeichen
 
OK,Das hier ist die Lösung.
Delphi-Quellcode:
function TLog.Internal_GetEmailFile: String;
var alogtext:String;
begin
  result := '';
  Internal_ReadFile(alogtext);
  alogtext := aLogtext.Replace(''+linefeed, ''+carriageReturn+''+linefeed, [rfReplaceAll] );
  alogtext := alogtext.Replace(''#0,'',[rfReplaceAll]);
  if tFile.Exists(fEmailFile) then
    Tfile.Delete(fEmailFile);
  TFile.WriteAllText(femailfile,aLogText, TEncoding.UTF8 );

  result := femailfile;
end;
Ich weiß nicht wie die ganzen "null" werte da rein kommen, aber es fühlt sich so ein bisschen an als würde der Filestream einen Nulltermnierten string schreiben, und auch die #0 in die Datei speichern.

nahpets 7. Aug 2017 13:07

AW: Ansi Encoding ohne Leerzeichen
 
In 'nem FileStream ist alles drin, bei 'nem #0-terminierten String auch die #0, da sie ein Teil von ihm ist.

QuickAndDirty 7. Aug 2017 13:41

AW: Ansi Encoding ohne Leerzeichen
 
Zitat:

Zitat von nahpets (Beitrag 1378258)
In 'nem FileStream ist alles drin, bei 'nem #0-terminierten String auch die #0, da sie ein Teil von ihm ist.

Ist der Datentyp "String" in Firemonkey Anwendungen für Android ein Nullterminierter unicode string?

himitsu 7. Aug 2017 15:10

AW: Ansi Encoding ohne Leerzeichen
 
Jain.

String ist ein Delphi-String mit Unicode (seit 2009)
Delphi-Strings haben eine Längenangabe (wie in dynamisches "Array of Char"), außerdem besitzen sie aus Kompatibilitätsgründen und für "einfache" PChar-Casts auch eine implizit abschließende Doppel-Null (#0#0).

nahpets 7. Aug 2017 15:11

AW: Ansi Encoding ohne Leerzeichen
 
Kenne mich da nicht mit aus, aber ist nicht inzwischen alles, was nicht im Bereich von String[1] bis String[255] liegt, ein nullterminierter String?
Aus die Schnelle fand ich das: http://www.delphipraxis.net/166685-s...erminiert.html

himitsu 7. Aug 2017 15:55

AW: Ansi Encoding ohne Leerzeichen
 
Nein.

String (Delphi 1) und String[Länge] nennen sich jetzt "ShortString" und das ist ein Record/StaticArray mit einem Längen-Byte auf Char[0]. (darum fangen in Delphis Strings auch bei 1 an)

Der LongString, aka String, AnsiString und UnicodeString, ist ein aufgemotztes dynamisches Array (array of char), mit CodePage neben dem Längen-Integer und hinten ein implizites #0#0.

QuickAndDirty 7. Aug 2017 15:57

AW: Ansi Encoding ohne Leerzeichen
 
Zitat:

Zitat von himitsu (Beitrag 1378271)
Jain.

String ist ein Delphi-String mit Unicode (seit 2009)
Delphi-Strings haben eine Längenangabe (wie in dynamisches "Array of Char"), außerdem besitzen sie aus Kompatibilitätsgründen und für "einfache" PChar-Casts auch eine implizit abschließende Doppel-Null (#0#0).

:(

Hm, dessen war ich mir nicht bewusst.

So ein bisschen ärgert es mich auch. Aber gut, genau hinsehen hätte mir sowas ja auch verraten.
bekomme ich die doppelnullterminierung auch vom Tstringhelper.toCharArray und Tencoding.unicode.Getbytes ?

Sprich was ist der richtige Buffer für filestream write?

nahpets 7. Aug 2017 17:03

AW: Ansi Encoding ohne Leerzeichen
 
Habe gerade mal in meinem ollen Delphi 7 probiert:
Delphi-Quellcode:
var
  s1     : String[1];
  s255   : String[255];
  s     : String;
  sShort : ShortString;
begin
  ShowMessage(Format('s = %d, s1 = %d, s255 = %d, sShort = %d',  [SizeOf(s),SizeOf(s1),SizeOf(s255),SizeOf(sShort)]));
end;
Das liefert mir
Code:
s = 4, s1 = 2, s255 = 256, sShort = 256
Daraus schließe ich jetzt einfach mal (bitte korrigiert mich):

String[255] entspricht ShortString, String[1] bis String[255] verhalten sich wie schon beim alten Turbopascal. (Array of Char, bei dem an Position 0 die Längenangabe des tatsächliche genutzten Teils des Arrays steht.)

String ist, wie himitsu beschrieb, eine nullterminierte Zeichenfolge.

QuickAndDirty 7. Aug 2017 17:16

AW: Ansi Encoding ohne Leerzeichen
 
ich schreibe das jetzt alles so
Delphi-Quellcode:
      aText := Datetimetostr(now) + ' ' + aText + linefeed;
      aByteArr := TEncoding.Utf8.GetBytes(aText);
      //FStream.Write(aText[1], length(aText) * Sizeof(aText[1]) );
      FStream.WriteData(aByteArr, Length(aByteArr));
Datei wird wie folgt erzeugt, damit es passt
Delphi-Quellcode:
    if not TFile.Exists(fLogFile) then
    Begin
      FileOpenMode := fmCreate;
      fStream := TFileStream.create( self.fLogFile, FileOpenMode );
      Preambel := Tencoding.UTF8.GetPreamble;
      fStream.WriteData(Preambel,length(Preambel));
      fStream.free;
    End;
Ich öffne mehrere (wenige und kleine)Logfiles und hänge sie hintereinander in einen String.
Delphi-Quellcode:
  aText := aText + TFile.ReadAllText(flogfile,Tencoding.UTF8);
Dann erzeuge ich aus dem String eine einzige Datei für ein Email Attchment.
Delphi-Quellcode:
function TLog.Internal_GetEmailFile: String;
var alogtext:String;
begin
  result := '';
  Internal_ReadFile(alogtext);
  alogtext := aLogtext.Replace(''+linefeed, ''+carriageReturn+''+linefeed, [rfReplaceAll] );//für Notepad.exe
  alogtext := alogtext.Replace(''#0,'',[rfReplaceAll]);//einfach zur sicherheit.
  if tFile.Exists(fEmailFile) then
    Tfile.Delete(fEmailFile);
  TFile.WriteAllText(femailfile,aLogText, TEncoding.UTF8 );//erzeugt eine UTF8 Preambel (BOM)
  result := femailfile;
end;
Diese Datei kann ich dann tatsächlich per notepad.exe öffnen.

Problem ist also gelöst..
und viel über kodierung und strings dabei gelernt.

himitsu 7. Aug 2017 19:39

AW: Ansi Encoding ohne Leerzeichen
 
Zitat:

Zitat von nahpets (Beitrag 1378289)
Daraus schließe ich jetzt einfach mal (bitte korrigiert mich):

String[255] entspricht ShortString, String[1] bis String[255] verhalten sich wie schon beim alten Turbopascal. (Array of Char, bei dem an Position 0 die Längenangabe des tatsächliche genutzten Teils des Arrays steht.)

String ist, wie himitsu beschrieb, eine nullterminierte Zeichenfolge.

Der Typ (Type-Definition) ShortString entspricht String[255].
String[1] bis String[255] sind ShortString (DatenFormat-Definition).

Und LongString (AnsiString und UnicodeString) sowie WideString arbeiten mit Längen-Bytes/Integern, aber haben auch PChar-Charakteristiken drin, die aber vom String selber nicht verwendet werden.
WideString ist fast so wie LongString, nur etwas Einfacher und es wird von der OleAuth32.dll verwaltet. (WinAPI und deren SpeicherManager)

Delphi-Quellcode:
var
  S1, S2, S3: string;

S1 := 'abc'#0'def';
S2 := Copy(S1); // S2 := S1; ... damit auch wirklich der Inhalt kopiert wird, da LongStrings referenzverwaltet sind und sonst nur den Pointer, aber nicht den Inhalt kopieren
S3 := PChar(S1);
ShowMessage(Format('%d %d %d', [Length(S1), Length(S2), Length(S3)]));


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:04 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