[英]How to keep reading from an InputStream as long as there is something in it (Android/Java)?
我正在使用REST API从硬件键盘获取输入。 我想知道如何在有输入的情况下继续从InputStream
读取内容,然后优雅地停止而不抛出SocketTimoutException
。
我的密码
// Start a new thread for reading the keyboard input
new Thread(new Runnable() {
@Override
public void run() {
InputStream inputStream = null;
try {
// Set byte stream from response body
inputStream = response.body().byteStream();
// I THINK THIS IS THE PROBLEM. WHILE (TRUE) //
while (true) {
// This is where the rest response is read into an array of bytes. I interpret this array below and it seems to work as intended.
final byte[] buffer = new byte[256];
int bytesRead = inputStream.read(buffer, 0, buffer.length);
// This was more for debugging purposes... it never get invoked, as far as I can tell.
if (bytesRead < 0) {
Log.w(TAG, "...Returning. 0 bytes read.");
return;
}
// I'll specify what a response looks like below this code block.
String fullResponse = new String(buffer, StandardCharsets.UTF_8);
Log.v(TAG, "...Full rest response : \n " + fullResponse);
// This processes the response, narrowing down to just the keycode. This works as it's supposed to.
processResponse(fullResponse);
}
} catch (IOException e) {
e.printStackTrace();
Log.v(TAG, "...Problem reading input stream");
} finally {
// Close input stream when I'm done with it.
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}).start();
因此,这是我从其余api得到的响应的示例。 我的processResponse()
方法使用按下的键码(在本例中为34)定位并更新文本视图。 这按预期工作。
...Full rest response :
timeout: 2000000
event: keypress
id: 1492005344
data: {"device":"keyboard","pressedKeycodes":"34 "}
我想知道的是,只要有东西存在,如何继续从InputStream
读取数据,并且在没有收到更多输入而又不抛出SockoutTimeoutException
情况下停止SockoutTimeoutException
。 如果我while(true)
不这样做,则不会出现异常,但它只会读取一个按键。
这是例外:
04-12 15:18:02.467 7585-7810/com.accutime.restpractice W/System.err: java.net.SocketTimeoutException
04-12 15:18:02.469 7585-7810/com.accutime.restpractice W/System.err: at java.net.PlainSocketImpl.read(PlainSocketImpl.java:488)
04-12 15:18:02.470 7585-7810/com.accutime.restpractice W/System.err: at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:37)
04-12 15:18:02.471 7585-7810/com.accutime.restpractice W/System.err: at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:237)
04-12 15:18:02.472 7585-7810/com.accutime.restpractice W/System.err: at okio.Okio$2.read(Okio.java:140)
04-12 15:18:02.473 7585-7810/com.accutime.restpractice W/System.err: at okio.AsyncTimeout$2.read(AsyncTimeout.java:238)
04-12 15:18:02.474 7585-7810/com.accutime.restpractice W/System.err: at okio.RealBufferedSource.request(RealBufferedSource.java:66)
04-12 15:18:02.475 7585-7810/com.accutime.restpractice W/System.err: at okio.RealBufferedSource.require(RealBufferedSource.java:59)
04-12 15:18:02.476 7585-7810/com.accutime.restpractice W/System.err: at okio.RealBufferedSource.readHexadecimalUnsignedLong(RealBufferedSource.java:284)
04-12 15:18:02.477 7585-7810/com.accutime.restpractice W/System.err: at okhttp3.internal.http.Http1xStream$ChunkedSource.readChunkSize(Http1xStream.java:441)
04-12 15:18:02.478 7585-7810/com.accutime.restpractice W/System.err: at okhttp3.internal.http.Http1xStream$ChunkedSource.read(Http1xStream.java:422)
04-12 15:18:02.479 7585-7810/com.accutime.restpractice W/System.err: at okio.RealBufferedSource.read(RealBufferedSource.java:45)
04-12 15:18:02.479 7585-7810/com.accutime.restpractice W/System.err: at okio.ForwardingSource.read(ForwardingSource.java:35)
04-12 15:18:02.480 7585-7810/com.accutime.restpractice W/System.err: at retrofit2.OkHttpCall$ExceptionCatchingRequestBody$1.read(OkHttpCall.java:279)
04-12 15:18:02.481 7585-7810/com.accutime.restpractice W/System.err: at okio.RealBufferedSource$1.read(RealBufferedSource.java:386)
04-12 15:18:02.482 7585-7810/com.accutime.restpractice W/System.err: at com.accutime.restpractice.MainActivity$1$1.run(MainActivity.java:172)
04-12 15:18:02.483 7585-7810/com.accutime.restpractice W/System.err: at java.lang.Thread.run(Thread.java:818)
首先,我将创建一个实用程序类,该实用程序类读取InputStream
并返回已读取内容的byte[]
。 假设在此示例中,实用程序类称为InputOutputStreams
。
我的方法将是:
public static byte[] readFully(InputStream input) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[256];
int totalBytesRead = 0;
int bytesRead = 0;
while (input.read(buffer) > 0) {
baos.write(buffer, 0, bytesRead);
}
return baos.toByteArray();
}
然后,我将删除您拥有的while
循环(以及各种实现),并使用上面实现的实用工具类来检索InputStream
的内容,如下所示:
// Start a new thread for reading the keyboard input
new Thread(new Runnable() {
@Override
public void run() {
InputStream inputStream = null;
try {
// Set byte stream from response body
inputStream = response.body().byteStream();
// I'll specify what a response looks like below this code block.
//THIS IS WHERE I USE THE UTILITY CLASS
String fullResponse = new String(InputOutputStreams.readFully(inputStream), StandardCharsets.UTF_8);
Log.v(TAG, "...Full rest response : \n " + fullResponse);
// This processes the response, narrowing down to just the keycode. This works as it's supposed to.
processResponse(fullResponse);
} catch (IOException e) {
e.printStackTrace();
Log.v(TAG, "...Problem reading input stream");
} finally {
// Close input stream when I'm done with it.
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}).start();
我希望这有帮助...
我想出了解决问题的办法。 问题正文中的代码可以保持不变,但是当我创建改造生成器时,我需要添加一个具有read timeout
和max value
write timeout
的OkHttpClient。
这将导致程序不会因SocketNotFound
异常而SocketNotFound
,并且很高兴会长时间接受输入。
这是我的代码:
// TODO 9 : Set a timeout for the connection // <- I NEEDED TO ADD THIS BLOCK ***
OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
.readTimeout(Integer.MAX_VALUE, TimeUnit.MILLISECONDS)
.writeTimeout(Integer.MAX_VALUE, TimeUnit.MILLISECONDS)
.build();
// TODO 7 : Create retrofit builder
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ClockAPI.ENDPOINT) // Refers to endpoint defined in GithubAPI
.addConverterFactory(GsonConverterFactory.create(gson)) // Refers to gson builder, created
.client(okHttpClient) // <- AND THIS LINE ***
.build();
// TODO 8 : Create REST API through retrofit builder
clockUserAPI = retrofit.create(ClockAPI.class);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.