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.
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
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?
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
ö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
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?
Ähem,
ist das nicht etwas kompliziert? Was spircht denn gegen meinen simplen Vorschlag einfach den laufenden Strom zu durchsuchen?
f_igy
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
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()?
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