Java: StringBuffer to byte [] without toString

The title says it all. Is there a way to convert from StringBuilder to byte [] without using String in the middle?

The problem is that I control REALLY large strings (millions of characters), and then I have a loop that adds char at the end and receives byte []. The process of converting StringBuffer to String makes this loop very very slow.

Is there any way to do this? Thanks in advance!

+6
source share
6 answers

As already mentioned, you can use the CharBuffer class, but allocating a new CharBuffer will only worsen your problem.

Instead, you can directly wrap your StringBuilder in a CharBuffer, since StringBuilder implements CharSequence:

Charset charset = StandardCharsets.UTF_8; CharsetEncoder encoder = charset.newEncoder(); // No allocation performed, just wraps the StringBuilder. CharBuffer buffer = CharBuffer.wrap(stringBuilder); ByteBuffer bytes = encoder.encode(buffer); 

EDIT: Duarte correctly indicates that the CharsetEncoder.encode method can return a buffer whose back array is larger than the actual data value, its capacity is greater than its limit. You must either read from ByteBuffer, or read the byte array from ByteBuffer, which is guaranteed to have the right size. In the latter case, two copies of bytes in memory cannot be avoided, albeit briefly:

 ByteBuffer byteBuffer = encoder.encode(buffer); byte[] array; int arrayLen = byteBuffer.limit(); if (arrayLen == byteBuffer.capacity()) { array = byteBuffer.array(); } else { // This will place two copies of the byte sequence in memory, // until byteBuffer gets garbage-collected (which should happen // pretty quickly once the reference to it is null'd). array = new byte[arrayLen]; byteBuffer.get(array); } byteBuffer = null; 
+11
source

If you want to replace StringBuilder with something else, another option would be Writer , supported by ByteArrayOutputStream :

 ByteArrayOutputStream bout = new ByteArrayOutputStream(); Writer writer = new OutputStreamWriter(bout); try { writer.write("String A"); writer.write("String B"); } catch (IOException e) { e.printStackTrace(); } System.out.println(bout.toByteArray()); try { writer.write("String C"); } catch (IOException e) { e.printStackTrace(); } System.out.println(bout.toByteArray()); 

As always, your mileage may vary.

+2
source

For starters, you should probably use StringBuilder , since StringBuffer has synchronization overhead that you don't normally need.

Unfortunately, there is no way to go directly to byte s, but you can copy char to an array or iterate from 0 to length() and read each charAt() .

+1
source

Unfortunately, the answers above regarding the ByteBuffer array () method are a bit wrong ... The problem is that the allocated byte [] is likely to be larger than you expected. This way, NULL bytes will be saved, which are hard to undo, since you cannot β€œre-size” arrays in Java.

Here is an article that explains this in more detail: http://worldmodscode.wordpress.com/2012/12/14/the-java-bytebuffer-a-crash-course/

+1
source

What are you trying to accomplish with the "million characters"? Should these logs be processed? Can you read this as bytes and stick with ByteBuffer ? Then you can do:

 buffer.array() 

to get byte[]

Depending on what you are doing, you can also use only char[] or CharBuffer :

 CharBuffer cb = CharBuffer.allocate(4242); cb.put("Depends on what it is you need to do"); ... 

Then you can get char[] as:

 cp.array() 

It is always useful to try, it is fun and proves the essence. The Java REPL is not what we're used to, but hey, there is Clojure to keep the day fluent in Java:

 user=> (import java.nio.CharBuffer) java.nio.CharBuffer user=> (def cb (CharBuffer/allocate 4242)) #'user/cb user=> (-> (.put cb "There Be") (.array)) #<char[] [ C@206564e9 > user=> (-> (.put cb " Dragons") (.array) (String.)) "There Be Dragons" 
0
source

If you need performance, I would not use StringBuilder or create a byte []. Instead, you can gradually write to a stream that will receive data first. If you cannot do this, you can copy data from StringBuilder to Writer, but it is much faster not to create a StringBuilder in the first place.

0
source

Source: https://habr.com/ru/post/956335/


All Articles