有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

在Java中,如何围绕字节序列拆分字节数组?

在Java中,如何围绕字节序列拆分byte[]?类似于^{}byte[]版本

示例

让我们来看看这个字节数组:
[11 11 FF FF 22 22 22 FF FF 33 33 33 33]

让我们选择分隔符
[FF FF]

然后拆分将产生以下三部分:
[11 11]
[22 22 22]
[33 33 33 33]

编辑:

请注意,由于编码问题,您无法将byte[]转换为String,然后将其拆分,然后再返回。在字节数组上进行这种转换时,得到的byte[]将不同。请参阅: Conversion of byte[] into a String and then back to a byte[]


共 (3) 个答案

  1. # 1 楼答案

    请注意,如果使用编码“iso8859-1”,则可以通过字符到字节的一对一映射,可靠地从字节[]转换为字符串并返回

    然而,这仍然是一个丑陋的解决方案

    我想你需要自己动手

    我建议分两个阶段解决:

    1. 了解如何找到分隔符每次出现的索引。谷歌为“Knuth Morris Pratt”提供了一个高效的算法——尽管对于短分隔符来说,更简单的算法也可以
    2. 每次找到索引时,都要使用数组。copyOfRange()获取所需的工件并将其添加到输出列表中

    这里使用的是一种简单的模式查找算法。如果分隔符很长,KMP就值得了(因为它可以避免回溯,但如果分隔符嵌入的序列在最后不匹配,它也不会错过分隔符)

    public static boolean isMatch(byte[] pattern, byte[] input, int pos) {
        for(int i=0; i< pattern.length; i++) {
            if(pattern[i] != input[pos+i]) {
                return false;
            }
        }
        return true;
    }
    
    public static List<byte[]> split(byte[] pattern, byte[] input) {
        List<byte[]> l = new LinkedList<byte[]>();
        int blockStart = 0;
        for(int i=0; i<input.length; i++) {
           if(isMatch(pattern,input,i)) {
              l.add(Arrays.copyOfRange(input, blockStart, i));
              blockStart = i+pattern.length;
              i = blockStart;
           }
        }
        l.add(Arrays.copyOfRange(input, blockStart, input.length ));
        return l;
    }
    
  2. # 2 楼答案

    这里有一个简单的解决方案

    与avgvstvs方法不同,它处理任意长度的分隔符。上面的答案也不错,但作者还没有解决Eitan Perkal指出的问题。这里使用珀卡尔建议的方法避免了这个问题

    public static List<byte[]> tokens(byte[] array, byte[] delimiter) {
            List<byte[]> byteArrays = new LinkedList<>();
            if (delimiter.length == 0) {
                return byteArrays;
            }
            int begin = 0;
    
            outer:
            for (int i = 0; i < array.length - delimiter.length + 1; i++) {
                for (int j = 0; j < delimiter.length; j++) {
                    if (array[i + j] != delimiter[j]) {
                        continue outer;
                    }
                }
                byteArrays.add(Arrays.copyOfRange(array, begin, i));
                begin = i + delimiter.length;
            }
            byteArrays.add(Arrays.copyOfRange(array, begin, array.length));
            return byteArrays;
        }
    
  3. # 3 楼答案

    你自己滚是唯一的办法。如果你对非标准库开放,我能提供的最好的想法是来自Apache的这个类:

    http://commons.apache.org/proper/commons-primitives/apidocs/org/apache/commons/collections/primitives/ArrayByteList.html

    Knuth的解决方案可能是最好的,但我会将数组视为堆栈,并执行以下操作:

    List<ArrayByteList> targetList = new ArrayList<ArrayByteList>();
    while(!stack.empty()){
      byte top = stack.pop();
      ArrayByteList tmp = new ArrayByteList();
    
      if( top == 0xff && stack.peek() == 0xff){
        stack.pop();
        continue;
      }else{
        while( top != 0xff ){
          tmp.add(stack.pop());
        }
        targetList.add(tmp);
      }
    }
    

    我知道这是相当快和肮脏,但它应该在所有情况下交付O(n)