Как получить побайтово из байтового массива
Я получаю ответ от сервера в формате строки, как
V1YYZZ0x0000010x0D0x00112050x0C152031962061900x0D410240x0E152031962061900x0F410240x1021TATADOCOMOINTERNET101
Затем я конвертирую его в байтовый массив, потому что мне нужно получить значение из этого байта за байтом.
Я пытался использовать
Arrays.copyOfRange(original,
from , to);
но это работает на основе индекса, а не на основе байтов.
Я также попробовал следующее решение, но оно также усекает строку (если я использую строку вместо байта []) на основе длины.
public static String truncateWhenUTF8(String s, int maxBytes) {
int b = 0;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
// ranges from http://en.wikipedia.org/wiki/UTF-8
int skip = 0;
int more;
if (c <= 0x007f) {
more = 1;
} else if (c <= 0x07FF) {
more = 2;
} else if (c <= 0xd7ff) {
more = 3;
} else if (c <= 0xDFFF) {
// surrogate area, consume next char as well
more = 4;
skip = 1;
} else {
more = 3;
}
if (b + more > maxBytes) {
return s.substring(0, i);
}
b += more;
i += skip;
}
return s;
}
Я знаю, как рассчитать строку в байтовой длине, но она дает только полную длину строки в байтах, как
Вот как мне нужно извлечь пакет на байтовой основе.
Выше коды и параметры является лишь примером. Мне нужно получить побайтово из строки / байтового массива.
Я искал много, но не нашел ни решения, ни ссылки, на которую мог бы сослаться. Я не понимаю, как разделить строку, используя длину в байтах, потому что я знаю длину в байтах для каждого параметра, а также для значения.
Пожалуйста, дайте мне любую ссылку или подсказку.
4 ответа
Определить, что равно одному байту в строке, нетривиально. Ваша строка содержит байты в шестнадцатеричном текстовом виде: 0x0D
(один байт, равный 13), но также содержит значения в качестве подстрок. Например 1024
может интерпретироваться как целое число, которое в этом случае умещается в 2 байта, но также может интерпретироваться как текст, состоящий из 4 символов, что в сумме составляет 8 байтов.
В любом случае, я бы разделил строку с помощью регулярного выражения, а затем разделил бы части на длину и значение:
String message = "V1YYZZ0x0000010x0D0x00112050x0C152031962061900x0D41024"+
"0x0E152031962061900x0F410240x1021TATADOCOMOINTERNET101";
String regex = "(0)(x)(\\w\\w)";
String[] parts = message.split(regex);
Log.d(TAG,"HEADER = "+parts[0]);
for (int i=1; i<parts.length; i++) {
String s = parts[i];
// Only process if it has length > 0
if (s.length()>0) {
String len = "", val = "";
// String s is now in format LVVVV where L is the length, V is the value
if (s.length() < 11) {
// 1 character indicates length, up to 9 contains value
len = s.substring(0, 1);
val = s.substring(1);
} else if (s.length() > 10) {
// 2 characters indicate length, up to 99 contains value
len = s.substring(0, 2);
val = s.substring(2);
} else if (s.length() > 101) {
// 3 characters indicate length, up to 999 contains value
len = s.substring(0, 3);
val = s.substring(3);
}
Log.d(TAG, "Length: " + len + " Value: " + val);
}
}
Это дает следующий вывод:
D/Activity: HEADER = V1YYZZ
D/Activity: Length: 0 Value: 001
D/Activity: Length: 1 Value: 1205
D/Activity: Length: 15 Value: 203196206190
D/Activity: Length: 4 Value: 1024
D/Activity: Length: 15 Value: 203196206190
D/Activity: Length: 4 Value: 1024
D/Activity: Length: 21 Value: TATADOCOMOINTERNET101
Затем вы можете проверить пакеты (первые два пакета в заголовке не нужны), конвертировать строки в то, что вы хотите (например, Integer.parseInt(val)
)
Если вы объясните структуру заголовка (V1YYZZ0x0000010x0D0x0011205
), Я могу улучшить свой ответ, чтобы найти количество сообщений.
Это не ответ на доступ к байтовому массиву побайтно, а ответ на ситуацию, в которой вы оказались.
Ваше объяснение и описание выглядят запутанными относительно того, что вы действительно получаете от сервера (например, довольно трудно представить "V1YYZZ0x0000010x0D0x001120" как 9-байтовое поле (обратите внимание, что оно, вероятно, заканчивается на 2, а не на 0)). Кроме того, вы используете неправильный метод для получения его с сервера или не получаете его в качестве предполагаемого типа данных.
Ваш код указывает на то, что вы считаете, что вы получаете строку UTF8. Данные, показанные в вашем вопросе, не указывают на то, что они предназначены для этого формата.
При выполнении чего-то подобного имейте в виду, что какой-то другой программист должен был создать структуру для данных, которые вы видите. Они должны были определить это где-то с намерением, чтобы он мог быть декодирован их предполагаемыми получателями. Если нет других соображений (безопасность, минимальная пропускная способность и т. Д.), Такие форматы обычно определяются так, чтобы их было легко кодировать и декодировать.
Существование нескольких шестнадцатеричных чисел в кодировке "0x"-ASCII- в частности, одного байта, представляющего параметр (называемый "varam" на графике), - в значительной степени подразумевает, что эти данные должны были интерпретироваться как строка в кодировке ASCII. Хотя это может быть и не так, об этом следует помнить, рассматривая проблему в более широкой перспективе.
Вы должны приложить слишком много усилий для расшифровки информации, которую вы получаете с сервера. Это, вероятно, должно быть относительно легко, если только нет соображений, почему это было бы намеренно затруднено.
Все это указывает на то, что настоящая проблема существует в области, для которой вы не предоставили нам никакой информации.
Шаг назад: Подумайте о таких вещах, как: Как вы получаете это от сервера (какая функция / интерфейс)?
В вызове, запрашивающем информацию с сервера, есть ли способ указать тип кодирования: байты, строку ASCII или какой-то другой формат, с которым легче иметь дело, чем с UTF8? Как минимум, очевидно, что данные не предназначались для обработки в виде строки UTF8. Должен быть способ получить его без конвертации в UTF8.
Кроме того, вы должны попытаться найти актуальную спецификацию для формата данных. Вы не очень много объяснили об источнике, так что, возможно, вы что-то перепроектировали и не имеете доступа к спецификациям.
По сути, похоже, что это проблема, когда было бы неплохо сделать шаг назад и спросить, начинаете ли вы с того момента, который облегчает решение, и движетесь ли вы в правильном направлении для этого.
Я думаю, что это выполнимо со сканером
import java.util.Scanner;
public class Library {
public static void main(String[] args) {
String s = "V1YYZZ0x0000010x0D0x001120"
+ "50x0C152031962061900x0D410240x0E152031962061900x0F410240x1"
+ "021TATADOCOMOINTERNET101";
// Skip first 9? bytes. I'm not sure how you define them
// so I just assumed it is 26 chars long.
s = s.substring(26, s.length());
System.out.println(s);
Scanner scanner = new Scanner(s);
// Use byte as delimiter i.e. 0xDC, 0x00
// Maybe you should use smth like 0x[\\da-fA-F]{2}
// And if you want to know that byte, you should use
// just 0x and get first 2 chars later
scanner.useDelimiter("0x\\w{2}");
// Easily extracted
int numberOfParams = scanner.nextInt();
for (int i = 0; i < numberOfParams; i++) {
String extracted = scanner.next();
// Length of message
int l = extracted.length();
boolean c = getLength(l) == getLength(l - getLength(l));
l -= getLength(l);
l = c ? l : l-1;
System.out.println("length="
+ extracted.substring(0, extracted.length()-l));
System.out.println("message="
+ extracted.substring(extracted.length()-l, extracted.length()));
}
// close the scanner
scanner.close();
}
// Counting digits assuming number is decimal
private static int getLength(int l) {
int length = (int) (Math.log10(l) + 1);
System.out.println("counted length = " + length);
return length;
}
}
Нам определенно нужна дополнительная информация о правилах, как формируется строка. И что именно вам нужно сделать. Этот код может быть достаточно хорош для вас. И без комментариев это действительно коротко и просто.
Я уверен, что упускаю что-то очевидное...
String.getBytes();
И если вы хотите обработать его по порядку, взяв определенные объекты из массива, просто оберните
ByteBuffer.wrap();
В результате получается что-то вроде:
String s = "OUTPUT FROM SERVER";
byte[] bytes = s.getBytes();
ByteBuffer bb = ByteBuffer.wrap(bytes);
Что я упустил из первоначального вопроса?:/