streamreading (java to c++)



  • Ich möchte folgende Java-Funktion in C++ nachprogrammieren:

    (stream ist ein InputStream)

    protected long readLong() throws IOException {
    		byte[] bytes = new byte[8];
    		this.stream.read(bytes);
    		return ((long) (bytes[7] & 0xff) << 56) | ((long) (bytes[6] & 0xff) << 48) | ((long) (bytes[5] & 0xff) << 40) | ((long) (bytes[4] & 0xff) << 32) |
    			   ((long) (bytes[3] & 0xff) << 24) | ((long) (bytes[2] & 0xff) << 16) | ((long) (bytes[1] & 0xff) << 8) | (bytes[0] & 0xff);
    	}
    

    meine vorläufige c++ variante sieht so aus, wobei stream ein ifstream ist:

    long Test::readLong()
    {
    	char* bytes = new char[8];
    	stream.read(bytes, 8); 
    
    	return ((long)(bytes[7] & 0xFF) << 56) | ((long)(bytes[6] & 0xFF) << 48) | ((long)(bytes[5] & 0xFF) << 40) | ((long)(bytes[4] & 0xFF) << 32) | 
    		   ((long)(bytes[3] & 0xFF) << 24) | ((long)(bytes[2] & 0xFF) << 16) | ((long)(bytes[1] & 0xFF) << 8) | (bytes[0] & 0xFF); 
    }
    

    Beim kompilieren bekomme ich nun aber diese Warnung:
    "'<<' shift count negative or too big, undefined behaviour"

    Hat jemand eine Idee wie ich den Code richtig in C++ übersetzen kann?

    Vielen Dank schon mal!



  • long ist bei dir wahrscheinlich nicht 64 bit breit. Nimm stattdessen int64_t.
    char würde ich auch nicht nehmen, wenn du mit Bytes hantierst. Mach dir lieber einen typedef unsigned char byte;.



  • und statt

    char* bytes = new char[8];
    
    char bytes[8];
    

    damit das ganze auch wieder gelöscht wird.



  • danke! int64_t müsste ich vermutlich selbst definieren, aber mit long long funktioniertes auch.

    Bezüglich char: ich hatte eigentlich vor unsigned char zu verwenden, aber die read methode verlangt einen char als parameter. Könnte es dann mit unsigned nicht zu problemen kommen?



  • brotbernd schrieb:

    und statt

    char* bytes = new char[8];
    
    char bytes[8];
    

    damit das ganze auch wieder gelöscht wird.

    diese variante wollte ich auch ursprünglich verwenden, hatte damit aber auch probleme mit der read methode, da ich dann diesen kompilierfehler bekam:

    Error 1 error C2664: 'std::basic_istream<_Elem,_Traits>::read' : cannot convert parameter 1 from 'char (*)[4]' to 'char *'

    also wenn ich bei meiner variante bleibe, müsste ich also noch ein delete bytes einfugen



  • int64_t & Co. bekommst du mit <stdint.h>.
    Warum eine read-Funktion char* als Parameter erwartet ist mir zwar rätselhaft, aber du kannst ihr gefahrlos einen unsigned char-Zeiger geben. Der benötigte Cast ist natürlich nicht so schön.

    Edit:

    Error	1	error C2664: 'std::basic_istream<_Elem,_Traits>::read' : cannot convert parameter 1 from 'char (*)[4]' to 'char *'
    

    Du hast char* bytes[8]; geschrieben.

    Edit2:
    Und auch dann müsste es delete[] bytes heißen.

    Wozu dienen eigentlich die ganzen &0xff? Das scheint mir weder in Java noch in C++ viel Sinn zu machen, denn größer als 0xff können Bytes sowieso nicht sein.



  • stdint.h kennt der compiler nicht (Visual Studio 2008).. also bleibe ich vorläufig einfach bei long long.

    den cast habe ich nur mit reinterpret_cast hinbekommen, ich denke das wird in diesem fall schon ok sein.

    die '& 0xFF' verstehe ich auch nicht. ich habe nur den java code vorliegen, den ich nun nach c++ überführen soll und so weit ich weiß funktioniert der java-code, also habe ich das einfach übernommen.

    Edit:
    vielleicht werden die 0xFF's in Java deswegen benötigt, da es in java keine unsigned bytes gibt und auf diese Weise das Vorzeichen beseitigt wird?



  • Im Prinzip ist es vollkommen wurst, ob char oder unsigned char , die ham ja eh dieselbe Bitrepräsentation und da ja hier nur mit Bits gearbeitet wird, kann man beides nehmen.



  • ich hätte hier noch ein weiteres Problem: und zwar muss ich UTF-8 codierte String einlesen.

    protected String readString(int size, int len, String charset) throws IOException
    {
    	int length = (size > 0 ? size : len);
    	byte[] bytes = new byte[length];
    	this.stream.read(bytes);
    	length = (len >= 0 ? len : size); 
    
    	try
    	{
    		return new String(new String(bytes, 0, length, charset).getBytes("UTF-8"), "UTF-8");
    	}
    	catch(Throwable e)
    	{
    		e.printStackTrace();
    	}
    	return new String(bytes, 0, length);
    }
    

    hat jemand eine Idee wie ich den Code ab dem try in C++ nachprogrammiere?

    Zur Zeit sieht der Code so aus, ich komme leider nur bis zum einlesen der Daten. Wie kann ich den char* in einen UTF-8 string casten bzw. welcher Datentyp ist dafür in c++ vorgesehen? So weit ich weiß ist ein wchar_t ja ein 16-bit Unicode, ein char* zwar 8-bit aber wieder ASCII codiert.

    ??? Test::readString(int size, int len)
    {
    	int length = (size > 0 ? size : len);
    	unsigned char* bytes = new unsigned char[length];
    
    	stream.read(reinterpret_cast<char*>(bytes), length); 
    
    }
    

    Ich hoffe jemand kennt sich damit aus, und auch vielen Dank für die bisherigen Beiträge!


Anmelden zum Antworten