binary



  • Hiho,
    also ich werkel hier jetzt schon ne zeit lang rum und bekomme es nicht auf den schirm.
    Ich möchte einfach eine Datei einlesen und es binär bekommen.

    z.B möchte ich ein JPG öffnen und die zusammensetzung des bildes als 1 und 0 bekommen......

    kann mir wer helfen?



  • Ströme und Dateien in C++
    siehe "das zweite Beispiel"



  • du meinst:

    using namespace std;
    fstream FileBin("d:\\cdtemp\\streams\\test.dat", ios::in|ios::out|ios::binary);
    if (FileBin.is_open())
    {
        // 1. Dateigröße bestimmen.
        FileBin.seekg(0, ios::end);
        unsigned long FileSize = streamoff(FileBin.tellg());
        FileBin.seekg(0, ios::beg);
    
        // 2. Puffer anlegen und Datei einlesen.
        char* pBuffer = new char[FileSize];
        FileBin.read(pBuffer, FileSize);
    
        // 3. An Stelle 7 (relativ zum Beginn) zwei Bytes ersetzen.
        FileBin.seekp(7, ios::beg);
        FileBin.write(pBuffer+FileSize-2, 2);
    
        // Nachher wieder aufräumen.
        delete [] pBuffer;
    }
    

    ??



  • Benutze ausserdem ein std::bitset

    [ Dieser Beitrag wurde am 08.04.2003 um 13:47 Uhr von MaSTaH editiert. ]



  • *TILT*

    sorry, hab davon noch nicht den schnall. kannste mir helfen??



  • Hallo,
    um es nocheinaml (zu siebenhunderttausendsten mal) zu sagen. Der Openmode binray
    hat *absolut überhaupt nichts* mit der binär-Darstellung von Zahlen zu tun. Anders ausgedrückt. binary hat *absolut überhaupt nichts* mit 0en und 1en zu tun.

    Also "binary stream" != Stream von 0en und 1en.

    Das ganze hat ausschließlich etwas mit durchgeführten Konvertierungen zu tun.

    Ich zitiere mal James Kanze:

    I think you have misunderstood the meaning of "binary stream" in this
    context. File oriented streams do conversions at three different
    levels:

    - At the lowest level, the external representation of end of line
    and end of file is converted into the internal one.

    - After than, the data is mapped in accordance with the locale
    associated with the stream.

    - Finally, the << and >> are used for textual formatting.

    In each case, there is a separate control of the mechanism:

    - At the lowest level, the ios::binary flag means that the stream
    will not be treated as text at the operating system interface
    level. Typically, this will mean no end of line mapping -- in
    cases where text files have a special end of file marker (CP/M,
    for example), this will also be ignored.

    - At the second level, you can imbue the locale you want. The "C"
    locale will guarantee a one to one translation.

    - At the formatting level, if you don't want formatting, don't use
    the formatting functions; use read and write instead.

    In actual practice, saying that you don't want formatting is simply
    saying that you have data that has been or will be formatted
    elsewhere. You never want to do IO on unformatted data; when you
    speak of binary, you are generally refering to a non-textual format.
    In all but the simplest cases, the correct solution is to create your
    own iostream types which do the correct formating.

    Der Punkt hier ist: Durch den Openmode binary werden Konvertierungen des EOL-Zeichen unterdrückt. Eine Datei wird also nicht als *formatierte* Textdatei behandelt sondern als eine Datei die ein dem Benutzer bekanntes binär Format besitzt. Solche Datei werden dann *nicht* mit den Funktionen für die formatierte Ein-/Ausgabe bearbeitet sondern mit den low-level Funktionen read/write. Die korrekte Formatierung muss dann an anderer Stelle geschehen.

    Wer alles oben geschriebene vergessen will, sollte wenigstens eins behalten:
    Wer 0en und 1en als Ausgabe haben will, muss selbst dafür sorgen, dass er aus Zeichen 0en und 1en macht. C++ arbeitet auf *Zeichenebene* (1 Byte = 1 char) nicht auf Bitebene. Völlig egal ob openmode binary gesetzt ist oder nicht.

    Die Lösung deines Problems besteht also darin,
    jedes eingelesene Zeichen in seine binäre-Darstellung umzuwandeln. Wie du das machst, findest du in den FAQs erklärt.
    Dezimal in Binär



  • klare Ansage, danke Hume...
    liegts mit deiner Vermutung wie ich es benötige richtig 🙂



  • Hallo,
    wenn man wollte könnte man sich natürlich einen Wrapper basteln, der automatisch eine Konvertierung ins binär-System durchführt. Ein eigener streambuf wäre natürlich sehr bequem, mir fällt spontan aber nicht ein, wie man die Aufgabe mit einem solchen lösen könnte. Auf streambuf-Ebene gibt es nur noch Zeichen, es wird also schwer dort Zahlen zu erkennen.

    Bleibt erstmal nur ein StreamWrapper.
    Hier mal ein fürchterlich naiver und ungetesteter Ansatz:

    string decimalToBinary(unsigned long value, 
                        unsigned binDigits = numeric_limits<unsigned long>::digits,
                        bool trimLeft = true)
    {
    
        bool leadingZero = true;
        unsigned digit = 1 << (binDigits-1);
        string ret;
        ret.reserve(binDigits);
        do
        {
            if (value & digit)
            {
                ret += '1';
                leadingZero = false;
            }
            else if (!trimLeft || !leadingZero)
            {
                ret += '0';
            }
            digit /= 2;
        } while (digit != 0);
        return ret;
    }
    
    class BinWrapper
    {
    public:
        explicit BinWrapper(ostream& os, bool trimLeft = false) 
            : realStream_(os)
            , trimLeft_(trimLeft)
        {}
        ostream& getStream() const
        {
            return realStream_;
        }
    
        friend BinWrapper& operator << (BinWrapper& os, const std::string& s);
        BinWrapper& operator<<(ios& (*pf)(ios&))
        {
            realStream_ << pf;
            return *this;
        }
        BinWrapper& operator<<(ostream& (*pf)(ostream&))
        {
            realStream_ << pf;
            return *this;
        }
        BinWrapper& operator<<(ios_base& (*pf)(ios_base&))
        {
            realStream_ << pf;
            return *this;
        }
        BinWrapper& operator<<(streambuf *sb)
        {
            realStream_ << sb;
            return *this;
        }
    
        BinWrapper& operator<<(const char* s)
        {
            return *this << std::string(s);
        }
    
        BinWrapper& operator<<(unsigned long n)
        {
            return writeNumber(n, numeric_limits<unsigned long>::digits);
        }
        BinWrapper& operator<<(char c)
        {
            return writeNumber(c, numeric_limits<char>::digits);
        }
        BinWrapper& operator<<(bool n)
        {
            return writeNumber(n, numeric_limits<bool>::digits);
        }
        BinWrapper& operator<<(short n)
        {
            return writeNumber(n, numeric_limits<short>::digits);
        }
        BinWrapper& operator<<(unsigned short n)
        {
            return writeNumber(n, numeric_limits<unsigned short>::digits);
        }
        BinWrapper& operator<<(int n)
        {
            return writeNumber(n, numeric_limits<int>::digits);
        }
        BinWrapper& operator<<(unsigned int n)
        {
            return writeNumber(n, numeric_limits<unsigned int>::digits);
        }
        BinWrapper& operator<<(long n)
        {
            return writeNumber(n, numeric_limits<long>::digits);
        }
    
        BinWrapper& operator<<(float n)
        {
            return writeFloatNumber(n, numeric_limits<float>::digits);
        }
        BinWrapper& operator<<(double n)
        {
            return writeFloatNumber(n, numeric_limits<double>::digits);
        }
        BinWrapper& operator<<(long double n)
        {
            return writeFloatNumber(n, numeric_limits<long double>::digits);
        }
        BinWrapper& operator<<(void * n)
        {
            writeNumber((unsigned long) n, numeric_limits<unsigned long>::digits);
        }
    
        template <class T>
        BinWrapper& operator<<(const T& t)
        {
            realStream_ << t;
            return *this;
        }
    private:
        BinWrapper& writeNumber(unsigned long n, unsigned binDigits)
        {
            std::string binStr = decimalToBinary(n, binDigits, trimLeft_);
            realStream_ << binStr;
            return *this;
        }
        BinWrapper& writeFloatNumber(unsigned long n, unsigned binDigits)
        {
            throw "not implemented";
            return *this;
        }
        ostream& realStream_;
        bool trimLeft_;
    };
    
    BinWrapper& operator << (BinWrapper& os, const std::string& s)
    {
        for (unsigned i = 0 ; i < s.length() ; ++i)
        {
            std::string binStr = decimalToBinary(s[i], numeric_limits<char>::digits,
                                                os.trimLeft_);
            os.realStream_ << binStr;
        }
        return os;
    }
    int main()
    {
        BinWrapper binOut(cout);
        binOut << "Hallo Welt" << 123 << endl;
    }
    

    Für Floating-Point-Zahlen muss man sich mal das entsprechende IEEE-Format anschauen. Ich kannte auch mal den Algo zur Umwandlung. Habe ich im Moment aber vergessen und keine Lust nachzusehen 🙂

    Ansonsten müsste man das natürlich etwas ordentlicher machen. So mit beliebiger Feldbreite usw.


Anmelden zum Antworten