CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Stream to unsigned char (array)

Stream to unsigned char (array)

dział ogólny

Stream to unsigned char (array)

Nowy postprzez Slynx » niedziela, 23 stycznia 2011, 18:06

Witam,
szukam jakiegoś dobrego sposobu na konwersję Stream do tablicy unsigned Char i jakoś nie mam pomysłów, tj. wpadłem na jeden:

KOD cpp:     UKRYJ  
 System::IO::StreamReader ^ sr = gcnew System::IO::StreamReader(data);
 unsigned char str[bufsize];
 str = (unsigned char)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi().ToPointer();


ale dodatkowo wymagałoby robienia tego bajt po bajcie. Poza tym, to droga na około. Zależy mi na szybkości działania. Oczywiście Stream należy do .Net a unsigned char z stdlib (żadnego wchar_t i podobnych tablic cli).
Z pewnością można to zapisać w 1-2 linijkach. Ktoś może coś doradzić ? (Zakładamy że strumień ma dokładnie taką samą wielkość co tablica)
Wcześniej mam podobnie, z tą różnicą, że z .NET Stringa do char (format do funkcji fopen)

KOD cpp:     UKRYJ  
 char aa = (char)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(file_path).ToPointer();


Nie wiem jak tego typu funkcję odbijają się na szybkości działania. Przy jednorazowym wywołaniu to oczywiście nie ma znaczenia, ale jest to wstęp do funkcji liczącej CRC32 dla kilkuset małych plików lub strumieni.
Avatar użytkownika
Slynx
Mądrosław
Mądrosław
 
Posty: 350
Dołączył(a): piątek, 17 grudnia 2010, 21:59
Podziękował : 11
Otrzymał podziękowań: 0
System operacyjny: Windows 7 32
Kompilator: Visual C++ 2005; Visual C++ 2008; Visual C++ 2010; Visual C# 2010;
Gadu Gadu: 0
    Windows 7Firefox

Re: Stream to unsigned char (array)

Nowy postprzez Cyfrowy Baron » niedziela, 23 stycznia 2011, 19:22

Strumienia nie da się przekonwertować na łańcuch znaków, chyba chcesz raczej przepisać dane ze strumienia do zmiennej typu char, a nie unsigned char Jeżeli nie oto chodzi to nie rozumiem, jeżeli jednak jest tak jak piszę to możesz przecież skorzystać z funkcji Read:

KOD cpp:     UKRYJ  
function Read(const Buffer: TCharArray;
                Index: Integer;
                Count: Integer): Integer; overload; override;


W pomocy do C++Builder 2010 jest:

KOD text:     UKRYJ  
Read character data, advancing pointer.

Read reads data from the input source and advances the data pointer to the source, unlike Peek.
This method is functionally identical to the Microsoft .NET method StreamReader.Read.


I jeszcze przykład użycia TStreamReader i TStreamWriter dla C++Builder 2010:

KOD cpp:     UKRYJ  
void __fastcall TMainForm::btStoreClick(TObject *Sender)
{
        TStreamWriter* writer;
        String line;
 
        /* Create a file stream and open a text writer for it. */
        writer = new TStreamWriter(
                new TFileStream("local_file.txt", fmCreate),
                TEncoding::UTF8, 1024
        );
 
        /* Do not flush after each write, youu will do it manually. */
        writer->AutoFlush = false;
 
        /* Set the custom newline to be Unix-compatible. */
        writer->NewLine = '\a';
 
        /* Start storing all the lines in the memo. */
        for (int i = 0; i < mmText->Lines->Count; i++)
        {
                /* Obtain the line. */
                line = mmText->Lines->Strings[i];
 
                /* Write char-by-char. */
                for (int j = 1; j <= line.Length(); j++)
                        writer->Write(line[j]);
 
                /* Add a line terminator. */
                writer->WriteLine();
        }
 
        /* Flush the contents of the writer to the stream. */
        writer->Flush();
 
        /* Close the writer. */
        writer->Close();
 
        /* Obtain the size of the data. */
        int64_t size = writer->BaseStream->Size;
 
        /* Free the writer and the underlying stream. */
        delete writer->BaseStream;
        delete writer;
 
        MessageDlg(Format("%d bytes written to the stream using the %s encoding!",
                ARRAYOFCONST((size, writer->Encoding->ClassName()))),
                mtInformation, TMsgDlgButtons() << mbOK, 0
        );
}
 
