输入流问题
Input Stream Issue
卡在一期中,
我正在使用 BluetoothSocket
class,我在输入和输出流的帮助下发送和接收数据。
当 App 从输入流接收到大量数据时,我正在强行杀死我的应用程序,然后我再次重新启动我的应用程序,但是 InputStream
returns 我以前的数据,这不是需要 anymore.how 丢弃旧数据?
有人解决这个问题吗?
以下是我的源代码:
public class MyBluetoothService {
private static final String TAG = "MY_APP_DEBUG_TAG";
private Handler mHandler; // handler that gets info from Bluetooth service
// Defines several constants used when transmitting messages between the
// service and the UI.
private interface MessageConstants {
public static final int MESSAGE_READ = 0;
public static final int MESSAGE_WRITE = 1;
public static final int MESSAGE_TOAST = 2;
// ... (Add other message types here as needed.)
}
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private byte[] mmBuffer; // mmBuffer store for the stream
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams; using temp objects because
// member streams are final.
try {
tmpIn = socket.getInputStream();
} catch (IOException e) {
Log.e(TAG, "Error occurred when creating input stream", e);
}
try {
tmpOut = socket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "Error occurred when creating output stream", e);
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
mmBuffer = new byte[1024];
int numBytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs.
while (true) {
try {
// Read from the InputStream.
numBytes = mmInStream.read(mmBuffer);
// Send the obtained bytes to the UI activity.
Message readMsg = mHandler.obtainMessage(
MessageConstants.MESSAGE_READ, numBytes, -1,
mmBuffer);
readMsg.sendToTarget();
} catch (IOException e) {
Log.d(TAG, "Input stream was disconnected", e);
break;
}
}
}
// Call this from the main activity to send data to the remote device.
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
// Share the sent message with the UI activity.
Message writtenMsg = mHandler.obtainMessage(
MessageConstants.MESSAGE_WRITE, -1, -1, mmBuffer);
writtenMsg.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "Error occurred when sending data", e);
// Send a failure message back to the activity.
Message writeErrorMsg =
mHandler.obtainMessage(MessageConstants.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString("toast",
"Couldn't send data to the other device");
writeErrorMsg.setData(bundle);
mHandler.sendMessage(writeErrorMsg);
}
}
// Call this method from the main activity to shut down the connection.
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "Could not close the connect socket", e);
}
}
}
}
我认为你应该关闭套接字来管理这个错误。
我建议您像下面的代码一样在终结器中执行此操作。
private class ConnectedThread extends Thread
{
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private byte[] mmBuffer; // mmBuffer store for the stream
@override
protected void finalize() throws Throwable
{
try
{
cancel();
}
finally
{
super.finalize();
}
}
...
另外正如我在评论中提到的,在关闭套接字之前每隔 stream
秒关闭一次会更安全。
所以,试试这个 cancel()
方法。
// Call this method from the main activity to shut down the connection.
public void cancel()
{
try {
mmInStream.close();
} catch( NullPointerException | IOException e) {}
try {
mmOutStream.close();
} catch( NullPointerException | IOException e) {}
try
{
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "Could not close the connect socket", e);
}
}
和more information关于finalize
方法。
编辑:粗体比其他建议更重要。
阅读 EJP 的评论我理解了为什么您的应用程序在您获取大量数据时停止:您可能必须在调用 read()
之前清除缓冲区。他说终结器可能恰好没有被系统调用(我不知道为什么)。
break
当read()
返回-1
?
刚才我发现了一个有用的 link 关于读取流的正确方法。希望对您有所帮助。
代码引用自link
private String extract(InputStream inputStream) throws IOException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int read = 0;
while ((read = inputStream.read(buffer, 0, buffer.length)) != -1) {
baos.write(buffer, 0, read);
}
baos.flush();
return new String(baos.toByteArray(), "UTF-8");
}
还有
虽然 finalizer
可能无法通过系统关闭 streams
在关闭之前调用 sockets
更安全(我之前阅读过一些 SO 线程)。
// Keep listening to the InputStream until an exception occurs
问题就在这里。您应该继续从流中读取数据,直到 流结束或 发生异常。如果 read()
returns -1.
,则需要跳出读取循环
目前您正在读取超出流的末尾,并且完全忽略了条件,因此上次成功读取时缓冲区中的数据当然仍然存在。
为了让您的应用程序保持看到该数据,您还必须忽略读取计数并假设缓冲区已满,这也是无效的。
卡在一期中,
我正在使用 BluetoothSocket
class,我在输入和输出流的帮助下发送和接收数据。
当 App 从输入流接收到大量数据时,我正在强行杀死我的应用程序,然后我再次重新启动我的应用程序,但是 InputStream
returns 我以前的数据,这不是需要 anymore.how 丢弃旧数据?
有人解决这个问题吗?
以下是我的源代码:
public class MyBluetoothService {
private static final String TAG = "MY_APP_DEBUG_TAG";
private Handler mHandler; // handler that gets info from Bluetooth service
// Defines several constants used when transmitting messages between the
// service and the UI.
private interface MessageConstants {
public static final int MESSAGE_READ = 0;
public static final int MESSAGE_WRITE = 1;
public static final int MESSAGE_TOAST = 2;
// ... (Add other message types here as needed.)
}
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private byte[] mmBuffer; // mmBuffer store for the stream
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams; using temp objects because
// member streams are final.
try {
tmpIn = socket.getInputStream();
} catch (IOException e) {
Log.e(TAG, "Error occurred when creating input stream", e);
}
try {
tmpOut = socket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "Error occurred when creating output stream", e);
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
mmBuffer = new byte[1024];
int numBytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs.
while (true) {
try {
// Read from the InputStream.
numBytes = mmInStream.read(mmBuffer);
// Send the obtained bytes to the UI activity.
Message readMsg = mHandler.obtainMessage(
MessageConstants.MESSAGE_READ, numBytes, -1,
mmBuffer);
readMsg.sendToTarget();
} catch (IOException e) {
Log.d(TAG, "Input stream was disconnected", e);
break;
}
}
}
// Call this from the main activity to send data to the remote device.
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
// Share the sent message with the UI activity.
Message writtenMsg = mHandler.obtainMessage(
MessageConstants.MESSAGE_WRITE, -1, -1, mmBuffer);
writtenMsg.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "Error occurred when sending data", e);
// Send a failure message back to the activity.
Message writeErrorMsg =
mHandler.obtainMessage(MessageConstants.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString("toast",
"Couldn't send data to the other device");
writeErrorMsg.setData(bundle);
mHandler.sendMessage(writeErrorMsg);
}
}
// Call this method from the main activity to shut down the connection.
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "Could not close the connect socket", e);
}
}
}
}
我认为你应该关闭套接字来管理这个错误。
我建议您像下面的代码一样在终结器中执行此操作。
private class ConnectedThread extends Thread
{
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private byte[] mmBuffer; // mmBuffer store for the stream
@override
protected void finalize() throws Throwable
{
try
{
cancel();
}
finally
{
super.finalize();
}
}
...
另外正如我在评论中提到的,在关闭套接字之前每隔 stream
秒关闭一次会更安全。
所以,试试这个 cancel()
方法。
// Call this method from the main activity to shut down the connection.
public void cancel()
{
try {
mmInStream.close();
} catch( NullPointerException | IOException e) {}
try {
mmOutStream.close();
} catch( NullPointerException | IOException e) {}
try
{
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "Could not close the connect socket", e);
}
}
和more information关于finalize
方法。
编辑:粗体比其他建议更重要。
阅读 EJP 的评论我理解了为什么您的应用程序在您获取大量数据时停止:您可能必须在调用 read()
之前清除缓冲区。他说终结器可能恰好没有被系统调用(我不知道为什么)。
break
当read()
返回-1
?
刚才我发现了一个有用的 link 关于读取流的正确方法。希望对您有所帮助。
代码引用自link
private String extract(InputStream inputStream) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int read = 0; while ((read = inputStream.read(buffer, 0, buffer.length)) != -1) { baos.write(buffer, 0, read); } baos.flush(); return new String(baos.toByteArray(), "UTF-8"); }
还有
虽然 finalizer
可能无法通过系统关闭 streams
在关闭之前调用 sockets
更安全(我之前阅读过一些 SO 线程)。
// Keep listening to the InputStream until an exception occurs
问题就在这里。您应该继续从流中读取数据,直到 流结束或 发生异常。如果 read()
returns -1.
目前您正在读取超出流的末尾,并且完全忽略了条件,因此上次成功读取时缓冲区中的数据当然仍然存在。
为了让您的应用程序保持看到该数据,您还必须忽略读取计数并假设缓冲区已满,这也是无效的。