# in.ready() liefert IMMER false zurück



## JROppenheimer (10. Nov 2006)

ich hab hier ein problem.

ich hab einen BufferedReader. Der wird gefüllt, mit nem InputStream von nem socket.


```
this.socket = new Socket(host, port);										.
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
```

jetzt versuche ich hier eine methode zu schreiben, die folgendes leistet:

wenn in "in" etwas ist, soll es ausgelesen und weiter verarbeitet werden.
wenn nichts drin ist, dann soll nix passieren.

ich versuche das seit 2 tage auf die Reihe zu bekommen.
Mein erster versuch war:


```
if (in.readLine != null)
   System.out.println(in.readLine());
```
das hat nicht gemacht, was ich wollte

dann bin ich auf diese ready() Methode gestoßen und hab es so versucht:


```
if (in.ready() == true)
   System.out.println(in.readLine());
```

aber das Problem ist:

wenn ich in.ready() benutze, bekomm ich IMMER false.
wenn ich es aber dann ausgebe via System.out.println, bekomm ich den string, den der host geschickt hat.

wo ist mein Fehler?


----------



## SlaterB (10. Nov 2006)

meinst du

if ((line = in.readLine()) != null)
   System.out.println(line);
}


----------



## JROppenheimer (10. Nov 2006)

so hab ich das auch schon versucht, aber dann hat mein programm ne übertrieben lange laufzeit.

jedesmal, wenn in.readLine() null ist, dann dauert es ewig bis dieses null zurückgegeben wird.
Das ist es ja, was ich nicht verstehe.

in.ready() sollte doch eigendlich true liefern, wenn etwas in "in" liegt, was dann mit in.readLine() abgerufen werden kann, oder?

aber ich bekomm IMMER false ... und das verstehe ich nicht.


----------



## SlaterB (10. Nov 2006)

wie stellst du dir das ganze eigentlich vor?
solange die Verbindung existiert, wird ready auch true senden,

und solange sollte doch wohl ein Thread darauf warten, dass neue Daten kommen,
dieses Warten kann unbestimmt lange dauern, das ist richtig,
aber andere Programmteile können ja in anderen Threads weiterarbeiten

ich benutzte z.B.

```
public void run() {
		int len;
		byte[] b = new byte[400];

		while (!breakV) {
			try {
	
				if ((len = in.read(b)) == -1) { 
	            	break;
				}
				
				if (empf != null) {
					empf.verarbeiteDaten(new String(b,0,len));
				}

			} catch (InterruptedIOException e) { 
				//nochmal versuchen
			} catch (IOException e) {
				L.p("IO-Exception");
				e.printStackTrace();
				P.exit();
			}

		}
	}
```


----------



## JROppenheimer (10. Nov 2006)

na das problem ist ja, dass ich NIE true bekomme. sondern immer nur false!

selbst wenn ich es direkt nach der abfrage ausgebe, und sehe,dass da inhalt drin ist, ist in.ready() = false!


----------



## SlaterB (10. Nov 2006)

nun gut, dann sage ich mal:
1 Nanosekunde nach dem Aufbau der Verbindung sind noch keine Daten da, also liefert der Stream korrekt 'false',
falls der Server umgehend was sendet, kann das ja durchaus 100ms oder noch viel länger dauern,

wie gehst du denn damit um?


----------



## JROppenheimer (10. Nov 2006)

okay, du hast ja nicht unrecht, aber schau Dir bitte mal folgendes an:


```
try
		{
			for (int i=1; i<11; i++) 
			{
				String line = in.readLine();
				if (line != null)
					System.out.println(line);
				else if (line == null)
					System.out.println("null");
			}			
		}
		catch (Exception ex)
		{
			System.out.println(ex.toString());
		}
```

das habe ich nur mal gemacht, damit ich Dir erklären kann, was ich meine.

die ausgabe lautet schon richtig:

Anfang
ready: false
<msg source="System">ready</msg>
------------------
UND GENAU HIER von <msg ... > bis zum ersten null, dauert es mehrere Sekunden. und DAS versteh ich nicht. wäre "in" leer, dann könnte der doch direkt null zurückgeben. vlt kann mich mal jemand erleuchten!
------------------
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
Ende


----------



