[英]Why can I read with a BufferedReader in Java without Eventlistener
[英]How can I read from a BufferedReader in Java without blocking?
我想向服務器發送命令,並查看是否收到響應。
現在我正在使用BufferedReader
的readline()
函數,它會阻塞直到有來自服務器的響應,但我想要做的就是首先驗證是否有來自服務器的響應。
我嘗試使用ready()
或reset()
來避免此塊,但無濟於事。
這導致我的程序卡住等待服務器響應,這從未發生過。 InputStreamReader
似乎做同樣的事情,根據我的理解。
我在這里找到的關於這個主題的其他問題沒有回答我的問題,所以如果你能回答我的問題,那就太好了。
如果您想異步讀取響應,我建議啟動一個讀取 BufferedReader 的線程。 這更易於編碼且更易於控制。
您可能只需要InputStream
而不將其包裝在BufferedReader
while (inputStream.available() > 0) {
int i = inputStream.read(tmp, 0, 1024);
if (i < 0)
break;
strBuff.append(new String(tmp, 0, i));
}
我希望這有幫助。
我最近使用 CountDownLatch 做了類似的事情。 可能有一些更好的方法,但這很容易,而且似乎工作得相當好。 您可以調整 CountDownLatch 的等待時間以滿足您的需要。
package com.whatever;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TestRead {
private static final Logger log = LoggerFactory.getLogger(TestRead.class);
private CountDownLatch latch = new CountDownLatch(1);
public void read() {
URLReader urlReader = new URLReader();
Thread listener = new Thread(urlReader);
listener.setDaemon(true);
listener.start();
boolean success = false;
try {
success = latch.await(20000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
log.error("error", e);
}
log.info("success: {}", success);
}
class URLReader implements Runnable {
public void run() {
log.info("run...");
try {
URL oracle = new URL("http://www.oracle.com/");
URLConnection yc = oracle.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
latch.countDown();
} catch (Exception ex) {
log.error("error", ex);
}
log.info("consumer is done");
}
}
public static void main(String[] args) {
TestRead testRead = new TestRead();
testRead.read();
}
}
如果您使用標准的 Java IO,那么不會阻塞是一項棘手的任務。 常見的答案是遷移到 NIO 或 netty。 Netty 是更可取的選擇。 但是,有時您別無選擇,因此我建議您嘗試我的解決方法:
public String readResponse(InputStream inStreamFromServer, int timeout) throws Exception {
BufferedReader reader = new BufferedReader(new InputStreamReader(inStreamFromServer, Charsets.UTF_8));
char[] buffer = new char[8092];
boolean timeoutNotExceeded;
StringBuilder result = new StringBuilder();
final long startTime = System.nanoTime();
while ((timeoutNotExceeded = (TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) < timeout))) {
if (reader.ready()) {
int charsRead = reader.read(buffer);
if (charsRead == -1) {
break;
}
result.append(buffer, 0, charsRead);
} else {
try {
Thread.sleep(timeout / 200);
} catch (InterruptedException ex) {
LOG.error("InterruptedException ex=", ex);
}
}
}
if (!timeoutNotExceeded) throw new SocketTimeoutException("Command timeout limit was exceeded: " + timeout);
return result.toString();
}
此解決方法不是靈丹妙葯,但它具有一些重要功能:
LF/CR
符號並且您的代碼將被卡住。 當您從文件中讀取時,無論如何您都會到達文件的末尾並不重要。char symbol = (char) fr.read();
. 這種方法比讀取 char[] 慢
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.