3

How can I replace a subarray of a byte array?

I need something similar with replace method for strings:

"I want pizza".replace("pizza", "replace method for byte arrays")

but it should work for byte[].

7
  • what kind of data is in the byte array you are handling? Commented Apr 21, 2020 at 16:21
  • one possibility would be to wrap the bytes in a input stream and then do as suggested in this answer: stackoverflow.com/questions/7743534/… Commented Apr 21, 2020 at 16:24
  • @Renato it's binary data from image files Commented Apr 21, 2020 at 16:43
  • 1
    A dirty trick you could try would be to simply do new String(bytes) and pray it will work, then use String's replace() with Strings built in the same way, then get back your bytes with str.getBytes(). But with an image file, I think you will run into illegal byte sequences for pretty much any String encoding, so that's likely unsafe. Commented Apr 21, 2020 at 17:35
  • 1
    @Renato if you use an encoding such as ISO_8859_1 which has a one-to-one mapping between a byte and a char, then you can do that. Yes, ugly. Commented Apr 21, 2020 at 18:18

2 Answers 2

3

Assuming you want to replace an n-byte subarray with another n-byte subarray, you can use System.arraycopy.

For example:

System.arraycopy(theNewBytes, startPosition,
                 theArrayYouWantToUpdate, startPosition1, length);

If you want to replace n bytes with some different number of bytes, you would need to create a new array anyway:

  • Create the new array with the desired length (prefix length + new portion length + suffix length)
  • Copy the prefix from the existing array, using arrayCopy
  • Copy the new portion
  • Copy the suffix from the existing array.
Sign up to request clarification or add additional context in comments.

2 Comments

I do not have the replaced subarray location (the startPosition).
Minor correction it's arraycopy (just in case a beginner uses this and has an issue with arrayCopy not being found).
-1

It is possible to use the power of the almighty String to do this :)

static byte[] replace(byte[] src, byte[] find, byte[] replace) {
    String replaced = cutBrackets(Arrays.toString(src))
            .replace(cutBrackets(Arrays.toString(find)), cutBrackets(Arrays.toString(replace)));

    return Arrays.stream(replaced.split(", "))
            .map(Byte::valueOf)
            .collect(toByteArray());
}

private static String cutBrackets(String s) {
    return s.substring(1, s.length() - 1);
}

private static Collector<Byte, ?, byte[]> toByteArray() {
    return Collector.of(ByteArrayOutputStream::new, ByteArrayOutputStream::write, (baos1, baos2) -> {
        try {
            baos2.writeTo(baos1);
            return baos1;
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }, ByteArrayOutputStream::toByteArray);
}

Using custom Collector.toByteArray from this answer

Test results:

byte[] arr = {10, 20, 30, 40, 50, 51, 52, 53, 54, 62, 63};
byte[] find = {10, 20, 30};
byte[] replace = {21, 22, 23, 31, 32, 33};

System.out.println(Arrays.toString(replace(arr, find, replace)));

Output:

[21, 22, 23, 31, 32, 33, 40, 50, 51, 52, 53, 54, 62, 63]

5 Comments

Why are you using Strings here? Will the conversion from bytes work?
I did it just for fun to check if this could be implemented. Yes, conversion of bytes array with Arrays.toString() works fine
This is a rather expensive way of doing it: not only is this converting to a string (taking a lot more memory than the original), it's also using regex, because String.replace actually invokes replaceAll, after quoting its arguments. You can reasonably easily implement an indexOf method that finds the start position of a subarray in another array (fancy algorithms exist, but String.indexOf is actually naive); then use System.arrayCopy.
@AndyTurner I was and am aware of all those overheads :) The point was to reuse as much of existing String functionality as possible. Sorry if it was not that funny.
@AlexRudenko the point isn't necessarily that you need to be made aware of them, but readers of your answer do.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.