Forum: PC-Programmierung Java - signed Byte in unsigned int wandeln


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Jonny (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich stehe gerade vor einem kleinen "Problemchen".
Ich möchte in Java einen einkommenden Bytestream sortieren und dann in 
einen Integer wandeln. Jetzt gibt es ja die bereitgestellten 
Inputstreamfunktionen die mir die ankommenden Bytes in einen Bytearray 
speichert.

Jetzt ist es so das ein ankommendes Byte mit dem Wert 0x80 oder höher 
als signed gespeichert wird. Also -128 im Falle von 0x80 da ja das 
Vorzeichenbit gesetzt ist.

Weiss jemand wie ich das am besten handeln kann, sodass ein empfangenes 
0x80 auch wirklich als +128 gespeichert wird. Mit Typcast? Bloß wie und 
in was?


Gruß
Jonny

: Verschoben durch Moderator
von Läubi .. (laeubi) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Jonny schrieb:
> mit dem Wert 0x80 oder höher
> als signed gespeichert wird

Bytes sind immer signed, generelll ist jeder Integer-Datentyp in Java 
signed.

Was genau möchtest du den dort sortieren?

Am einfachstem wäre es wohl wenn du das ganze in int konvertierst etwa 
so:
byte myByte = ...;
int unsingedByte = ((int)myByte) & 0xFF;
Alternativ kannst du ja auch die bytes einzeln über die read Funktion 
gleich als int lesen.

von Jonny (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Danke für die Antwort. Ich sortiere die Bytes sodass das MSB vorne 
steht. Ich verwende nun eine Konvertierung, allerdings zu long, da int 
nicht ausreichend ist.
Dazu verwende ich die Funktion:

long ByteArrayToLong(byte[] b)
{

   long[] buf = {(((long)b[0]) & 0xFF),(((long)b[1]) & 
0xFF),(((long)b[2]) & 0xFF),(((long)b[3]) & 0xFF)};


        return   buf[3] & 0xFF |
                (buf[2] & 0xFF) << 8 |
                (buf[1] & 0xFF) << 16 |
                (buf[0] & 0xFF) << 24;
  }

Nun funktioniert alles. Danke nochmal.

Gruß
Jonny

von Läubi .. (laeubi) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Die konvertierung in ein Long array ist unötig, du kannst auch einfach 
die bytes dirket casten so ist es etwas doppelt gemoppelt.

von Jonny (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Danke für den Hinweis.

Funktioniert nun alles wie gewollt.

von Mr.Unsigned (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo auch wenn der Thread etwas älter ist, selbes Problem wie der TE, 
ich mache mal kein neuen auf...


Läubi .. schrieb:
> Bytes sind immer signed, generelll ist jeder Integer-Datentyp in Java
> signed.

Ich hab versucht jedes Element in meinem Input-stream mit 0&FF zu 
erweitern... die untere Hälfte des Wertebereichs ist alles richtig, aber 
statt einer 0x80 erhalte ich dann eine: c2 80,

für 0x81 eine c2 81, für 0x82 c2 82, usw....

statt eine FF erhalte ich: c3 bf; was das für ein Quatsch?


Bitte um Hilfe. Bin Java-Laie, danke :)



   byte[] readBuf = (byte[]) msg.obj;


                           int[] ret = new int[readBuf.length];
                            for (short i = 0; i < readBuf.length; i++)
                        {
                              ret[i] = (readBuf[i]&255);
                           }


                        String strIncom = new String(readBuf, 0, msg.arg1);                 // erstelle String aus Bytes Array
                            sb.append(strIncom);                                                // String anhängen
                            int endOfLineIndex;
                            String path = "sdcard/" + dateipfad.getText().toString() + ".txt";  //Environment.getExternalStorageDirectory().getPath()

                            while ((endOfLineIndex = sb.indexOf("|0|")) >= 0) {                  // wenn end-of-line,
                                String sbprint;                                                 // extrahiere String
                                sbprint = sb.substring(0, endOfLineIndex);
                                sb.delete(0, sb.length());                                      // und löschen

                                try {
                                    File myFile = new File(path);
                                    myFile.createNewFile();
                                    FileOutputStream fOut = new FileOutputStream(myFile, true);
                                    OutputStreamWriter myOutWriter =
                                            new OutputStreamWriter(fOut);
                                    myOutWriter.append(sbprint);
                                    myOutWriter.close();
                                    fOut.close();

von Mr.Unsigned (Gast)


Bewertung
0 lesenswert
nicht lesenswert
String strIncom = new String(ret, 0, msg.arg1);


heißt es an dieser Stelle natürlich..

von Roland P. (pram)


Bewertung
0 lesenswert
nicht lesenswert
>   String strIncom = new String(readBuf, 0, msg.arg1);

Hier verwendest du 1. den Originalbuffer und 2 passiert hier sehr 
wahrscheinlich eine Zeichensatzkodierung.

/edit sehe gerade deinen Korrekturpost, deshalb streich 1.

Wenn du ein Byte-Array 1:1 weg schreiben willst, darfst du es nicht auf 
String konvertieren (da java die Bytes dann nach UTF-8 konvertiert)

Verwende einen ByteArrayOutputStream (eine Konvertierung nach Int ist 
dann nichz notwendig) und suche nach der Ende-Markierung zu fuß

Gruß Roland

: Bearbeitet durch User
von Mr.Unsigned (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo Roland und vielen Dank.

Roland P. schrieb:
> passiert hier sehr
> wahrscheinlich eine Zeichensatzkodierung.

das ist wohl mein Problem, genau.

Roland P. schrieb:
> Wenn du ein Byte-Array 1:1 weg schreiben willst

das will ich, einfach eine Art "Terminal"

Roland P. schrieb:
> darfst du es nicht auf
> String konvertieren (da java die Bytes dann nach UTF-8 konvertiert)

das habe ich gemerkt. :(

Roland P. schrieb:
> Verwende einen ByteArrayOutputStream (eine Konvertierung nach Int ist
> dann nichz notwendig)
ok.

>und suche nach der Ende-Markierung zu fuß

Wie sieht sowas denn dann aus?


Ich hatte mal folgendes probiert:




           byte[] readBuf = (byte[]) msg.obj;
 
                                try {
                                    File myFile = new File(path);
                                    myFile.createNewFile();
                                    FileOutputStream fOut = new FileOutputStream(myFile, true);
                                   
                                    fOut.write(readBuf);
                                    fOut.close();


...Wunderbar, meine 0xFF sind da. Natürlich fehlt jetzt der Index und 
der Buffer wird willkürlich ausgelesen.

Kannst du mir vlt. helfen wie ich da ohne Stringkonvertierung einen 
Index einführe?

Kann ich nicht statt |0|

verwenden:

0x7c 0x00 0x7c o.ä.? ??


Danke im Voraus. Gruß zurück :)

von Roland P. (pram)


Bewertung
0 lesenswert
nicht lesenswert
for (int i = 0; i < readBuf.length - 2; i++) {
  if (readBuf[i] == '|' && readBuf[i+1] == '0' && readBuf[i+2] == '|') {
    endePos = i;
    break
  }
}

von Mr.Unsigned (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Roland P. schrieb:
> for (int i = 0; i < readBuf.length - 2; i++) {
>   if (readBuf[i] == '|' && readBuf[i+1] == '0' && readBuf[i+2] == '|') {
>     endePos = i;
>     break
>   }
> }

Danke für deine schnelle Antwort Roland und sorry, dass ich dir nicht 
auf Anhieb folgen kann. (Java = sehr unerfahren).

durch int endePos = i, habe ich dann die Stelle an der der Index steht? 
Aber wie verwende ich die nun richtig ôÔ ?

von Jack (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Aus deinem Code versteht ich nicht was du wirklich willst. Daher hier 
nur Grundsätzliches:

...Reader / ...Writer sind für Text.

...InputStream / ...OutputStream sind für Daten.


Es zählt immer das Ende des Klassennamens. Beispiel: Ein 
InputStreamReader ist ein Reader (also für Text), der in diesem Fall 
seine Rohdaten aus einem InputStream bekommen kann.

Das Mischen von Reader und InputStream, bzw. Writer und OutputStream 
sollte nur kontrolliert erfolgen und dann sollte man wissen was man tut. 
Zum kontrollierten Mischen gehört, dass man ein Encoding angibt oder 
sich drei mal vergewissert hat, dass der Default das gewünschte Encoding 
ist.

Daten die ein Gemisch aus Text und Binärdaten sind kann man mit 
DataInputStream lesen wenn man sie mit DataOutputStream geschrieben hat. 
Für beliebige Dateiformate sind die beiden Klassen zu unflexibel. 
Ähnlich eingeschränkt sind diverse andere Klassen die DataInput bzw. 
DataOutput implementieren.

Für kompliziertere Operationen auf beliebige Dateiformate, 
einschließlich der Änderung der Endianess, kann man auf "new" IO 
(java.nio) Klassen wechseln. Insbesondere ByteBuffer. Um ein ByteBuffer 
zu bekommen beginnt man mit einer wrap() oder allocate() Methode oder 
liest von einem FileChannel.

Ein "|o|" als Ende-Markierung in eine Binärdatei zu schreiben ist 
reichlich merkwürdig. Wer gibt einem die Garantie, dass normale Daten 
nicht zufällig "|o|" enthalten? Entweder weiß man von vornherein wie 
lang die Daten sind, oder man schreibt zuerst die Länge der Daten, dann 
die Daten. Bei Text kann man auch Null-Terminierte Daten schreiben, wenn 
das Encoding garantiert, dass \0 nie innerhalb des encodierten Textes 
auftritt.

von Mr.Unsigned (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hi Jack und danke für deine ausführliche Antwort.

Jack schrieb:
> ...InputStream / ...OutputStream sind für Daten.

ok, ich bin noch sehr neu in diesem Gebiet.. da es zum größtenteil 
funktioniert hat, dachte ich es schnell fertig zu bekommen... :(

Jack schrieb:
> Ein "|o|" als Ende-Markierung in eine Binärdatei zu schreiben ist
> reichlich merkwürdig. Wer gibt einem die Garantie, dass normale Daten
> nicht zufällig "|o|"

gibt keine Garantie, aber selbst wenn, dann wird doch der Index nur 
einmal verrückt beim ersten Code und ein kürzerer String extrahiert? 
Dadurch geht doch nichts verloren? Oder liege ich da falsch.

Jack schrieb:
> Entweder weiß man von vornherein wie

soll ja ein Stream werden, µC schickt permanent Werte.
Ich kenne die Anzahl der Bytes pro mein definiertes Paket..

Der erste Code war schon so wie ich ihn haben wollte.. eigentlich..

von Mr.Unsigned (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Das müsste alles sein.
Handler() {
    public void handleMessage (android.os.Message msg){


        switch (msg.what) {
            case RECIEVE_MESSAGE:
                byte[] readBuf = (byte[]) msg.obj;
                ByteArrayOutputStream baos = new ByteArrayOutputStream(readBuf.length);
                


               int[] ret = new int[readBuf.length];
                for (short i = 0; i < readBuf.length; i++)
            {
                  ret[i] = (readBuf[i]&255);
               }


            String strIncom = new String(ret, 0, msg.arg1);                 // erstelle String aus Bytes Array
                sb.append(strIncom);                                                // String anhängen
                int endOfLineIndex;
                String path = "sdcard/" + dateipfad.getText().toString() + ".txt";  //Environment.getExternalStorageDirectory().getPath()

                while ((endOfLineIndex = sb.indexOf("|0|")) >= 0) {                  // wenn end-of-line,
                    String sbprint;                                                 // extrahiere String
                    sbprint = sb.substring(0, endOfLineIndex);
                    sb.delete(0, sb.length());                                      // und löschen

                    try {
                        File myFile = new File(path);
                        myFile.createNewFile();
                        FileOutputStream fOut = new FileOutputStream(myFile, true);
                        //OutputStreamWriter myOutWriter =
                          //      new OutputStreamWriter(fOut);
                        //myOutWriter.append(sbprint);
                        //myOutWriter.close();
                        fOut.write(readBuf);
                        fOut.close();



                    } catch (Exception e) {
                        Toast.makeText(getBaseContext(), e.getMessage(),
                                Toast.LENGTH_SHORT).show();
                    }
                }
                break;
        }
    }

}

;


private class ConnectedThread extends Thread {
       private final InputStream mmInStream;
       private final OutputStream mmOutStream;

       public ConnectedThread(BluetoothSocket socket) {
           InputStream tmpIn = null;
           OutputStream tmpOut = null;

           try {
               tmpIn = socket.getInputStream();
               tmpOut = socket.getOutputStream();
           } catch (IOException e) { }

           mmInStream = tmpIn;
           mmOutStream = tmpOut;
       }

       public void run() {
           byte[] buffer = new byte[1024];  // Pufferspeicher für den Stream
           int bytes; // ausgegebene Bytes von read()



           //  InputStream lesen bis Fehler auftreten
           while (true) {
              try {
                   // Lese InputStream
                   bytes = mmInStream.read(buffer);      // Erhalte Anzahl der Bytes und der Daten in "buffer"
                    h.obtainMessage(RECIEVE_MESSAGE, bytes, -1, buffer).sendToTarget();       // Sende zum Handler
               } catch (IOException e) {
                   break;
               }
           }
       }

     
       public void write(String message) {
          //Log.d(TAG, "...Data to send: " + message + "...");
          byte[] msgBuffer = message.getBytes();
          try {
               mmOutStream.write(msgBuffer);
           } catch (IOException e) {
            
             }
       }
   }




}


von Mr.Unsigned (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ich werde mich dann mal weiter einlesen, ich hoffe aber doch das mein 
Problem verständlich ist, oder?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.