javaspringspring-bootoutputstreambytearrayoutputstream

Conversion of ByteArrayInputStream.toString results in warning Inefficient conversion from ByteArrayOutputStream


I have a Spring Boot application that converts the XML to JSON. The conversion is done by calling another JAVA application internally and passing some information. The implementation of the called application is out of my control and I do not have access to make any changes to it.

The called Java Application requires a OutputStream so I am using the ByteArrayOutputStream and passing it within the method. After receiving the output I am converting the OutputStream to String. During the conversion, I am running into the warning Inefficient conversion from ByteArrayOutputStream.

I wanted to know how can I fix this warning. I researched a bit and found that we need to pass the size of ByteArrayOutputStream but in my case I am not aware how much size it can have because it would depend on the size of the input XML that I am giving. So I am unable to predict it and set it.

Can someone please guide me on what I can do within my Spring Boot application ByteArrayOutputStream so as to fix the warning that I receive in my Intellij IDE: Inefficient conversion from ByteArrayOutputStream

Following is my code sample:

final InputStream inputStream = new ByteArrayInputStream(xmlEvents.getBytes(StandardCharsets.UTF_8));
final var output = new ByteArrayOutputStream();
new Converter().convert(inputStream, new Handler<>(new Validator(), new StreamCollector(output)));
return new String(output.toByteArray());

I am getting the warning for the line: new String(output.toByteArray())


Solution

  • The explanation for this warning is that

      new String(output.toByteArray());
    

    creates a byte[] from the contents of the ByteArrayOutputStream, then creates a String from the byte[]. That is doing an unnecessary copy of the data.

    The fix1 suggested by Intellij is:

     output.toString(StandardCharsets.UTF_8).
    

    which creates the String in a single operation without creating an intermediate byte[].

    How does it do this?

    Well toString() is passing the ByteArrayOutputStream's internal byte[] buffer to the String constructor. By contrast, output.toByteArray() is copying the buffer to a new byte[] ... so that the caller cannot interfere with the actual buffer's contents.


    1 - In fact the suggested fix doesn't have identical semantics to your original code. The fix uses a specific character set for (UTF-8) converting the bytes to a string. Your original code uses the platform's default character set. In context, it looks like the fix is more correct than the original ... since the bytes seem to have started out as UTF-8. However I guess that the converter could be mapping the bytes from one encoding to another behind the scenes.