[GELÖST] Dreh mich im Kreis mit 'ß'...

Für Fragen von Einsteigern und Programmieranfängern...
BitRausch
Beiträge: 50
Registriert: Di 30. Mai 2017, 09:32

[GELÖST] Dreh mich im Kreis mit 'ß'...

Beitrag von BitRausch »

Hallo,

vielleicht kann mir jemand helfen...sitze seit einiger Zeit an dem Problem...
Ich habe jetzt einiges zum Thema UTF8 / Ansi Konvertierung gelesen aber ich dreh mich hier im Kreis...
Aus eine CSV Datei (ANSI) lese ich eine Textfeld ein. Beim Einlesen habe ich folgenden Text in der String Variable drin stehen: ...Roter Strau'#157' (Sollte Roter Strauß stehen)
Dieses Feld soll über eine StringList in eine Text Datei geschrieben werden

Wenn ich ANSIToUTF8 benutze habe ich: Roter Strau�
Wenn ich UTF8ToAnsi benutze habe ich: Roter Strau?

Irgendwie bekomme ich es nicht hin das das 'ß' entweder in die Variable richtig eingelesen wird oder aber in der Ausgabe korrekt geschrieben wird.
Oder muss ich tatsächlich den String scannen und das Zeichen durch 'ss' ersetzen???

Noch zur Info:
OS Win7 / Win10, Lazarus 1.6.2, FPC 3.02, keine speziellen Compiler Schalter gesetzt.

PS. benutze die Unit csvreadwrite zum einlesen des Textes
Zuletzt geändert von BitRausch am Sa 30. Sep 2017, 12:52, insgesamt 1-mal geändert.

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: Dreh mich im Kreis mit 'ß'...

Beitrag von Timm Thaler »

Und wenn Du gar nicht konvertierst?

Unter Windows sollte FPC einen String erstmal als Ansistring ansehen, sofern nichts anderes angegeben.

BitRausch
Beiträge: 50
Registriert: Di 30. Mai 2017, 09:32

Re: Dreh mich im Kreis mit 'ß'...

Beitrag von BitRausch »

Hi Timm - danke für deine Antwort.
Ohne Konvertierung bekomme ich als Ausgabe 'Roter Strau '
Also ohne das ß am ende ...

Vielleicht sollte ich noch erwähnen das ich bei der Ausgabe einen String aus verschiedenen Felder erzeugen die ich in einer Stringlist hinzufüge um sie dann mit SaveToFile weg zuschreiben.
Die Felder werden mit PadRight formatiert
Diesem Fall s:= ...+...+PadRight(Beschreibung,65)
wobei Beschreibung die Feldvariable vom typ String ist..

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Dreh mich im Kreis mit 'ß'...

Beitrag von wp_xyz »

Nein, konvertieren auf irgendeine Art und Weise muss man schon, denn die Strings in der Daten sind wahrscheinlich für die Codeseite 1252 codiert, wir brauchen in Lazarus aber UTF8. Das geht seit FPC3.0 automatisch, wenn man alles richtig macht - siehe dazu http://wiki.freepascal.org/Unicode_Support_in_Lazarus. Am veständlichsten und einleuchtendsten sind in meinen Augen aber immer noch die expliziten Konvertierungsfunktionen. Nur muss man dazu wissen, dass seit fpc 3.0 funktionieren die "klassischen" Routinen AnsiToUtf8 und SysToUtf8 nicht mehr funktioniereen - das ist nach Einführung der neuen Strings so gewollt (wobei ich nie verstehe, ob das wirklich sein musste). Nimm stattdessen CP1252ToUTF8() aus lconvencoding oder WinCPToUTF8() aus LazUtf8. Falls du eine Zwischenvariable für den vom csvParser zurückgegebenen String verwenden willst, deklariere den aufnehmenden String am besten als RawBytestring, damit FPC nicht hier schon eine Konvertierung durchführt.

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var
  csv: TCSVParser;
  ms: TMemoryStream;
begin
  csv := TCSVParser.Create;
  try
    ms := TMemoryStream.Create;
    try
      ms.LoadfromFile(FILE_NAME);
      csv.Delimiter := #9;
      csv.SetSource(ms);
      csv.ResetParser;
      while csv.ParseNextCell do
        Memo1.Lines.Add(CP1252ToUtf8(csv.CurrentCellText));   // <--- hier
    finally
      ms.Free;
    end;
  finally
    csv.Free;
  end;
end;

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Dreh mich im Kreis mit 'ß'...

Beitrag von wp_xyz »

BitRausch hat geschrieben:Hi Timm - danke für deine Antwort.
Ohne Konvertierung bekomme ich als Ausgabe 'Roter Strau '
Also ohne das ß am ende ...

