Question

We use this small utility method. But we don't like it. Since it's not very crucial (it works anyway ... ) , we have forgotten it.
But that's ugly, because we have to go through the whole array, only to convert it from Byte[] to byte[].
I'm looking :

  • for a way to cast the Byte[] in byte[] without going through it
  • or for a utility method for cast a List into string

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);
}
Was it helpful?

Solution

Your method is pretty much the only way to do it. You may find an external library that does all or part of it, but it will essentially do the same thing.

However, there is one thing in your code that is a potential problem: When calling new String(array), you are using the platform default encoding to convert the bytes to characters. The platform encoding differs between operating system and locale settings - using it is almost always a bug waiting to happen. It depends on where you're getting those bytes from, but their encoding should be specified somewhere, passed as argument to the method and used for the conversion (by using the String constructor with a second parameter).

OTHER TIPS

import org.apache.commons.lang.ArrayUtils;

...

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

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

without any additional library (e.g. apache commons) your method is fine

Minor nit:

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

to avoid creating empty Strings for empty lists.

Guava provides a number of useful primitive utilities, including a Bytes class which makes this and other operations on collections of Bytes trivial.

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

You could use java.nio and come up with something like this

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();
}

but I really don't think I'd recommend for something this simple.

One option might be to use 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();
}

Or, if you need character conversion

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");
}

If you are aggregating bytes, try ByteArrayOutputStream in the first place instead of List of bytes. Note: Watch out for the UnsupportedEncodingException - you'll need to try-catch it somewhere.

Check out the BitConverter class, I think it does what you want. Use it in combination with the List.toArray() method.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top