AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Zeilenumbruch ersetzen Algorithmus

Ein Thema von hansklok · begonnen am 10. Mär 2018 · letzter Beitrag vom 15. Mär 2018
Antwort Antwort
Delphi.Narium

Registriert seit: 27. Nov 2017
2.596 Beiträge
 
Delphi 7 Professional
 
#1

AW: Zeilenumbruch ersetzen Algorithmus

  Alt 10. Mär 2018, 23:11
grober Vorschlag:

zwei Streams nehmen:

1. Stream = Input
2. Stream = Output

1. Stream byteweise (oder charweise) lesen.
2. jedes Zeichen abfragen, ob es in den Output soll.
3. Zeichen schreiben oder verwerfen.

ungefähr (ungetestet) sowas:
Delphi-Quellcode:
procedure TIrgendeineKlasse.Zeichenaustauschen(input : TMemoryStream; output : TMemoryStream);
Var
  ch : Char;
begin
  input.Position := 0;
  output.Position := 0;
  // Ist überhaupt was in der Datei drin?
  if input.Read(ch, 1) > 0 then begin
    repeat
      case ch of
        // Hier zeichenweise entscheiden, was geschehen soll.
        #10 : begin
                output.Write(ch,1);
              end;
        #13 : begin
                // output.Write(ch,1);
              end;
      else
        // Übrige Zeichen ausgeben.
        output.Write(ch,1);
      end;
    until input.Read(ch, 1) = 0;
    input.Position := 0;
    output.Position := 0;
  end;
end;
Das sollte auch bei größeren Datenmengen noch vertretbar schnell sein.
  Mit Zitat antworten Zitat
hansklok

Registriert seit: 14. Apr 2004
Ort: Karlsruhe
318 Beiträge
 
Delphi 2010 Architect
 
#2

AW: Zeilenumbruch ersetzen Algoritmud

  Alt 11. Mär 2018, 12:51
Vielen Dank schon einmal für die vielen Beitröge. Ich versuche darauf einzugehen. Wie gesagt, ich bin kein Profi und mir geht es eher um einen Aufbau des Algorithmus.

Es geht kein Weg daran vorbei, die zu verarbeitenden Daten in den Speicher zu laden. Die Frage ist "nur" wie groß die Happen sind die verarbeitet werden.
Das weiß ich ja. Deswegen lade ich mit einer Schleife immer die Chunks und verarbeite sie. In dem Fall so,Ute ich dann das Häppchen in Zeilen. Und da ich nur so,irrem wenn das Zeilenende „0A“ als Umbruch habe, muss ich eben vor diesem ganzen Vorgang die eventuellen, für mich ungewollten, Zeilenumbrüche durch „0A“ ersetzen. Und das ist eben meine Frage, wie ein solcher Algorithmus auf Basis von TFileStream aussehen kann, wo man z.B. einfach eine modifizierte Kopie der originalen Datei erstellt mit den ersetzten Zeilenumbrüchen.
Ich weiß ja nicht wie Deine Ausgabe der Text-Datei vonstatten geht, erstellt dein Parser einen String pro Zeile?
Genau der Parser arbeitet Zeilenweise. Es ist eben nur doof, wenn er auf eine Zeile eines falsch gesplitteten Strings zurück greift. Und wie gesagt, ich möchte ja erst im zweiten Durchgang splitten, wenn ich weiß, dass alle Ueilenenden der Datei „0A“ sind bzw. durch diese ersetzt wurden.
ungefähr (ungetestet) sowas:
Delphi-Quellcode:
procedure TIrgendeineKlasse.Zeichenaustauschen(input : TMemoryStream; output : TMemoryStream);
Var
  ch : Char;
begin
  input.Position := 0;
  output.Position := 0;
  // Ist überhaupt was in der Datei drin?
  if input.Read(ch, 1) > 0 then begin
    repeat
      case ch of
        // Hier zeichenweise entscheiden, was geschehen soll.
        #10 : begin
                output.Write(ch,1);
              end;
        #13 : begin
                // output.Write(ch,1);
              end;
      else
        // Übrige Zeichen ausgeben.
        output.Write(ch,1);
      end;
    until input.Read(ch, 1) = 0;
    input.Position := 0;
    output.Position := 0;
  end;
end;
Die Schleife geht ja Byteweise vor. Wenn ich jetzt auf #13 treffe, was muss ich dann machen?
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.596 Beiträge
 
Delphi 7 Professional
 
#3

AW: Zeilenumbruch ersetzen Algorithmus

  Alt 11. Mär 2018, 14:28
Im Case kannst Du jeweils das zuletzt gelesene Zeichen abfragen.

Findest Du nun eine #13 und willst sie nicht ausgeben, so wird sie halt nicht geschrieben.

Oder anders ausgedrückt:

In der Else werden alle die Zeichen ausgegeben, die nicht vorher im Case irgendwie verarbeitet wurden.

Soll also z. B. die #13 nie ausgegeben werden, sähe der Quelltext so aus:
Delphi-Quellcode:
procedure TIrgendeineKlasse.Zeichenaustauschen(input : TMemoryStream; output : TMemoryStream);
Var
  ch : Char;
begin
  input.Position := 0;
  output.Position := 0;
  // Ist überhaupt was in der Datei drin?
  if input.Read(ch, 1) > 0 then begin
    repeat
      case ch of
        #13 : ; // Das Zeichen wird schlicht und einfach ignoriert.
      else
        output.Write(ch,1); // Übrige Zeichen ausgeben.
      end;
    until input.Read(ch, 1) = 0;
    input.Position := 0;
    output.Position := 0;
  end;
