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


von Jonny (Gast)


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 User
von Läubi .. (laeubi) Benutzerseite


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:
1
byte myByte = ...;
2
int unsingedByte = ((int)myByte) & 0xFF;
Alternativ kannst du ja auch die bytes einzeln über die read Funktion 
gleich als int lesen.

von Jonny (Gast)


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


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)


Lesenswert?

Danke für den Hinweis.

Funktioniert nun alles wie gewollt.

von Mr.Unsigned (Gast)


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 :)


1
   byte[] readBuf = (byte[]) msg.obj;
2
3
4
                           int[] ret = new int[readBuf.length];
5
                            for (short i = 0; i < readBuf.length; i++)
6
                        {
7
                              ret[i] = (readBuf[i]&255);
8
                           }
9
10
11
                        String strIncom = new String(readBuf, 0, msg.arg1);                 // erstelle String aus Bytes Array
12
                            sb.append(strIncom);                                                // String anhängen
13
                            int endOfLineIndex;
14
                            String path = "sdcard/" + dateipfad.getText().toString() + ".txt";  //Environment.getExternalStorageDirectory().getPath()
15
16
                            while ((endOfLineIndex = sb.indexOf("|0|")) >= 0) {                  // wenn end-of-line,
17
                                String sbprint;                                                 // extrahiere String
18
                                sbprint = sb.substring(0, endOfLineIndex);
19
                                sb.delete(0, sb.length());                                      // und löschen
20
21
                                try {
22
                                    File myFile = new File(path);
23
                                    myFile.createNewFile();
24
                                    FileOutputStream fOut = new FileOutputStream(myFile, true);
25
                                    OutputStreamWriter myOutWriter =
26
                                            new OutputStreamWriter(fOut);
27
                                    myOutWriter.append(sbprint);
28
                                    myOutWriter.close();
29
                                    fOut.close();

von Mr.Unsigned (Gast)


Lesenswert?

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


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

von Roland P. (pram)


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)


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:



1
           byte[] readBuf = (byte[]) msg.obj;
2
 
3
                                try {
4
                                    File myFile = new File(path);
5
                                    myFile.createNewFile();
6
                                    FileOutputStream fOut = new FileOutputStream(myFile, true);
7
                                   
8
                                    fOut.write(readBuf);
9
                                    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)


Lesenswert?

1
for (int i = 0; i < readBuf.length - 2; i++) {
2
  if (readBuf[i] == '|' && readBuf[i+1] == '0' && readBuf[i+2] == '|') {
3
    endePos = i;
4
    break
5
  }
6
}

von Mr.Unsigned (Gast)


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)


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)


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)


Lesenswert?

Das müsste alles sein.
1
Handler() {
2
    public void handleMessage (android.os.Message msg){
3
4
5
        switch (msg.what) {
6
            case RECIEVE_MESSAGE:
7
                byte[] readBuf = (byte[]) msg.obj;
8
                ByteArrayOutputStream baos = new ByteArrayOutputStream(readBuf.length);
9
                
10
11
12
               int[] ret = new int[readBuf.length];
13
                for (short i = 0; i < readBuf.length; i++)
14
            {
15
                  ret[i] = (readBuf[i]&255);
16
               }
17
18
19
            String strIncom = new String(ret, 0, msg.arg1);                 // erstelle String aus Bytes Array
20
                sb.append(strIncom);                                                // String anhängen
21
                int endOfLineIndex;
22
                String path = "sdcard/" + dateipfad.getText().toString() + ".txt";  //Environment.getExternalStorageDirectory().getPath()
23
24
                while ((endOfLineIndex = sb.indexOf("|0|")) >= 0) {                  // wenn end-of-line,
25
                    String sbprint;                                                 // extrahiere String
26
                    sbprint = sb.substring(0, endOfLineIndex);
27
                    sb.delete(0, sb.length());                                      // und löschen
28
29
                    try {
30
                        File myFile = new File(path);
31
                        myFile.createNewFile();
32
                        FileOutputStream fOut = new FileOutputStream(myFile, true);
33
                        //OutputStreamWriter myOutWriter =
34
                          //      new OutputStreamWriter(fOut);
35
                        //myOutWriter.append(sbprint);
36
                        //myOutWriter.close();
37
                        fOut.write(readBuf);
38
                        fOut.close();
39
40
41
42
                    } catch (Exception e) {
43
                        Toast.makeText(getBaseContext(), e.getMessage(),
44
                                Toast.LENGTH_SHORT).show();
45
                    }
46
                }
47
                break;
48
        }
49
    }
50
51
}
52
53
;
54
55
56
private class ConnectedThread extends Thread {
57
       private final InputStream mmInStream;
58
       private final OutputStream mmOutStream;
59
60
       public ConnectedThread(BluetoothSocket socket) {
61
           InputStream tmpIn = null;
62
           OutputStream tmpOut = null;
63
64
           try {
65
               tmpIn = socket.getInputStream();
66
               tmpOut = socket.getOutputStream();
67
           } catch (IOException e) { }
68
69
           mmInStream = tmpIn;
70
           mmOutStream = tmpOut;
71
       }
72
73
       public void run() {
74
           byte[] buffer = new byte[1024];  // Pufferspeicher für den Stream
75
           int bytes; // ausgegebene Bytes von read()
76
77
78
79
           //  InputStream lesen bis Fehler auftreten
80
           while (true) {
81
              try {
82
                   // Lese InputStream
83
                   bytes = mmInStream.read(buffer);      // Erhalte Anzahl der Bytes und der Daten in "buffer"
84
                    h.obtainMessage(RECIEVE_MESSAGE, bytes, -1, buffer).sendToTarget();       // Sende zum Handler
85
               } catch (IOException e) {
86
                   break;
87
               }
88
           }
89
       }
90
91
     
92
       public void write(String message) {
93
          //Log.d(TAG, "...Data to send: " + message + "...");
94
          byte[] msgBuffer = message.getBytes();
95
          try {
96
               mmOutStream.write(msgBuffer);
97
           } catch (IOException e) {
98
            
99
             }
100
       }
101
   }
102
103
104
105
106
}

von Mr.Unsigned (Gast)


Lesenswert?

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

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.