如何处理大量的字节数组
How to deal with huge amount of byte arrays
所以我从 USB 设备接收字节数组(一些日志消息),我遇到了一个问题,我不知道解析或读取它们的最佳方法是什么...
这是接收者:
static class ReceiveLogsThread implements Runnable {
private static final String TAG = "IoTReceiveLogsThread";
Message msgRead;
ReceiveLogsThread() {
}
public void run() {
byte[] rbuf = new byte[4096];
while (!Thread.currentThread().isInterrupted()) {
try {
int len = mSerial.readLog(rbuf, mSerialPortLog);
if (len > 0) {
// Crashlytics.log(Log.DEBUG, TAG, "ReceiveLogsThread: " + printHex(rbuf));
// this.msgRead = receiveLogsHandler.obtainMessage(HANDLE_READ, printHex(rbuf));
this.msgRead = receiveLogsHandler.obtainMessage(HANDLE_READ, rbuf);
receiveLogsHandler.sendMessage(this.msgRead);
}
} catch (NullPointerException e1) {
e1.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
Thread.currentThread().interrupt();
if (!mReadFlag) {
Crashlytics.log(Log.WARN, TAG, "Receive thread finished");
}
}
}
如您所见,printHex() 方法已被注释,因为我认为它导致我因实时解析而丢失了一些消息,正如您从它的实现中看到的那样
private static String printHex(byte[] bytes) {
Formatter formatter = new Formatter();
for (byte b : bytes) {
formatter.format("%02x", b);
}
String hex = formatter.toString();
return hex;
}
我不认为一收到字节数组就执行 printHex 方法是个好主意,因为字节来得太快了,所以我想尝试另一种方法..
我想将它们作为字节数组发送,然后在完成所有操作后解析它们,所以我不确定如何正确实现它...
这是来自我的 activity 的接收处理程序,我将这些数组存储到可能包含 30000 个字节数组的字节数组列表中:
private List<byte[]> logs = new ArrayList<>();
Handler receiveLogsHandler = new Handler(Looper.getMainLooper()) {
public void handleMessage(Message msgRW) {
super.handleMessage(msgRW);
// logMessagesList.add(msgRW.obj.toString().toUpperCase());
// String message = msgRW.obj.toString().toUpperCase();
if(shouldCollectLogs) {
byte[] message = (byte[]) msgRW.obj;
logs.add(message);
}
....
所以我在这里面临的问题是,如何将所有这些字节数组合并为一个!然后在那个大数组上执行 printHex..
好的,这里有两种方法可以在最后处理字节数组的最终列表,具体取决于您的需要。
备选方案 1:收集到字符串列表
List<String> hexStrings = listOfBytes.parallelStream() //Process in paralell each byte array
.map(bytes -> printHex(bytes)) // Map each byte array from byte[] to String
.collect(Collectors.toList());// Collect the streams into one final list
备选方案 2:收集到一个字符串
String oneBigStringOfBytesInHex = listOfBytes.parallelStream() //Process in paralell each byte array
.map(bytes -> printHex(bytes)) // Map each byte array from byte[] to String
.collect(Collectors.joining()); // Concat the streams into one final String
你应该小心第二种选择,你必须考虑到字符串的最大大小是 2147483647 (2^31 - 1)。无论如何,如果您的最终数据量是 30.000 字节数组的列表,每个数组 4096 字节,您应该没有任何问题。
您的 printToHex 函数应如下所示,传递字节读取计数。我从另一个 post.
复制了一些代码
private final static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String printToHex(byte[] bytes, int len) {
char[] hexChars = new char[len * 2];
for ( int j = 0; j < len; j++ ) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
所以我从 USB 设备接收字节数组(一些日志消息),我遇到了一个问题,我不知道解析或读取它们的最佳方法是什么...
这是接收者:
static class ReceiveLogsThread implements Runnable {
private static final String TAG = "IoTReceiveLogsThread";
Message msgRead;
ReceiveLogsThread() {
}
public void run() {
byte[] rbuf = new byte[4096];
while (!Thread.currentThread().isInterrupted()) {
try {
int len = mSerial.readLog(rbuf, mSerialPortLog);
if (len > 0) {
// Crashlytics.log(Log.DEBUG, TAG, "ReceiveLogsThread: " + printHex(rbuf));
// this.msgRead = receiveLogsHandler.obtainMessage(HANDLE_READ, printHex(rbuf));
this.msgRead = receiveLogsHandler.obtainMessage(HANDLE_READ, rbuf);
receiveLogsHandler.sendMessage(this.msgRead);
}
} catch (NullPointerException e1) {
e1.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
Thread.currentThread().interrupt();
if (!mReadFlag) {
Crashlytics.log(Log.WARN, TAG, "Receive thread finished");
}
}
}
如您所见,printHex() 方法已被注释,因为我认为它导致我因实时解析而丢失了一些消息,正如您从它的实现中看到的那样
private static String printHex(byte[] bytes) {
Formatter formatter = new Formatter();
for (byte b : bytes) {
formatter.format("%02x", b);
}
String hex = formatter.toString();
return hex;
}
我不认为一收到字节数组就执行 printHex 方法是个好主意,因为字节来得太快了,所以我想尝试另一种方法..
我想将它们作为字节数组发送,然后在完成所有操作后解析它们,所以我不确定如何正确实现它...
这是来自我的 activity 的接收处理程序,我将这些数组存储到可能包含 30000 个字节数组的字节数组列表中:
private List<byte[]> logs = new ArrayList<>();
Handler receiveLogsHandler = new Handler(Looper.getMainLooper()) {
public void handleMessage(Message msgRW) {
super.handleMessage(msgRW);
// logMessagesList.add(msgRW.obj.toString().toUpperCase());
// String message = msgRW.obj.toString().toUpperCase();
if(shouldCollectLogs) {
byte[] message = (byte[]) msgRW.obj;
logs.add(message);
}
....
所以我在这里面临的问题是,如何将所有这些字节数组合并为一个!然后在那个大数组上执行 printHex..
好的,这里有两种方法可以在最后处理字节数组的最终列表,具体取决于您的需要。
备选方案 1:收集到字符串列表
List<String> hexStrings = listOfBytes.parallelStream() //Process in paralell each byte array
.map(bytes -> printHex(bytes)) // Map each byte array from byte[] to String
.collect(Collectors.toList());// Collect the streams into one final list
备选方案 2:收集到一个字符串
String oneBigStringOfBytesInHex = listOfBytes.parallelStream() //Process in paralell each byte array
.map(bytes -> printHex(bytes)) // Map each byte array from byte[] to String
.collect(Collectors.joining()); // Concat the streams into one final String
你应该小心第二种选择,你必须考虑到字符串的最大大小是 2147483647 (2^31 - 1)。无论如何,如果您的最终数据量是 30.000 字节数组的列表,每个数组 4096 字节,您应该没有任何问题。
您的 printToHex 函数应如下所示,传递字节读取计数。我从另一个 post.
复制了一些代码private final static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String printToHex(byte[] bytes, int len) {
char[] hexChars = new char[len * 2];
for ( int j = 0; j < len; j++ ) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}