Vielleicht sollte ich noch erwähnen das ich bei der Ausgabe einen String aus verschiedenen Felder erzeugen die ich in einer Stringlist hinzufüge um sie dann mit SaveToFile weg zuschreiben.
Die Felder werden mit PadRight formatiert
Diesem Fall s:= ...+...+PadRight(Beschreibung,65)
wobei Beschreibung die Feldvariable vom typ String ist..

Hier stecken einige Stolperfallen drin...

SaveToFile: Wenn du vorher eine Konvertierung der Stringcodierung vorgenommen hast, sind die Strings, die du in die Datei schreibst UTF8. Ich weiß nicht, ob das vorkommen kann, aber deine Routine, die die Dateien eingelesen hat, darfst du dann auf diese Datei nicht anwenden, denn es war ja angenommen, dass die Strings die Codeseite 1252 haben. Ganz schön kompliziert... Schreibe die Datei als UTF8 mit BOM, dann ist klar, dass es eine UTF8-Datei ist, du musst das halt beim Einlesen prüfen. Oder konvertiere alles zurück auf ANSI und schreibe wieder eine ANSI-Datei mit Codepage 1252 (obwohl ich das heute nicht mehr machen würde, ANSI sollte allmählich verschwinden).

PadRight(Beschreibung, 65): Ich nehme an, dass das Feld nun UTF8-kodiert ist. Wenn das feld den Text "Strauß" enthält, musst du beachten, dass dieser String 7 Byte lang ist (statt 6), weil das ß in UTF8-Kodierung zwei Byte umfasst.. Die Funktion PadRight(...,65) füllt auf insgesamt 65 Byte auf - das heißt, wenn du z.B. mit Schriftart Courier mehrere so erweiterte Felder untereinander ausgibst, wird dieses um 1 Zeichen zu kurz sein. Nimm stattdessen die Funktion UTF8PadRight, die die "wahren" Zeichen zählt (aber etwas langsamer ist).

BitRausch
Beiträge: 50
Registriert: Di 30. Mai 2017, 09:32

Re: Dreh mich im Kreis mit 'ß'...

Beitrag von BitRausch »

vielen Dank wp_xyz.
Habe gerade

CP1252ToUtf8 getestet:

Roter Strau

und mit WinCPToUTF8

Roter Strau'

das selbe Ergebnis..

Einlesen und Ausgabe sind unterschiedlich Listen
TFPGObjectList vs TStringList

... wird dieses um 1 Zeichen zu kurz sein

genau das passiert mir gerade und zerschießt meinen fixen Satzaufbau in der Ausgabe...

mit UTF8PadRight fehlt mir weiterhin ein Zeichen...

Komisch finde ich das bei einem Text wie "Rosa Bl³ten" die anzahl stellen stimmen... auch wenn Umlaut nicht stimmt...
Ausgabe ist übrigens eine ANSI Datei. Bei der Stringliste benutze ich keine CodePage...

Wahnsinnig kompliziert das ganze

Edit: Ich nutze keine GUI Kontrollelemente zur Anzeige des Datensatzes...
Im Prinzip mach ich folgendes:
- Lesen eines CSV Datensatzes in ein TMyObject
- validieren des Datensatzes
- Add(TMyObject) zur TFPGObjectList
- Sortieren der Liste
- zusammenbauen eines Strings
- Add(s) to StringListe
- SaveToFile

Fast nur Stringoperationen/zuweisungen...

BitRausch
Beiträge: 50
Registriert: Di 30. Mai 2017, 09:32

Re: Dreh mich im Kreis mit 'ß'...

Beitrag von BitRausch »

vielleicht ist es einfacher Umlaute und das 'ß' im Feld zu ersetzen...
Gibt es eine Routine die Umlaute und das 'ß' einfach ersetzt bzw durch 'ae','ue','oe', 'ss' ersetzt ohne das ein Konvertierung UTF-8/Ansi notwendig wäre?

BitRausch
Beiträge: 50
Registriert: Di 30. Mai 2017, 09:32

Re: Dreh mich im Kreis mit 'ß'...

Beitrag von BitRausch »

... mich wundert auch das das 'ß' beim einlesen mit dem Code #157 im String angezeigt wird...
Das steht in der ASCII Tabelle für Ø
Das 'ß' hat den Code 225...
oder ist das nicht der ASCII Code??

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Dreh mich im Kreis mit 'ß'...

Beitrag von Mathias »

Aus eine CSV Datei (ANSI) lese ich eine Textfeld ein. Beim Einlesen habe ich folgenden Text in der String Variable drin stehen: ...Roter Strau'#157' (Sollte Roter Strauß stehen)

