Список<Byte> что касается String, можете ли вы помочь с рефакторингом этого (небольшого) метода?

StackOverflow https://stackoverflow.com/questions/1096868

  •  11-09-2019
  •  | 
  •  

Вопрос

Мы используем этот небольшой служебный метод.Но нам это не нравится.Поскольку это не очень важно (это все равно работает ...), мы забыли об этом.
Но это некрасиво, потому что мы должны пройти через весь массив, только чтобы преобразовать его из Byte[] Для byte[].
Я ищу :

  • для того, чтобы найти способ разыграть Byte[] в byte[] не проходя через это
  • или для служебного метода для преобразования списка в строку

public static String byteListToString(List<Byte> l, Charset charset) {
    if (l == null) {
        return "";
    }
    byte[] array = new byte[l.size()];
    int i = 0;
    for (Byte current : l) {
        array[i] = current;
        i++;
    }
    return new String(array, charset);
}
Это было полезно?

Решение

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

Однако в вашем коде есть одна вещь, которая является потенциальной проблемой:При вызове new String(array), вы используете кодировку платформы по умолчанию для преобразования байтов в символы.Кодировка платформы отличается в зависимости от настроек операционной системы и локали - ее использование почти всегда сопряжено с ожидающей своего появления ошибкой.Это зависит от того, откуда вы получаете эти байты, но их кодировка должна быть где-то указана, передана в качестве аргумента методу и использована для преобразования (с помощью конструктора String со вторым параметром).

Другие советы

import org.apache.commons.lang.ArrayUtils;

...

Byte[] bytes = new Byte[l.size()];
l.toArray(bytes);

byte[] b =  ArrayUtils.toPrimitive(bytes);

без какой-либо дополнительной библиотеки (например,apache commons) ваш метод в порядке

Незначительная гнида:

if (l == null || l.isEmpty() ) {
    return "" ;
}

чтобы избежать создания пустых строк для пустых списков.

Гуава предоставляет ряд полезных примитивные утилиты, включая Bytes класс, который выполняет эту и другие операции над коллекциями Byteэто тривиально.

private static String toString(List<Byte> bytes) {
  return new String(Bytes.toArray(bytes), StandardCharsets.UTF_8);
}

Вы могли бы использовать java.nio и придумать что-то вроде этого

public static String byteListToString(List<Byte> l, Charset cs)
throws IOException
{
    final int CBUF_SIZE = 8;
    final int BBUF_SIZE = 8;

    CharBuffer cbuf = CharBuffer.allocate(CBUF_SIZE);
    char[] chArr = cbuf.array();
    ByteBuffer bbuf = ByteBuffer.allocate(BBUF_SIZE);
    CharsetDecoder dec = cs.newDecoder();
    StringWriter sw = new StringWriter((int)(l.size() * dec.averageCharsPerByte()));

    Iterator<Byte> itInput = l.iterator();
    int bytesRemaining = l.size();
    boolean finished = false;
    while (! finished)
    {
        // work out how much data we are likely to be able to read
        final int bPos = bbuf.position();
        final int bLim = bbuf.limit();
        int bSize = bLim-bPos;
        bSize = Math.min(bSize, bytesRemaining);
        while ((--bSize >= 0) && itInput.hasNext()) 
        {
            bbuf.put(itInput.next().byteValue());
            --bytesRemaining;
        }
        bbuf.flip();
        final int cStartPos = cbuf.position();
        CoderResult cr = dec.decode(bbuf, cbuf, (bytesRemaining <= 0));
        if (cr.isError()) cr.throwException();
        bbuf.compact();
        finished = (bytesRemaining <= 0) && (cr == CoderResult.UNDERFLOW);
        final int cEndPos = cbuf.position();
        final int cSize = cEndPos - cStartPos;
        sw.write(chArr, cStartPos, cSize);
        cbuf.clear();
    }
    return sw.toString();
}

но я действительно не думаю, что стал бы рекомендовать что-то настолько простое.

Одним из вариантов может быть использование StringBuilder:

public static String byteListToString(List<Byte> l) {
    if (l == null) {
        return "" ;
    }
    StringBuilder sb = new StringBuilder(l.size());

    for (Byte current : l) {
        sb.append((char)current);
    }

    return sb.toString();
}

Или, если вам нужно преобразование символов

public static String byteListToString(List<Byte> l) {
    if (l == null) {
        return "" ;
    }
    ByteArrayOutputStream bout = new ByteArrayOutputStream(l.size());

    for (Byte current : l) {
        bout.write(current);
    }

    return bout.toString("UTF-8");
}

Если вы агрегируете байты, попробуйте ByteArrayOutputStream в первую очередь вместо списка байтов.Примечание:Следите за исключением UnsupportedEncodingException - вам нужно будет попытаться его где-нибудь перехватить.

Посмотрите на Преобразователь битов класс, я думаю, это делает то, что ты хочешь.Используйте его в сочетании с методом List.toArray().

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top