【问题标题】:Java byte array replaceJava字节数组替换
【发布时间】:2020-04-21 16:12:40
【问题描述】:

如何替换字节数组的子数组?

我需要与 replace 方法类似的字符串:

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

但它应该适用于byte[]

【问题讨论】:

  • 你正在处理的字节数组中有什么样的数据?
  • 一种可能性是将字节包装在输入流中,然后按照此答案中的建议进行操作:stackoverflow.com/questions/7743534/…
  • @Renato 这是来自图像文件的二进制数据
  • 你可以尝试的一个肮脏的伎俩是简单地做new String(bytes)并祈祷它会起作用,然后使用String的replace()以同样的方式构建字符串,然后用@987654328取回你的字节@。但是对于图像文件,我认为几乎任何字符串编码都会遇到非法字节序列,所以这可能是不安全的。
  • 字节算法与字符算法相同,因此您可以复制 Java 实现并将类型更改为字节:docjar.com/html/api/java/lang/String.java.html

标签: java replace byte


【解决方案1】:

假设你想用另一个n字节子数组替换一个n字节子数组,你可以使用System.arraycopy

例如:

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

如果你想用不同数量的字节替换 n 字节,你需要创建一个新数组:

  • 创建具有所需长度的新数组(前缀长度 + 新部分长度 + 后缀长度)
  • 从现有数组中复制前缀,使用arrayCopy
  • 复制新部分
  • 从现有数组中复制后缀。

【讨论】:

  • 我没有被替换的子数组位置(startPosition)。
  • 小修正它是arraycopy(以防万一初学者使用它并且遇到未找到arrayCopy的问题)。
【解决方案2】:

可以利用万能的字符串的力量来做到这一点:)

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

使用来自this answer 的自定义 Collector.toByteArray

测试结果:

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

输出:

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

【讨论】:

  • 你为什么在这里使用字符串?从字节转换会起作用吗?
  • 我这样做只是为了检查这是否可以实现。是的,使用Arrays.toString() 转换字节数组可以正常工作
  • 这是一种相当昂贵的方法:不仅转换为字符串(比原来占用更多的内存),而且还使用了正则表达式,因为String.replace 实际上调用了@987654327 @,在引用了它的论点之后。您可以相当容易地实现一个 indexOf 方法,该方法在另一个数组中找到子数组的起始位置(存在花哨的算法,但 String.indexOf 实际上是幼稚的);然后使用System.arrayCopy
  • @AndyTurner 我知道所有这些开销 :) 重点是尽可能多地重用现有的 String 功能。对不起,如果它不是那么有趣。
  • @AlexRudenko 重点不一定是 需要了解它们,但您的答案的读者需要。
猜你喜欢
  • 1970-01-01
  • 2011-07-02
  • 2016-09-10
  • 2014-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-11
  • 1970-01-01
相关资源
最近更新 更多