## SlaterB (10. Nov 2006)

ich kenne mich da auch nicht völlig aus,
zum testen:

statt
<msg source="System">ready</msg> 
sende mal 
<msg source="System">ready</msg>\nzweite Zeile,
dann müsste hoffentlich zwischen den beiden 
möglichen in.readLine() ready auf true sein? 

das der nächste Aufruf dann blockiert, das ist vorgesehen,
das ist so normal?!

ich weiß nicht genau wie lange, evtl. ewig (bis zum Ende der Verbindung),
bei dir vielleicht Timeout nach einiger Zeit?

was sind die vielen null danach, gehts dann schnell?
liegt das vielleicht daran dass die Verbindung dann geschlossen ist?


----------



## JROppenheimer (10. Nov 2006)

das problem ist ja, ich bekomm ide antwort <msg .. so vom host geschickt. ich schicke mir das net selbst.

aber kanns daran liegen, dass ready() erst true ist, sobald der einen zeilenumbruch findet?


----------



## SlaterB (10. Nov 2006)

Zeilenumbruch sagte ich nur weil du ja readline benutzt,
damit hat das nix zu tun, sondern es ist allein die Frage, ob ein folgender read-Aufruf was liest,
ob irgendein (mindestens ein) Byte da ist,

(edit: da du also keinen Zeilenumbruch einfügen kannst, benutze read() statt readLine(), evtl direkt auf dem Stream, 
lies also mal die Nachricht in Teilen ein, dann müsste ready() zwischendurch hoffentlich true sein)

wenn es nicht da ist, sondern der Server es erst schicken muss oder die Nachricht unterwegs ist, 
dann liefert zum einen ready() false,
zum anderen blockieren die read()-Aufrufe bis endlich was da ist,

klingt eigentlich logisch


----------



## JROppenheimer (12. Nov 2006)

also ich versuch das noch mal anders zu beschreiben, was ich da mache.

das ganze läuft in einem Thread. der sieht so aus:


```
public void run() {
		while(true){
			try {
				Thread.sleep(10);
				if (connected){
					if (toSend.length() != 0) {
						out.print(toSend); out.flush();
						toSend.setLength(0);
						actor.networkEvent();
					}
					processPossibleXMLInput();
				}
			}
			catch (InterruptedException e) {
				return;
			}
		}
	}
```



```
processPossibleXMLInput();
```

sieht so aus:


```
private void processPossibleXMLInput()
	{
		
		System.out.println("processPossibleXMLInput()");
	
		try {
			System.out.println(in.readLine());
		} catch (IOException e) {
			// TODO Automatisch erstellter Catch-Block
			e.printStackTrace();
		}
}
```

das problem ist jetzt, wenn der thread das erste mal läuft, gibt es irgenwo einen punkt, wo er mehrere Seunden hängt, bevor er weiter läuft. Wenn der thread das erste mal durchläuft, dann gehts. Dann macht der auch diese Sekundenpause nicht mehr. Aber beim ERSTEN durchlauf, gibts irgendwo ne Pause ... und ich weiss net, warum das passiert.

wenn ich in run() diese process-methode auskommentiere gehts....


----------



## Murray (13. Nov 2006)

Wenn eine Operation beim ersten Mal deutlich länger läuft als bei den nachfolgenden Aufrufen, dann liegt das häufig daran, dass irgendwelche Klassen geladen (und initialisiert) werden müssen, die die VM bisher nicht benötigt hat. Ausserdem wird vielfach das Konzept der "lazy initialization" realisiert, bei dem Resourcen, deren Erzeugung einigen Aufwand erfordern (z.B. Datenbankverbindungen) erst in dem Moment erzeugt werden, in dem sie das erste Mal gebraucht werden.
Ausserdem können auch Dateioperationen ähnliche Effekte hervorrufen: das Lesen einer Datei dauert beim ersten Mal i.d.R. erheblich länger als beim zweiten Mal, da hier diverse Caching-Mechanismen ins Spiel kommen.

Woran es im konkreten Fall liegt, ist nicht immer ganz einfach zu sehen. Wenn Du die VM mit der Option -verbose startest, siehst Du eventuell, ob an dieser Stelle viele Klassen nachgeladen werden.


----------

