TMemoryStream "umkehren"



  • Wie kann man den Inhalt eines MemoryStreams in einen anderen umgekehrt reinschreiben? (MemoryStream2 1.Zeichen = MemoryStream1 letztes Zeichen usw.)
    Ich habe schon alles mögliche versucht, aber Ich komme mit dem Read und Write nicht zurecht.



  • erstell einen 2. memorystream und geh mit seek vom letzten zum ersten byte

    so in etwa:

    MS: memorystream mit daten
    MS2: memorystream mit umgekehrten daten von MS

    char a[1];
    MS->Seek(0, soFromBeginning); // an anfang setzen
    MS2->Seek(0, soFromBeginning); // an anfang setzen
    
    for (int i = MS->Size - 1; i >= 0; i--)
    {
    
    MS->Seek(i, soFromBeginning);
    
    MS->ReadBuffer(a, 1)
    MS2->WriteBuffer(a[1], 1);
    
    }
    

    Sollte funktionieren

    Tim



  • Kann man dafür nicht auch Memory vergewaltigen? Vielleich so:

    char *buffer = (char*)MS->Memory;
    MS2->Position = 0; // an anfang setzen
    for (int i = MS->Size - 1; i >= 0; --i)
    {
        MS2->WriteBuffer(buffer[i], 1);
    }
    

    Das hier ist aber nicht getestet.



  • Braunstein schrieb:

    char *buffer = (char*)MS->Memory;
    

    Das dürfte über eventuelle Null-Bytes im Stream stolpern, oder?

    Ansonsten: man muss natürlich den zweiten Stream nicht notwendigerweise genauso gross machen wie den ersten, was gerade bei TMemoryStream je nach Grösse erhebliche Einsparungen beim Speicherbedarf des Programmes ermöglicht.
    Z.B. könnte man eine Hälfte des Stream in einen zweiten kopieren, dann die erste Hälfte des Originals rückwärts an das Ende des Originals kopieren und anschliessend das zwischengespeicherte Stück rückwärts an den Anfang. Oder man nimmt nur ein Drittel oder ein Viertel, etc. Bis man schliesslich bei diesem Extrem ankommt:

    // Test-Stream erstellen und füllen
      TMemoryStream *mem = new TMemoryStream();
      int len = 11;
      mem->Write("1234567890a", len);
    
      // Stream umkehren
      char front[2], back[2];
      for (int i = 0; i < len/2; i++)
      {
        mem->Position = i;
        mem->Read(front, 1);// ein Zeichen vom Anfang lesen
        mem->Position = len - i - 1;
        mem->Read(back, 1); // ein Zeichen vom Ende lesen
    
        mem->Position = i;
        mem->Write(back, 1);  // Zeichen vom Ende an den Anfang schreiben
        mem->Position = len - i - 1;
        mem->Write(front, 1); // Zeichen vom Anfang an das Ende schreiben
      }
    
      // Testausgabe und aufräumen
      char ch[12];
      mem->Position = 0;
      mem->Read(ch, len);
      delete mem;
    
      Caption = ch;
    

    Aufgrund des heftigen Seekens ist das wahrscheinlich etwas langsamer (müsste man mal anhand einer richtig grossen Datei vegleichen), insbesondere bei Verwendung von TFileStream. Wobei man dort aber kaum auf die Streamgrösse achten muss und dehalb meist ruhig auch eine 1:1 Kopie erzeugen kann.
    Je nach Anwendung muss man halt den richtigen Kompromiss zwischen Geschwindigkeit und Speicherbedarf finden.



  • Jansen schrieb:

    Braunstein schrieb:

    char *buffer = (char*)MS->Memory;
    

    Das dürfte über eventuelle Null-Bytes im Stream stolpern, oder?

    Da er keine String-Funktionen anwendet doch nicht wirklich oder?

    -junix



  • In dem Fall hat das char* nichts mit Strings zu tun. Man kann einen char* ja auch binär interpretieren. In dem Fall stört auch das 0-Byte nicht. Ich habe hier lediglich char verwendet da er genau 1 Byte gross ist.



  • Hi,

    Braunstein schrieb:

    ...
    for (int i = MS->Size - 1; i >= 0; --i)
    {
        MS2->WriteBuffer(buffer[i], 1);
    } 
    Das hier ist aber nicht getestet.
    

    kleine Korrektur:

    ...
    for (int i = MS->Size - 1; i >= 0; --i)
    {
        MS2->WriteBuffer(&buffer[i], 1);
    }
    

    Ansonsten wird der Wert buffer[i] als Adresse interpretiert und zeigt dann natürlich irgendwo ins Nirvana.



  • Danke für die vielen Antworten, aber der C++Builder bringt bei der Zeile
    "mem2->WriteBuffer(buffer[i], 1);" folgende Fehler:
    1. Cannot convert 'int' to 'const void *'.
    2. Type mismatch in parameter 'Buffer' in call to '_fastcall Classes::TStream::WriteBuffer(const void *,long)'.



  • dschensky schrieb:

    Ansonsten wird der Wert buffer[i] als Adresse interpretiert und zeigt dann natürlich irgendwo ins Nirvana.

    ... ähm ja, abgesehen davon, daß es sich sowieso nicht compilieren läßt:

    dbz165 schrieb:

    1. Cannot convert 'int' to 'const void *'.

    [cpp]MS2->WriteBuffer(**&**buffer[i], 1);[/cpp]



  • Danke, jetzt gehts.
    Ich habe noch eine letzte Frage:
    Ich möchte den MemoryStream jetzt in zweier Zeichen umkehren. Das funktioniert auch schon. Nur wenn die Länge des MemoryStreams ungerade ist funktioniert es nicht richtig. Wie könnte Ich das Problem beheben?


Anmelden zum Antworten