void __fastcall TMainForm::btLoadClick(TObject *Sender)
{
        TStreamReader* reader;
        String line;
 
        /* Create a file stream and open a text writer for it. */
        reader = new TStreamReader(
                new TFileStream("local_file.txt", fmOpenRead),
                TEncoding::UTF8
        );
 
        mmText->Clear();
 
        /* Check for the end of the stream and exit if necessary. */
        if (reader->EndOfStream)
        {
                MessageDlg("Nothing to read!", mtInformation, TMsgDlgButtons() << mbOK, 0);
 
                delete reader->BaseStream;
                delete reader;
        }
 
        /* Peek at each iteration to see whether there are characters
           to read from the reader. Peek is identical in its effect with
           EndOfStream property.
        */

        line = "";
 
        while (reader->Peek() >= 0)
        {
                /* Read the next character. */
                wchar_t ch = (wchar_t)reader->Read();
 
                /* Check for line termination (Unix-style). */
                if (ch == '\a')
                {
                        mmText->Lines->Add(line);
                        line = "";
                }
                else
                        line = line + ch;
        }
 
        /* Obtain the size of the data. */
        int64_t size = reader->BaseStream->Size;
 
        /* Free the reader and underlying stream. */
        reader->Close();
        delete reader->BaseStream;
        delete reader;
 
        MessageDlg(Format("%d bytes read from the stream using the %s encoding!",
                ARRAYOFCONST((size, reader->CurrentEncoding->ClassName()))),
                mtInformation, TMsgDlgButtons() << mbOK, 0
        );
}
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Stream to unsigned char (array)

Nowy postprzez Slynx » niedziela, 23 stycznia 2011, 22:41

To co podałeś i tak sprowadza się do użycia StreamReadera, więc pozostanę przy swojej wersji.
Trzeba po prostu przepisać (przekonwertować = przepisać; źle się wtedy wyraziłem) do tablicy uChar. Jak widzę, drogi na skróty specjalnie nie ma. Może się okazać, że szybciej będzie zapisać ten strumień do pliku tmp, a potem od razy podać ten plik do funkcji fopen. Jeszcze zobaczę, bo było tam kilka ciekawych funkcji. Wydajnie nie będzie, ale i tak lepiej niż przepisywanie bajt po bajcie StreamReaderem ; )
Avatar użytkownika
Slynx
Mądrosław
Mądrosław
 
Posty: 350
Dołączył(a): piątek, 17 grudnia 2010, 21:59
Podziękował : 11
Otrzymał podziękowań: 0
System operacyjny: Windows 7 32
Kompilator: Visual C++ 2005; Visual C++ 2008; Visual C++ 2010; Visual C# 2010;
Gadu Gadu: 0
    Windows 7Firefox

Re: Stream to unsigned char (array)

Nowy postprzez Cyfrowy Baron » poniedziałek, 24 stycznia 2011, 09:49

Nie wiem o co Tobie już chodzi. W kwestii klasy TStreamReader czy też TStream wystarczy użyć funkcji Read by zapisać to w zmiennej typu char. Nie napisałeś o co chodzi, więc to tyle...



Może się okazać, że szybciej będzie zapisać ten strumień do pliku tmp, a potem od razy podać ten plik do funkcji fopen


Na pewno nie będzie szybciej. Zapisanie do pliku a potem odczytanie z pliku. Czy operacje mają odbywać się w pamięci? Jeżeli tak to najlepiej skorzystać z klasy TMemoryStream.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Stream to unsigned char (array)

Nowy postprzez Slynx » poniedziałek, 24 stycznia 2011, 15:15

Ty, nie, ale ja już wiem o co Ci chodzi. Miałem trochę złe pojęcie o Stream. Sprawdziłem co i jak i chyba innego rozsądnego sposobu nie ma.
Avatar użytkownika
Slynx
Mądrosław
Mądrosław
 
Posty: 350
Dołączył(a): piątek, 17 grudnia 2010, 21:59
Podziękował : 11
Otrzymał podziękowań: 0
System operacyjny: Windows 7 32
Kompilator: Visual C++ 2005; Visual C++ 2008; Visual C++ 2010; Visual C# 2010;
Gadu Gadu: 0
    Windows 7Firefox

Re: Stream to unsigned char (array)

Nowy postprzez Slynx » środa, 29 czerwca 2011, 16:09

Znalazłem krótszą metodę rozwiązania tego problemu (wklejam dla ewentualnych "poszukiwaczy");

KOD cpp:     UKRYJ  
System::IO::BinaryReader^ br = gcnew BinaryReader(local);
array<unsigned char>^ buffer = br->ReadBytes(local->Length);
br->Close();


Przy założeniu że Stream ma wielkość, którą można pobrać za pomocą właściwości Length, w przeciwnym wypadku robimy tradycyjnie, czyli

KOD cpp:     UKRYJ  
array<unsigned char>^ buffer = gcnew array<unsigned char>(8*1024);
System::IO::MemoryStream^ ms = gcnew MemoryStream();
int read;
while((read = local->Read(buffer, 0, buffer->Length)) > 0)
{
ms->Write(buffer, 0, read);
}
// ms->ToArray();


Ale mnie dotyczył tylko pierwszy kod...
Avatar użytkownika
Slynx
Mądrosław
Mądrosław
 
Posty: 350
Dołączył(a): piątek, 17 grudnia 2010, 21:59
Podziękował : 11
Otrzymał podziękowań: 0
System operacyjny: Windows 7 32
Kompilator: Visual C++ 2005; Visual C++ 2008; Visual C++ 2010; Visual C# 2010;
Gadu Gadu: 0
    Windows 7Chrome


  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 6 gości