Java: удалите continious сегмент нулей от массива байтов

UML кажется пользе для крупных проектов с многочисленными командами людей. Однако я работал в малочисленных командах, где коммуникация лучше.

Используя схемы UML-esque хорошо хотя, особенно в перспективном проектировании. Я склонен думать в коде, таким образом, я нахожу пишущие большие спецификации трудно. Я предпочитаю записывать вводы и выводы и оставлять разработчиков для разработки бита в середине.

5
задан try-catch-finally 30 July 2017 в 11:05
поделиться

7 ответов

регулярное выражение не является инструментом для работы, вместо этого вам нужно будет реализовать его с нуля

1
ответ дан 18 December 2019 в 05:26
поделиться
byte[] a = {1,2,3,0,1,2,3,0,0,0,0,4};
String s0 = new String(a, "ISO-8859-1");
String s1 = s0.replaceAll("\\x00{4,}", "");
byte[] r = s1.getBytes("ISO-8859-1");

System.out.println(Arrays.toString(r)); // [1, 2, 3, 0, 1, 2, 3, 4]

Я использовал ISO-8859-1 (latin1), потому что, в отличие от любой другой кодировки,

  • каждый байт в диапазоне 0x00..0xFF отображается на допустимый символ, а

  • каждый из эти символы имеют то же числовое значение, что и его кодировка latin1.

Это означает, что строка имеет ту же длину, что и исходный массив байтов, вы можете сопоставить любой байт по его числовому значению с помощью конструкции \ xFF , и вы можете преобразовать полученную строку обратно в массив байтов без потери информации.

Я бы не стал пытаться отображать данные в строковой форме - хотя все символы действительны, многие из них не печатаются. Также избегайте манипулирования данными, пока они находятся в строковой форме; вы можете случайно выполнить некоторые замены escape-последовательности или другое преобразование кодировки, не осознавая этого. На самом деле, я бы не стал t рекомендуют вообще делать такие вещи, но вы не об этом просили. :)

Также имейте в виду, что этот метод не обязательно будет работать на других языках программирования или разновидностях регулярных выражений. Вам придется протестировать каждую отдельно.

26
ответ дан 18 December 2019 в 05:26
поделиться

Я не понимаю, как регулярное выражение будет будь полезным делать то, что хочешь. Единственное, что вы можете сделать, это использовать Run Length Encoding для кодирования этого массива байтов, заменять каждое вхождение «30» (чтение трех нулей) пустой строкой и декодировать последнюю строку. В Википедии есть простая реализация на Java.

1
ответ дан 18 December 2019 в 05:26
поделиться

Хотя я сомневаюсь, что reg-ex является подходящим инструментом для работы, если вы действительно хотите его использовать, я бы посоветовал вам просто реализовать оболочку CharSequence для байтового массива. Что-то вроде этого (я просто написал это прямо, а не скомпилировал ... но вы поняли идею).

public class ByteChars 
implements CharSequence

...

ByteChars(byte[] arr) {
    this(arr,0,arr.length);
    }

ByteChars(byte[] arr, int str, int end) {
    //check str and end are within range here
    strOfs=str;
    endOfs=end;
    bytes=arr;
    }

public char charAt(int idx) { 
    //check idx is within range here
    return (char)(bytes[strOfs+idx]&0xFF); 
    }

public int length() { 
    return (endOfs-strOfs); 
    }

public CharSequence subSequence(int str, int end) { 
    //check str and end are within range here
    return new ByteChars(arr,(strOfs+str,strOfs+end); 
    }

public String toString() { 
    return new String(bytes,strOfs,(endOfs-strOfs),"ISO8859_1");
    }
8
ответ дан 18 December 2019 в 05:26
поделиться

Я бы предложил преобразовать массив байтов в строку, выполнить регулярное выражение, а затем преобразовать его обратно. Вот рабочий пример:

public void testRegex() throws Exception {
    byte a[] = { 1, 2, 3, 0, 1, 2, 3, 0, 0, 0, 0, 4 };
    String s = btoa(a);
    String t = s.replaceAll("\u0000{4,}", "");
    byte b[] = atob(t);
    System.out.println(Arrays.toString(b));
}

private byte[] atob(String t) {
    char[] array = t.toCharArray();
    byte[] b = new byte[array.length];
    for (int i = 0; i < array.length; i++) {
        b[i] = (byte) Character.toCodePoint('\u0000', array[i]);
    }
    return b;
}

private String btoa(byte[] a) {
    StringBuilder sb = new StringBuilder();
    for (byte b : a) {
        sb.append(Character.toChars(b));
    }
    return sb.toString();
}

Для более сложных преобразований я бы предложил использовать лексер. И JavaCC, и ANTLR поддерживают синтаксический анализ / преобразование двоичных файлов.

0
ответ дан 18 December 2019 в 05:26
поделиться

Java Regex работает с CharSequences - вы можете CharBuffer обернуть существующий массив байтов (вам может потребоваться преобразовать его в char []?) И интерпретировать его как таковой, а затем выполнить на нем регулярное выражение?

-1
ответ дан 18 December 2019 в 05:26
поделиться

Несмотря на то, что существует разумная библиотека ByteString , никто из тех, кого я видел, не реализовал на них общую библиотеку регулярных выражений.

Я рекомендую решить вашу проблему напрямую чем реализация библиотеки регулярных выражений :)

Если вы все-таки конвертируете в строку и обратно, вы, вероятно, не найдете никакой существующей кодировки, которая дает вам круговой обход для ваших 0 байтов. В этом случае вам придется написать свой собственный массив байтов <-> преобразователи строк; не стоит проблем.

1
ответ дан 18 December 2019 в 05:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: