Probleme mit ifstream::read



  • Hallo!

    Eines vorweg, der Source unten habe ich nur reinkopiert falls andere so etwas mal suchen und brauchen
    Ich schreibe gerade eine MFC-Klasse um, welche Methoden anbietet um Dateien in Base64 zu codieren / decodieren. Die Benutzung ist denkbar einfach:

    **
    Base64 t;
    cout<<t.Encode("C:\\base64.txt", "c:\\granit.bmp")<<endl;
    cout<<t.Decode("C:\\graneitneu.bmp", "c:\\base64.txt")<<endl;
    **

    Mit nicht binären Dateien klappt auch alles, nur bei binären werden einige Zeichen nicht richtig intepretiert und ich weiß auch wo der Fehler liegt, nur ich weiß nicht wie ich ihn umgehen soll:

    bool Base64::Encode(const char* outFilePath, const char* inFilePath) 
    {
    	ofstream outFile(outFilePath, ios::app);
    	ifstream inFile(inFilePath, ios::in | ios::binary);
    
    [...]  // Code
    
    char src[57];   // Muss eigentlich BYTE (unsigned char) src[57] sein
    	char dst[76+1];
    	int Count=Len/57;
    
    	for(int i=0; i<Count; i++)
    	{
    		inFile.read(src, 57);  // read verkraftet aber kein uchar...
    		Encode(dst,src,57);
    		outFile.write(dst,76);
    		outFile.write("\r\n",2);
    	}
    
    [...]
    

    Hat jemand eine Lösungsidee? Ich weiß gerade nicht wie ich das ändern sollte, den ganzen Rest konnte ich problemlos von MFC nach standard C++ konvertieren, falls es jemand braucht hier der Code (wurde ja schon öfter nachgefragt, bis auf die oben genannte Stelle läuft es):

    base64.h

    #ifndef BASE64_H
    #define BASE64_H
    
    /*
    Usage:
      CBase64::Encode("C:\\T.b64"   ,"C:\\T.bmp");
      CBase64::Decode("C:\\TB64.bmp","C:\\T.b64");
    */
    typedef unsigned char BYTE;
    typedef unsigned long DWORD;
    
    #include <string>
    #include <fstream>
    using namespace std;
    
    class Base64
    {
    	public:
    		bool Encode(const char* outFilePath, const char* inFilePath); 
    		void Encode(char* Result, const char* src, int Len);
    
    		bool Decode(const char* outFilePath, const char* inFilePath);
    		char Decode(char* Result, const char* src); 
    };
    
    #endif
    

    base.cpp

    #include "base64.h"
    
    //-----------------------------------------------------------------------------------------//
    
    bool Base64::Encode(const char* outFilePath, const char* inFilePath) 
    {
    	ofstream outFile(outFilePath, ios::app);
    	ifstream inFile(inFilePath, ios::in | ios::binary);
    
    	if(!outFile || !inFile)
    		return(false);
    
    	inFile.seekg(0, ios::end);
        unsigned long Len = streamoff(inFile.tellg()); 
        inFile.seekg(0, ios::beg); 
    
    	char src[57];   // BYTE src[57];
    	char dst[76+1];
    	int Count=Len/57;
    
    	for(int i=0; i<Count; i++)
    	{
    		inFile.read(src, 57); 
    		Encode(dst,src,57);
    		outFile.write(dst,76);
    		outFile.write("\r\n",2);
    	}
    
    	if(int K=Len%57) 
    	{
    		inFile.read(src,K);
    		Encode(dst,src,K);
    		outFile.write(dst,((K+2)/3)<<2);
    		outFile.write("\r\n",2);
    	}
    
    	return(true);
    }
    
    //-----------------------------------------------------------------------------------------//
    
    void Base64::Encode(char* Result, const char* src, int Len) 
    {
    static const char Bit6ToBase64[65]={"\
    ABCDEFGHIJKLMNOPQRSTUVWXYZ\
    abcdefghijklmnopqrstuvwxyz\
    0123456789+/"};
    
    	register char* dst=Result+3;
    	register DWORD EncodeShifter=0;
    	int div=(Len==57) ? 57/3  : Len/3;
    	int mod=(Len==57) ?  0 : Len%3;
    
    	for(int i=0; i<div; i++) 
    	{
    		EncodeShifter=*src++;
    		EncodeShifter=(EncodeShifter<<8)|*src++;
    		EncodeShifter=(EncodeShifter<<8)|*src++;
    		*dst--=Bit6ToBase64[EncodeShifter & 0x3F]; EncodeShifter>>=6;
    		*dst--=Bit6ToBase64[EncodeShifter & 0x3F]; EncodeShifter>>=6;
    		*dst--=Bit6ToBase64[EncodeShifter & 0x3F]; EncodeShifter>>=6;
    		*dst  =Bit6ToBase64[EncodeShifter & 0x3F];
    		dst+=7;
    	}
    
    	*(dst-3)=0;
    
    	switch(mod) 
    	{
    		case 1: 
    		{
    			EncodeShifter=*src;
    			EncodeShifter<<=4;//111111 112222 222233 333333
    			*(dst+1)=0;       //         ====
    			*dst--='=';
    			*dst--='=';
    			*dst--=Bit6ToBase64[EncodeShifter & 0x3F]; EncodeShifter>>=6;
    			*dst  =Bit6ToBase64[EncodeShifter & 0x3F];
    			break;
    		}
    
    		case 2: 
    		{
    			EncodeShifter=*src++;
    			EncodeShifter=(EncodeShifter<<8)|*src;
    			EncodeShifter<<=2;//111111 112222 222233 333333
    			*(dst+1)=0;       //                  ==
    			*dst--='=';
    			*dst--=Bit6ToBase64[EncodeShifter & 0x3F]; EncodeShifter>>=6;
    			*dst--=Bit6ToBase64[EncodeShifter & 0x3F]; EncodeShifter>>=6;
    			*dst  =Bit6ToBase64[EncodeShifter & 0x3F];
    		} 
    	} 
    }
    
    //-----------------------------------------------------------------------------------------//
    
    bool Base64::Decode(const char* outFilePath, const char* inFilePath)
    {
    	ofstream outFile(outFilePath, ios::out | ios::binary);
    	ifstream inFile(inFilePath);
    
    	if(!outFile || !inFile)
    		return(false);
    
        char Result[57+1];  // byte
    
    	for(string line; getline(inFile, line); )   
    	{
    	  char Len=Decode(Result,line.c_str());
          outFile.write(Result, Len);
        }
        return true;
    }
    
    //-----------------------------------------------------------------------------------------//
    
    char Base64::Decode(char* Result, const char* src) 
    {
        static const BYTE Base64ToBit6[128]={
          -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
          -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
          -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63,
          52,53,54,55,56,57,58,59,60,61,-1,-1,-1, 0,-1,-1,
          -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
          15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,
          -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
          41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1,
        };
        register char* dst=Result+2;
        register DWORD DecodeShifter=0;
        size_t div=strlen(src)>>2; //no mod: the Law says its divisible by 4.
        BYTE B;
        for(size_t i=0; i<div; i++) 
    	{
          if((B=*src++) & 0x80 || B<0) 
    		  return *Result=0; //Bad characters in stream
    
          DecodeShifter=Base64ToBit6[B];
    
          if((B=*src++) & 0x80 || B<0) 
    		  return *Result=0; //Bad characters in stream
    
          DecodeShifter=(DecodeShifter<<6) | Base64ToBit6[B];
    
          if((B=*src++) & 0x80 || B<0) 
    		  return *Result=0; //Bad characters in stream
    
          if(B=='=') 
    	  {//1111 11222222
            *--dst=0; //====
            DecodeShifter>>=4; *--dst=(char)DecodeShifter;
            return dst-Result+1;
    	  }
    
          DecodeShifter=(DecodeShifter<<6) | Base64ToBit6[B];
    
          if((B=*src++) & 0x80 || B<0) 
    		  return *Result=0; //Bad characters in stream
    
          if(B=='=') 
    	  {//11 11112222 22333333
            *dst--=0; //==
            DecodeShifter>>=2; *dst--=(char)DecodeShifter;
            DecodeShifter>>=8; *dst  =(char)DecodeShifter;
            return dst-Result+2;
          }
    
          DecodeShifter=(DecodeShifter<<6) | Base64ToBit6[B];
    
          *dst--=(char)DecodeShifter; DecodeShifter>>=8;
          *dst--=(char)DecodeShifter; DecodeShifter>>=8;
          *dst  =(char)DecodeShifter;
           dst+=5;
        }
        *(dst-=2)=0;
    
        if(dst-Result>127)
    		return *Result=0; //We're not looking at a valid Base64 section!
    
        return dst-Result;
    }
    
    //-----------------------------------------------------------------------------------------//
    


  • So, dass Problem wurde durch Hilfe eines Kollegen gelöst. Hier die korrekten Funktionen im namespace Base64 (die Klasse war überflüssig). Viel Spaß damit wer sie braucht!

    base64.h

    #ifndef BASE64_H
    #define BASE64_H
    
    /*
    Usage:
      CBase64::Encode("C:\\T.b64"   ,"C:\\T.bmp");
      CBase64::Decode("C:\\TB64.bmp","C:\\T.b64");
    */
    #include <string>
    #include <fstream>
    using namespace std;
    
    namespace Base64
    {
    	bool Encode(const char* outFilePath, const char* inFilePath); 
    	void Encode(char* Result, const unsigned char* src, int Len);
    
    	bool Decode(const char* outFilePath, const char* inFilePath);
    	char Decode(char* Result, const char* src); 
    }
    
    #endif
    

    base64.cpp

    #include "base64.h"
    
    namespace Base64
    {
    //-----------------------------------------------------------------------------------------//
    
    bool Encode(const char* outFilePath, const char* inFilePath) 
    {
    	ofstream outFile(outFilePath, ios::app);
    	ifstream inFile(inFilePath, ios::in | ios::binary);
    
    	if(!outFile || !inFile)
    		return(false);
    
    	inFile.seekg(0, ios::end);
        unsigned long Len = streamoff(inFile.tellg()); 
        inFile.seekg(0, ios::beg); 
    
    	unsigned char src[57];   // BYTE src[57];
    	char dst[76+1];
    	int Count=Len/57;
    
    	for(int i=0; i<Count; i++)
    	{
    		inFile.read(reinterpret_cast<char*>(&src), 57);
    
    		//inFile.read(src, 57); 
    		Encode(dst,src,57);
    		outFile.write(dst,76);
    		outFile.write("\r\n",2);
    	}
    
    	if(int K=Len%57) 
    	{
    		inFile.read(reinterpret_cast<char*>(&src), K);
    	//	inFile.read(src,K);
    		Encode(dst,src,K);
    		outFile.write(dst,((K+2)/3)<<2);
    		outFile.write("\r\n",2);
    	}
    
    	return(true);
    }
    
    //-----------------------------------------------------------------------------------------//
    
    void Encode(char* Result, const unsigned char* src, int Len) 
    {
    static const char Bit6ToBase64[65]={"\
    ABCDEFGHIJKLMNOPQRSTUVWXYZ\
    abcdefghijklmnopqrstuvwxyz\
    0123456789+/"};
    
    	register char* dst=Result+3;
    	register unsigned long EncodeShifter=0;
    	int div=(Len==57) ? 57/3  : Len/3;
    	int mod=(Len==57) ?  0 : Len%3;
    
    	for(int i=0; i<div; i++) 
    	{
    		EncodeShifter=*src++;
    		EncodeShifter=(EncodeShifter<<8)|*src++;
    		EncodeShifter=(EncodeShifter<<8)|*src++;
    		*dst--=Bit6ToBase64[EncodeShifter & 0x3F]; EncodeShifter>>=6;
    		*dst--=Bit6ToBase64[EncodeShifter & 0x3F]; EncodeShifter>>=6;
    		*dst--=Bit6ToBase64[EncodeShifter & 0x3F]; EncodeShifter>>=6;
    		*dst  =Bit6ToBase64[EncodeShifter & 0x3F];
    		dst+=7;
    	}
    
    	*(dst-3)=0;
    
    	switch(mod) 
    	{
    		case 1: 
    		{
    			EncodeShifter=*src;
    			EncodeShifter<<=4;//111111 112222 222233 333333
    			*(dst+1)=0;       //         ====
    			*dst--='=';
    			*dst--='=';
    			*dst--=Bit6ToBase64[EncodeShifter & 0x3F]; EncodeShifter>>=6;
    			*dst  =Bit6ToBase64[EncodeShifter & 0x3F];
    			break;
    		}
    
    		case 2: 
    		{
    			EncodeShifter=*src++;
    			EncodeShifter=(EncodeShifter<<8)|*src;
    			EncodeShifter<<=2;//111111 112222 222233 333333
    			*(dst+1)=0;       //                  ==
    			*dst--='=';
    			*dst--=Bit6ToBase64[EncodeShifter & 0x3F]; EncodeShifter>>=6;
    			*dst--=Bit6ToBase64[EncodeShifter & 0x3F]; EncodeShifter>>=6;
    			*dst  =Bit6ToBase64[EncodeShifter & 0x3F];
    		} 
    	} 
    }
    
    //-----------------------------------------------------------------------------------------//
    
    bool Decode(const char* outFilePath, const char* inFilePath)
    {
    	ofstream outFile(outFilePath, ios::out | ios::binary);
    	ifstream inFile(inFilePath);
    
    	if(!outFile || !inFile)
    		return(false);
    
        char Result[57+1];  // byte
    
    	for(string line; getline(inFile, line); )   
    	{
    	  char Len=Decode(Result,line.c_str());
          outFile.write(Result, Len);
        }
        return true;
    }
    
    //-----------------------------------------------------------------------------------------//
    
    char Decode(char* Result, const char* src) 
    {
        static const unsigned char Base64ToBit6[128]={
          -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
          -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
          -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63,
          52,53,54,55,56,57,58,59,60,61,-1,-1,-1, 0,-1,-1,
          -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
          15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,
          -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
          41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1,
        };
        register char* dst=Result+2;
        register unsigned long DecodeShifter=0;
        size_t div=strlen(src)>>2; //no mod: the Law says its divisible by 4.
        unsigned char B;
        for(size_t i=0; i<div; i++) 
    	{
          if((B=*src++) & 0x80 || B<0) 
    		  return *Result=0; //Bad characters in stream
    
          DecodeShifter=Base64ToBit6[B];
    
          if((B=*src++) & 0x80 || B<0) 
    		  return *Result=0; //Bad characters in stream
    
          DecodeShifter=(DecodeShifter<<6) | Base64ToBit6[B];
    
          if((B=*src++) & 0x80 || B<0) 
    		  return *Result=0; //Bad characters in stream
    
          if(B=='=') 
    	  {//1111 11222222
            *--dst=0; //====
            DecodeShifter>>=4; *--dst=(char)DecodeShifter;
            return dst-Result+1;
    	  }
    
          DecodeShifter=(DecodeShifter<<6) | Base64ToBit6[B];
    
          if((B=*src++) & 0x80 || B<0) 
    		  return *Result=0; //Bad characters in stream
    
          if(B=='=') 
    	  {//11 11112222 22333333
            *dst--=0; //==
            DecodeShifter>>=2; *dst--=(char)DecodeShifter;
            DecodeShifter>>=8; *dst  =(char)DecodeShifter;
            return dst-Result+2;
          }
    
          DecodeShifter=(DecodeShifter<<6) | Base64ToBit6[B];
    
          *dst--=(char)DecodeShifter; DecodeShifter>>=8;
          *dst--=(char)DecodeShifter; DecodeShifter>>=8;
          *dst  =(char)DecodeShifter;
           dst+=5;
        }
        *(dst-=2)=0;
    
        if(dst-Result>127)
    		return *Result=0; //We're not looking at a valid Base64 section!
    
        return dst-Result;
    }
    
    //-----------------------------------------------------------------------------------------//
    
    } // end of namespace
    

    bye 🙂


Anmelden zum Antworten