Etwas komisch ist, das ausgerechnet #157 für das ß steht. Was macht Excel mit der CSV-Datei ?
Ich vermute mal, deine CSV wurde mit einem exotischen ASCII-Format abgespeichert.

Was spuckt dein Programm aus, wen du folgendes mit deinem String machst, nachdem er von der CSV-Datei eingelesen wurde ?

Code: Alles auswählen

const
  s = 'Roter Strauß';
var
  i: integer;
begin
  for i := 1 to Length(s) do begin
    Writeln(s[i], byte(s[i]): 6);
  end;
end.



PS: Jetzt habe ich gerade was neues entdeckt, wen ich auf meiner CH-Tastatur [Alt-GR + s] drücke, kommt ein ß. :wink:
PS2: in der CT, die vor 2 Wochen erschienen ist, hat es einen grösseren Artikel, wieso wir so Theater mit den Umlauten haben.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Dreh mich im Kreis mit 'ß'...

Beitrag von wp_xyz »

Edit: Ich nutze keine GUI Kontrollelemente zur Anzeige des Datensatzes...

Dann hast du ein reines FPC-Programm, ohne LCL? Und die Ausgabe geht auf die Konsole? Da ist alles nochmals anders...

Am besten wäre, die streichst dein Programm zu einer minimalen Demo zusammen, die nichts anderes macht, als die Datei zu laden und anzuzeigen, und lade alles (d.h. *.pas, *.lfm, *.lpr, *.lpi, sowie die Datei) in ein zip gepackt hier hoch.

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Dreh mich im Kreis mit 'ß'...

Beitrag von Mathias »

Und die Ausgabe geht auf die Konsole? Da ist alles nochmals anders...

Das spielt es dann auch wieder eine Rolle, die Konsolen können mit verschieden Codepages voreingestellt sein.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

BitRausch
Beiträge: 50
Registriert: Di 30. Mai 2017, 09:32

Re: Dreh mich im Kreis mit 'ß'...

Beitrag von BitRausch »

Nein es ist kein Konsolenprogramm. Die Verarbeitung passiert quasi im Hintergrund. Der User wählt die einzulsenden Dateien aus und startet die Validierung/Konvertierung.
Wollte nur sagen das die Datensätze nicht über ein GUI Element angezeigt werden. Ich hatte gelesen das bei GUI Elementen es nochmal Besonderheiten für UTF-8/Ansi gibt...

MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Re: Dreh mich im Kreis mit 'ß'...

Beitrag von MacWomble »

in ANSI CP 1252 ist 157 nicht definiert

157 0x9D undefined

Es wäre hilfreich, etwas über die Quelle der Datei zu erfahren. Kommt diese eventuell aus einem fremdsprachigen Programm?
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Dreh mich im Kreis mit 'ß'...

Beitrag von wp_xyz »

BitRausch hat geschrieben:Nein es ist kein Konsolenprogramm [...] Wollte nur sagen das die Datensätze nicht über ein GUI Element angezeigt werden.

Sorry dass ich so dumm frage, aber wo ist dann das Problem? Wenn du die Strings weder in einem Gui-Control noch auf der Konsole anzeigst, wie willst du dann wissen, dass die Kodierung nicht stimmt?

BitRausch
Beiträge: 50
Registriert: Di 30. Mai 2017, 09:32

Re: Dreh mich im Kreis mit 'ß'...

Beitrag von BitRausch »

hmmm...
Ich vergleiche gerade die Excel Datei mit den CSV und Textdateien und sehe folgendes:

Code: Alles auswählen

Excel:                                                         Excel CSV                                                    Nach Programmdurchlauf                                     Satzalänge
Rosa Bl³ten                                                Rosa Bl³ten                                                  Rosa Bl³ten                                                       OK
RoterStrau                                               RoterStrau                                                RoterStrau                                                     -1 Zeichen
Ölgemälde                                                 "Ölgemälde "                                                "Ölgemälde "                                                     OK
Krüge                                                         Krüge                                                         Krüge                                                                OK
Klimagerät                                                 Klimagerät                                                  Klimagerät                                                        OK


Was mir Auffällt ist das, egal ob der Inhalt mit korrektem Umlaut angezeigt wird oder nicht, die Satzlänge stimmt. Nur bei dem Feld wo das 'ß' am ende steht gibts das Problem...
Vielleicht tatsächlich ein Sonderzeichen in Excel?
Abgespeichert wird die Tabelle in Excel normal mit Dateityp CSV...

Ich werde mal das Feld in Excel leeren und Beschreibung neu eingebe ... mal schauen

Antworten