end;
Oder die Antwort auf deine Frage Wenn ich jetzt auf #13 treffe, was muss ich dann machen? ist: Nichts.

Alle anderen Zeichen werden ausgegeben.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.756 Beiträge
 
Delphi 12 Athens
 
#4

AW: Zeilenumbruch ersetzen Algorithmus

  Alt 11. Mär 2018, 15:03
Oder die Antwort auf deine Frage Wenn ich jetzt auf #13 treffe, was muss ich dann machen? ist: Nichts.
Und was ist, wenn auf das #13 kein #10 folgt?

Zitat:
Es gibt aber auch die Kombination „0D0A“ und „0D“.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.596 Beiträge
 
Delphi 7 Professional
 
#5

AW: Zeilenumbruch ersetzen Algorithmus

  Alt 11. Mär 2018, 15:33
Und was ist, wenn auf das #13 kein #10 folgt?
Dann muss man die Logik im Case an die eigenen Bedürfnisse anpassen.
Delphi-Quellcode:
procedure TIrgendeineKlasse.Zeichenaustauschen(input : TMemoryStream; output : TMemoryStream);
Var
  ch1 : Char;
  ch2 : Char;
begin
  input.Position := 0;
  output.Position := 0;
  // Ist überhaupt was in der Datei drin?
  if input.Read(ch1, 1) > 0 then begin
    repeat
      case ch of
        #13 : begin // Das nächste Zeichen lesen.
                if input.Read(ch2, 1) <> 0 then begin
                  case ch2 of
                    #10 : ; // ignorieren, wird als nächstes Zeichen gelesen.
                  else
                    begin // wenn wir 'ne #13 erhalten und keine #10 folgt, geben wir 'ne #10 aus.
                      ch2 := #10;
                      output.Write(ch2,1);
                    end;
                  end;
                  // und wieder ein Zeichen zurück.
                  input.Position := input.Position - 1;
                end;
              end;
      else
        output.Write(ch1,1); // Übrige Zeichen ausgeben.
      end;
    until input.Read(ch1, 1) = 0;
    input.Position := 0;
    output.Position := 0;
  end;
end;
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.756 Beiträge
 
Delphi 12 Athens
 
#6

AW: Zeilenumbruch ersetzen Algorithmus

  Alt 11. Mär 2018, 16:20
Delphi-Quellcode:
procedure TIrgendeineKlasse.Zeichenaustauschen(input : TMemoryStream; output : TMemoryStream);
Var
  ch1 : Char;
  ch2 : Char;
begin
  input.Position := 0;
  output.Position := 0;
  // Ist überhaupt was in der Datei drin?
  if input.Read(ch1, 1) > 0 then begin
    repeat
      case ch of
        #13 : begin // Das nächste Zeichen lesen.
                if input.Read(ch2, 1) <> 0 then begin
                  case ch2 of
                    #10 : ; // ignorieren, wird als nächstes Zeichen gelesen.
                  else
                    begin // wenn wir 'ne #13 erhalten und keine #10 folgt, geben wir 'ne #10 aus.
                      ch2 := #10;
                      output.Write(ch2,1);
                    end;
                  end;
                  // und wieder ein Zeichen zurück.
                  input.Position := input.Position - 1;
                end;
              end;
      else
        output.Write(ch1,1); // Übrige Zeichen ausgeben.
      end;
    until input.Read(ch1, 1) = 0;
    input.Position := 0;
    output.Position := 0;
  end;
end;
Der Code hat immer noch ein paar Probleme (unter der Annahme, daß hier mindestens das im Profil angegeben Delphi 2010 zum Einsatz kommt):

1. Auf der einen Seite werden ch1 und ch2 als Char (2 Bytes) deklariert, mit Read wird aber nur jeweils 1 Byte eingelesen. Damit ist das höhere Byte undefiniert und das case könnte daneben gehen. Da wir ja hier alle wohl von eine ANSI- bzw. UTF8-codierten Textdatei ausgehen, würde ich direkt mit Byte (oder AnsiChar) arbeiten.

2. Der Code unterschlägt das letzte Zeilenende, wenn dieses durch ein einzelnes #13 gekennzeichnet ist.

3. Eine Unicode-Datei könnte man damit nicht direkt umsetzen, da der komplette Bereich 0D00-0DFF sowie alle Zeichen mit 0D im Low-Byte falsch behandelt werden. Ich vermute aber, daß dies hier nicht relevant sein wird (siehe 1).
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: Zeilenumbruch ersetzen Algorithmus

  Alt 11. Mär 2018, 16:36
Noch eine Idee, aber ich weiß nicht ob alle Delphi Versionen das mitmachen,
deine Text-Datei einfach per ReadLn() einlesen, da ist automatisch schluss, egal wie die zeichenfolge ist.
also im BeginUpdate modus per schleife alles in deine memobox laden, dann passts.
Bei bedarf memo-box inhalt zurück auf platte schreiben, dann ist format einheitlich egal wie's vorher war.
Gruß vom KodeZwerg
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.596 Beiträge
 
Delphi 7 Professional
 
#8

AW: Zeilenumbruch ersetzen Algorithmus

  Alt 11. Mär 2018, 16:40
@Uwe Raabe

Es geht mir nicht um einen allumfassenden, immer und überall, jederzeit in allen Umgebungen und mit allen Delphiversionen funktionierenden Code, sondern um einen Vorschlag zur Problemlösung.

Selbstdenken und anpassen ist also durch erlaubt, erwünscht und im Rahmen des Möglichen.

Wenn Char nicht ein Byte ist, dann muss man das halt anpassen.

Statt der 1 könnte man halt eben auch SizeOf(ch1) nehmen oder SizeOf(EbenDerTypDenManBenutzt).
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:44 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