Frage zu InputStream?

Gerd Müller

Mitglied
Hallo,

Ich bestize einen Stromzähler der alle 3-4 Sekunden eine SML-Protokoll aussendet.
Das SML-Protokoll hat 396 Bytes und ich lese den Binärstrom über einen COM-Port
mit der Klasse BufferedInputStream ein.
Mein Problem ist das ich nie komplett die 396 Bytes in den readBuffer bekomme sonder nur 8-56 Bytes gespeichert werden.
Mache ich irgendetwas falsch, oder gibt es eine anderen möglichkeit den Datenstrom komplett auf
einmal einzulesen?
Speichert die seriele Schnittstelle die Daten in irgendeinen Buffer auf den ich dann zugreifen kann?

Java:
    public void serialEvent(SerialPortEvent event) {
        //getEventType() gibt eine Int-Wert zurück
    	
    	switch(event.getEventType()) {
        case SerialPortEvent.BI:
        case SerialPortEvent.OE:
        case SerialPortEvent.FE:
        case SerialPortEvent.PE:
        case SerialPortEvent.CD:
        case SerialPortEvent.CTS:
        case SerialPortEvent.DSR:
        case SerialPortEvent.RI:
        case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
            break;
        case SerialPortEvent.DATA_AVAILABLE:
        	
            byte[] readBuffer = new byte[396];
            BufferedInputStream bufferinputstream = new BufferedInputStream(inputStream,396);
            try {
             
 numBytes=bufferinputstream.read(readBuffer,0,396)+numBytes;
            
           for (int i=0; i<readBuffer.length; i++)
            		System.out.println(i + " : " + readBuffer[i]);	
            System.out.printf("%d\n",numBytes);
            System.out.printf("fertig");
           
            serialPort1.close();
            } 
            catch (IOException e)
            {
            	System.out.print(new String(readBuffer));
            }
            
            break;
        }
    }
Viel Dank im voraus
 
Zuletzt bearbeitet von einem Moderator:
Du musst read() in einer Schleife solange aufrufen bis du -1 als Rückgabe erhälst, dann ist die Übertragung abgeschlossen.
Entweder schreibst du dann jeweils den Inhalt deines readBuffers irgendwo weg (wenns nen String ist z.b. in einen StringBuilder), oder du merkst dir wieviele bytes gelesen wurden und fängst im nächsten Durchlauf an der Stelle wieder an in den readBuffer zu schreiben.
 
steigt die Anzahl der verfügbaren Bytes wenn bisschen gewartet wird?
Thread.sleep(100);
oder ist 56 bzw. eine höhere Teilzahl irgendwann Maximum?

und Hauptpunkt für Meldung:
Java-Tags nicht vergessen
 
Du musst read() in einer Schleife solange aufrufen bis du -1 als Rückgabe erhälst, dann ist die Übertragung abgeschlossen.
Entweder schreibst du dann jeweils den Inhalt deines readBuffers irgendwo weg (wenns nen String ist z.b. in einen StringBuilder), oder du merkst dir wieviele bytes gelesen wurden und fängst im nächsten Durchlauf an der Stelle wieder an in den readBuffer zu schreiben.


Hast du das so gemeint:
Java:
while((avaBytes=bufferinputstream.read(readBuffer,pos,396))!=-1)
 	{
 		numBytes=avaBytes+numBytes;
 		pos=numBytes;
 	}

irgendwie bekomm ich so gar keine werte mehr?
 
Wenn du mit einem array lesen willst, würde ich es eher so machen:
Java:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;

public class InputStreamExample 
{
	public static void main(String[] args) throws Exception 
	{
		InputStream in=getInputStream();
		
		byte[] buffer=new byte[2048];
		int bytesRead=-1;
		ByteArrayOutputStream baos=new ByteArrayOutputStream();
		
		while((bytesRead=in.read(buffer))!=-1) {
			baos.write(buffer, 0, bytesRead);
		}
		
		byte[] result=baos.toByteArray();
		System.out.println(new String(result));
	}	
	
	
	public static InputStream getInputStream()
	{
		return new ByteArrayInputStream("Verbrauch:2928289;In Euros: Ne ganze Menge! Haben die Strompreise wieder angehoben und du bist der Dumme =]".getBytes());
	}
}

Wenn du den Stream nicht von vorn lesen willst, sonder ab byte x, dann verwende die Methode [c]skip[/c] vom InputStream. (kannst du ja einfach an meinem KSKB testen, was passiert, wenn du vor dem lesen des Streams, skip aufrufst)
 
Wenn du mit einem array lesen willst, würde ich es eher so machen:
Java:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;

public class InputStreamExample 
{
	public static void main(String[] args) throws Exception 
	{
		InputStream in=getInputStream();
		
		byte[] buffer=new byte[2048];
		int bytesRead=-1;
		ByteArrayOutputStream baos=new ByteArrayOutputStream();
		
		while((bytesRead=in.read(buffer))!=-1) {
			baos.write(buffer, 0, bytesRead);
		}
		
		byte[] result=baos.toByteArray();
		System.out.println(new String(result));
	}	
	
	
	public static InputStream getInputStream()
	{
		return new ByteArrayInputStream("Verbrauch:2928289;In Euros: Ne ganze Menge! Haben die Strompreise wieder angehoben und du bist der Dumme =]".getBytes());
	}
}

