我正在声明一个大小未知的字节数组,因为它一直在更新,所以如何声明无限大小/可变大小的字节数组?
答案 0 :(得分:10)
你不能声明一个无限大小的数组,因为这需要无限的内存。此外,所有分配调用都处理数字,而不是无限数量。
您可以分配一个按需调整大小的字节缓冲区。我相信最简单的选择是ByteArrayOutputStream
。
ByteBuffer
有一个API,可以更轻松地操作缓冲区,但您必须自己构建调整大小功能。最简单的方法是分配一个新的,更大的数组,复制旧内容,并交换旧缓冲区。
其他答案提到使用某种List<Byte>
。值得注意的是,如果创建一堆new Byte()
个对象,则可以大大增加内存消耗。 Byte.valueOf
回避了这个问题,但您必须确保在整个代码中始终如一地使用它。如果你打算在很多地方使用这个列表,我可能会考虑编写一个简单的List
装饰器来实现所有元素。例如:
public class InterningList extends AbstractList<Byte>
{
...
@Override
public boolean add(Byte b) {
return super.add(Byte.valueOf(b));
}
...
}
这不是一个完整的(甚至是经过测试的)示例,只是一些开始......
答案 1 :(得分:6)
Java中的数组不是动态的。您可以改用列表。
List<Byte> list = new ArrayList<Byte>();
由于自动装箱功能,您可以自由地将字节对象或原始字节添加到此列表中。
答案 2 :(得分:2)
要定义不同长度的bytearray,只需使用apache commons.io.IOUtils
库而不是指定手动长度,如
byte[] b=new byte[50];
您可以将输入流传递给IOUtils
函数,该函数将在此输入流上执行读取功能,因此字节数组将具有所需的精确字节长度。
离。
byte[] b = IOUtils.toByteArray(inpustream);
混沌..
答案 3 :(得分:1)
最好的办法是使用ArrayList。当你填写它时它会调整大小。
List<Byte> array = new ArrayList<Byte>();
答案 4 :(得分:1)
显而易见的解决方案是使用ArrayList。
但是如果你需要性能或者内存受限,这是一个糟糕的解决方案,因为它并不真正存储字节而是字节(即对象)。
对于任何实际的应用程序,答案很简单:你必须通过使用方法使自己管理自己的必要增长。如果需要,您可以将其嵌入特定的类中:
public class AlmostInfiniteByteArray {
private byte[] array;
private int size;
public AlmostInfiniteByteArray(int cap) {
array = new byte[cap];
size = 0;
}
public int get(int pos) {
if (pos>=size) throw new ArrayIndexOutOfBoundsException();
return array[pos];
}
public void set(int pos, byte val) {
if (pos>=size) {
if (pos>=array.length) {
byte[] newarray = new byte[(pos+1)*5/4];
System.arraycopy(array, 0, newarray, 0, size);
array = newarray;
}
size = pos+1;
}
array[pos] = val;
}
}
答案 5 :(得分:1)
ByteArrayOutputStream将允许写入动态字节数组。但是,删除,替换和插入等方法不可用。必须提取字节数组,然后直接操作它。
答案 6 :(得分:0)
答案 7 :(得分:0)
ArrayList的初始容量为10.您可以通过ArrayList(5000)更改它。 ArrayList会在需要时将其大小加倍(它将创建新数组并将旧数组复制到新数组)。
答案 8 :(得分:0)
我会略微调整其他人的答案。
创建一个LargeByteArray类来管理您的数组。无论你需要什么,它都会获得和设置方法等。
在幕后,类将使用long来保存当前长度并使用ArrayList来存储数组的内容。
我会选择在ArrayList中存储byte [8192]或byte [16384]数组。这将在浪费的大小方面给出合理的权衡,并减少调整大小的需要。
如果该框中存储了非零值,您甚至可以使数组'稀疏',即只分配list.get(index / 8192)条目。
在某些情况下,这样的结构可以为您提供更多的存储空间。
您可以使用的另一种策略是在写入之后压缩byte []框并在读取之前解压缩(使用LRU缓存进行读取),这可以允许存储两次或更多可用的ram ...虽然这取决于压缩策略
之后,您可以查看将某些框分页到磁盘...
这就像我能得到的那样接近无限阵列; - )
答案 9 :(得分:0)
Prashant已经告诉你,你可以从片断中使用IOUtils。
这里有一小部分可以解决任务(你需要IOUtils.toByteArray):
public class IOUtils {
private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
public static byte[] toByteArray(InputStream input) throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
copy(input, output);
return output.toByteArray();
}
public static int copy(InputStream input, OutputStream output)
throws IOException {
long count = copyLarge(input, output);
if (count > Integer.MAX_VALUE) {
return -1;
}
return (int) count;
}
public static long copyLarge(InputStream input, OutputStream output)
throws IOException {
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
long count = 0;
int n = 0;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
return count;
}
}