如何在Java中的字节序列周围分割byte[]
?类似于String#split(regex)
的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[]
答案 0 :(得分:10)
这是一个简单的解决方案。
与avgvstvs方法不同,它处理任意长度分隔符。最佳答案也很好,但作者没有解决Eitan Perkal指出的问题。使用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;
}
答案 1 :(得分:7)
请注意,如果使用编码&#34; iso8859-1&#34;
但是,它仍然是一个丑陋的解决方案。
我认为你需要自己动手。
我建议分两个阶段来解决它:
这里使用的是朴素的模式发现算法。如果分隔符很长,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)
我修改了'L. Blanc的答案是在开始和结束时处理分隔符。另外,我将其重命名为“拆分”。
private List<byte[]> split(byte[] array, byte[] delimiter)
{
List<byte[]> byteArrays = new LinkedList<byte[]>();
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;
}
}
// If delimiter is at the beginning then there will not be any data.
if (begin != i)
byteArrays.add(Arrays.copyOfRange(array, begin, i));
begin = i + delimiter.length;
}
// delimiter at the very end with no data following?
if (begin != array.length)
byteArrays.add(Arrays.copyOfRange(array, begin, array.length));
return byteArrays;
}
答案 3 :(得分:0)
滚动自己是唯一的方式去这里。如果您对非标准库开放,我可以提供的最好的想法是来自Apache的这个类:
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)。
答案 4 :(得分:0)
对https://stackoverflow.com/a/44468124/1291605的答案Roger有一些改进:
假设我们有这样的数组||||aaa||bbb
和定界符||
。在这种情况下,我们得到
java.lang.IllegalArgumentException: 2 > 1
at java.util.Arrays.copyOfRange(Arrays.java:3519)
因此,最终的改进方案是:
public static List<byte[]> split(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;
}
}
// This condition was changed
if (begin != i)
byteArrays.add(Arrays.copyOfRange(array, begin, i));
begin = i + delimiter.length;
}
// Also here we may change condition to 'less'
if (begin < array.length)
byteArrays.add(Arrays.copyOfRange(array, begin, array.length));
return byteArrays;
}
答案 5 :(得分:-2)
您可以使用Arrays.copyOfRange()
。
答案 6 :(得分:-4)
您可以从String
数组构造一个byte
对象。猜猜你知道其余的。
public static byte[][] splitByteArray(byte[] bytes, byte[] regex, Charset charset) {
String str = new String(bytes, charset);
String[] split = str.split(new String(regex, charset));
byte[][] byteSplit = new byte[split.length][];
for (int i = 0; i < split.length; i++) {
byteSplit[i] = split[i].getBytes(charset);
}
return byteSplit;
}
public static void main(String[] args) {
Charset charset = Charset.forName("UTF-8");
byte[] bytes = {
'1', '1', ' ', '1', '1',
'F', 'F', ' ', 'F', 'F',
'2', '2', ' ', '2', '2', ' ', '2', '2',
'F', 'F', ' ', 'F', 'F',
'3', '3', ' ', '3', '3', ' ', '3', '3', ' ', '3', '3'
};
byte[] regex = {'F', 'F', ' ', 'F', 'F'};
byte[][] splitted = splitByteArray(bytes, regex, charset);
for (byte[] arr : splitted) {
System.out.print("[");
for (byte b : arr) {
System.out.print((char) b);
}
System.out.println("]");
}
}