Wenn du den Stream nicht von vorn lesen willst, sonder ab byte x, dann verwende die Methode [c]skip[/c] vom InputStream. (kannst du ja einfach an meinem KSKB testen, was passiert, wenn du vor dem lesen des Streams, skip aufrufst)



Hab jetzt so ähnlich probiert, bloß mein problem ist jetzt das er nicht mehr aus der while schleife raus geht.
Kannst du mir sagen wieso?
Hab gemeint bei Streamende gibt read eine -1 zurück?

Java:
 public void serialEvent(SerialPortEvent event) {
        //getEventType() gibt eine Int-Wert zurück
        
        switch(event.getEventType()) {
        case SerialPortEvent.BI:
        case SerialPortEvent.OE:
        case SerialPortEvent.FE:
        case SerialPortEvent.PE:
        case SerialPortEvent.CD:
        case SerialPortEvent.CTS:
        case SerialPortEvent.DSR:
        case SerialPortEvent.RI:
        case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
            break;
        case SerialPortEvent.DATA_AVAILABLE:
            
            byte[] readBuffer = new byte[396];
            int iread=-1;
            BufferedInputStream bufferinputstream = new BufferedInputStream(inputStream,396);
            try {
             
            	while((iread=bufferinputstream.read(readBuffer,0,396))!=-1)
            	{
	 
            	}
		 
            
           for (int i=0; i<readBuffer.length; i++)
                    System.out.println(i + " : " + readBuffer[i]);  
            System.out.printf("%d\n",numBytes);
            System.out.printf("fertig");
           
            serialPort1.close();
            } 
            catch (IOException e)
            {
                System.out.print(new String(readBuffer));
            }
            
            break;
        }
    }
 
-1 wird nur dann zurückgegeben, wenn der Stream wirklich zu Ende ist. Aber in deinem Scenario wird das wahrscheinlich niemals der Fall sein => du wirst ja permanent Strom verbrauchen. Von daher bekommst du immer Daten zugesendet.

Ich weiß nicht, wie die Daten aussehen die du bekommst. Aber du kannst die Empfangen Daten ja auswerten und wenn die Informationen vollständig sind, die Anzeige Aktualisieren. Ich würde sagen, du wirst da Multithreading betreiben müssen, da du sonst wirklich in dieser Schleife festhängst (außer dir reicht das Anzeigen dieser Werte).
 
-1 wird nur dann zurückgegeben, wenn der Stream wirklich zu Ende ist. Aber in deinem Scenario wird das wahrscheinlich niemals der Fall sein => du wirst ja permanent Strom verbrauchen. Von daher bekommst du immer Daten zugesendet.

Ich weiß nicht, wie die Daten aussehen die du bekommst. Aber du kannst die Empfangen Daten ja auswerten und wenn die Informationen vollständig sind, die Anzeige Aktualisieren. Ich würde sagen, du wirst da Multithreading betreiben müssen, da du sonst wirklich in dieser Schleife festhängst (außer dir reicht das Anzeigen dieser Werte).

Es wird alle 3-4 Sekunden ein Komplettes SML-Protokoll a 396 Bytes seriell aus Stromzähler ausgesendet, sozusagen ein Bytestrom am COM-Port meines PC's. Ich benötige immer die Kompletten 396 Bytes.

Also muss ja mein Stream auch einmal ein Ende haben?
 
Zuletzt bearbeitet:
gehe andersrum vor, lies immer soviel wie da ist, wenn blockiert wird ist das ok, ansonsten reiche die 5, 20 oder 50 Bytes weiter,
ein zweiter Thread (oder der Code des ersten Threads in der read-Schleife) bekommt ständig die Bytes,
hat dort den Überblick, und wenn der erkennt dass genau 396 zusammengekommen sind dann reicht der diese 396 weiter,
falls der Sprung von 380 auf 405 war, dann trotzdem die hoffentlich richtigen 396 weiterreichen und die 19 weiteren fürs nächste 396-Paket 'ansparen'

so in etwa hast du dir vielleicht die Funktionalität von
> bufferinputstream.read(readBuffer,0,396)
vorgestellt,
das mag es nicht geben, kannst du dir aber mehr oder weniger selber zusammenbauen
 
Also muss ja mein Stream auch einmal ein Ende haben?

Nein. Der Stream wird vllt 3-4 Sekunden blockieren oder einfach nur \0 o.ä. senden, aber ein Ende wie du glaubst hat er so (wahrscheinlich) nicht. Außer dein Stromzähler explodiert,resetet sich,... Du musst eben die Daten auswerten und wenn deine Information da ist, die du benötigst, leitest du diese eben weiter.
 
Dann sollte es doch so eigentlich funktionieren oder?
oder kann es da sein, das zwischendrinnen einzelne Bytes übersehen werden??

Java:
int i = 0;
        	byte[] readBuffer = new byte[396];        	
            BufferedInputStream bufferinputstream = new BufferedInputStream(inputStream,396);
            try {
             
            	while(i<396)
            	{
            		i=bufferinputstream.read(readBuffer,i,1)+i;           		
            	}
 

Zurück
Oben