Laden...

"String" im sehr großem Byte-Stream replacen

Erstellt von Diablo vor 10 Jahren Letzter Beitrag vor 10 Jahren 1.552 Views
D
Diablo Themenstarter:in
47 Beiträge seit 2011
vor 10 Jahren
"String" im sehr großem Byte-Stream replacen

Hallo,

ich würde gerne in einem Stream einen String finden und replacen. Allerdings nicht die altbewerte Methode, den ganzen Text zu buffern, sondern am besten byte für byte. Die eingehende Datei kann nämlich mehrere GB groß sein.

Ich habe in An EncodingTranscoder Custom Pipeline Component zwar eine Lösung zum Encoden von Text, aber weiß nicht so recht ob man das auch auf mein Anliegen anwenden kann, da ich ja einen String habe, keinen System.Text.Decode / Encode.

Vielleicht kann mir ja jemand einen Tipp geben.

3.825 Beiträge seit 2006
vor 10 Jahren

Schau Dir mal StreamInsight von Microsoft an :

.NET Usergroup Frankfurt 18. Juli : StreamInsight - Complex Event Processing by Microsoft

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

D
Diablo Themenstarter:in
47 Beiträge seit 2011
vor 10 Jahren

Hey, danke für den Tipp, aber gibt es auch eine Möglichkeit ohne noch extra Bibliotheken o.ä. installieren zu müssen?

Z.B.: Über die Stream.Read() - Funktion?

F
115 Beiträge seit 2012
vor 10 Jahren

Hi,

ich denke, Du wirst den Stream so lange unstersuchen müssen bis Du sicher bist, ob der zu ersetzende String enthalten oder nicht enthalten ist.

Pseudocodemäßig sowas in der Richtung vielleicht?

i=-1
repeat
  readStream(inByte)
  i++
until(inByte != suchString[i] || i=suchString.length())
case
  when i=0 //erstes Zeichen passt schon nicht -> also direkt das Zeichen
    return(inByte)
  when i=suchString.length() //alle passen, also den ersetzString
    return(ersetzString())
  else // suchsString passt bis zur Position i, also bis dahin zurück
    return(suchString().substr(1,i)+inByte)
end

Gruß
f_igy

S
145 Beiträge seit 2013
vor 10 Jahren

öh einfach System.IO.StreamReader ausm Framework zum lesen
und zum schreiben/ersetzten wäre ja dann StreamWriter, theoretisch müsst ja nur dann die Position zum setzten/weiterlesen entsprechend gesetzt werden

D
Diablo Themenstarter:in
47 Beiträge seit 2011
vor 10 Jahren

Hallo,

habe jetzt mit folgendem Code die Position herausfinden können:

 public long FindPosition(Stream stream, byte[] byteSequence)
        {
            if (byteSequence.Length > stream.Length)
                return -1;

            byte[] buffer = new byte[byteSequence.Length];

            using (BufferedStream bufStream = new BufferedStream(stream, byteSequence.Length))
            {
                int i;
                while ((i = bufStream.Read(buffer, 0, byteSequence.Length)) == byteSequence.Length)
                {
                    if (byteSequence.SequenceEqual(buffer))
                        return bufStream.Position - byteSequence.Length;
                    else
                        bufStream.Position -= byteSequence.Length - PadLeftSequence(buffer, byteSequence);
                }
            }

            return -1;
        }

        private int PadLeftSequence(byte[] bytes, byte[] seqBytes)
        {
            int i = 1;
            while (i < bytes.Length)
            {
                int n = bytes.Length - i;
                byte[] aux1 = new byte[n];
                byte[] aux2 = new byte[n];
                Array.Copy(bytes, i, aux1, 0, n);
                Array.Copy(seqBytes, aux2, n);
                if (aux1.SequenceEqual(aux2))
                    return i;
                i++;
            }
            return i;
        }

Gibt es jetzt so eine Art Virtuellen Stream, mit dem man dann neue Daten in den Hauptstream einfügen kann?
Problem ist ja nämlich folgendes:

Wenn ich ein Wort was ich suche gefunden habe, und mit einem kürzeren oder längeren Wort ersetzen möchte, wie funktioniert das, man kann ja nichts abschneiden oder auffüllen vom Hauptstream, also bräuchte man ja einen zweiten o.ä. um das neue Wort halt zu ersetzen?!

Jemand eine Idee?

F
115 Beiträge seit 2012
vor 10 Jahren

Ähem,

ist das nicht etwas kompliziert? Was spircht denn gegen meinen simplen Vorschlag einfach den laufenden Strom zu durchsuchen?

f_igy

49.485 Beiträge seit 2005
vor 10 Jahren

Hallo Diablo,

du kannst eine eigene Stream-Klasse schreiben, die den Original-Stream als Konstruktor-Parameter bekommt und die dann die modifizierten Daten nach außen gibt. Im Original-Stream bleiben die Daten dann einfach unverändert.

Deine ursprüngliche Idee mit dem Einfügen oder Löschen des Daten aus dem Original-Stream wird wohl nicht funktionieren.

herbivore

D
Diablo Themenstarter:in
47 Beiträge seit 2011
vor 10 Jahren

du kannst eine eigene Stream-Klasse schreiben [...]

Hey, das hatte ich vor, allerdings weiß ich noch nicht genau wie man das am Besten realisiert. Sprich die Daten in den (kopierten?) Stream einfügen und ersetzen.

Kann man das über bytes[].AddRange() bzw. bytes[].RemoveRange()?

49.485 Beiträge seit 2005
vor 10 Jahren

Hallo Diablo,

aus meiner Sicht brauchst du bis auf einen Minibuffer, der (ungefähr) so groß ist, wie der zu suchende "String" in der eigenen Stream-Klasse gar keinen Buffer, so dass du auch nichts einfügen oder ersetzen musst. Die Daten sind ja schon in dem originalen Steam gepuffert. Wenn du Daten brauchst, holst du dir die einfach aus dem originalen Stream. Du musst dir höchsten merken, um wieviel Byte die Position in dein Stream von dem originalen Stream abweicht. Ich gehe mal davon aus, dass du in deinem Stream CanSeek auf false setzt.

herbivore