这里
ArrayList<Integer> byteArray = new ArrayList<Integer>();
int tempByte;
do {
tempByte = stream.read();
byteArray.add(tempByte);
你的每一个字节写直入内存整型数组!每个整数占用4个字节的内存,而每个读取字节只需要一个字节。实际上,您应该使用ArrayList<Byte>
或更好的byte[]
,因为每个byte
只需要一个字节的内存,但是每个saldo仍会分配尽可能多的内存。
这里
byte[] bytes = new byte[byteArray.size()];
你以后分配尽可能多的内存一样大的文件。根据文件大小的不同,你可以使用ArrayList<Integer>
和byte[]
分配5倍的内存。
这是一种浪费。
你应该把它写到OutputStream
立即,例如, FileOutputStream
。
InputStream input = null;
OutputStream output = null;
try {
input = license.openStream();
output = new FileOutputStream("/file.ext");
byte[] buffer = new byte[1024];
for (int length; (length = input.read(buffer)) > 0;) {
output.write(buffer, 0, length);
}
} finally {
if (output != null) try { output.close(); } catch (IOException logOrIgnore) {}
if (input != null) try { input.close(); } catch (IOException logOrIgnore) {}
}
,这将花费仅有效的存储器的缓冲液代替字节(或使用整数时的它的4倍)的整个文件长度1KB。
或者如果你真的想要它在byte[]
然后只是跳过整个ArrayList<Integer>
步骤。这个不成立。使用ByteArrayOutputStream
作为OutputStream
。
InputStream input = null;
ByteArrayOutputStream output = null;
try {
input = license.openStream();
output = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
for (int length; (length = input.read(buffer)) > 0;) {
output.write(buffer, 0, length);
}
} finally {
if (output != null) try { output.close(); } catch (IOException logOrIgnore) {}
if (input != null) try { input.close(); } catch (IOException logOrIgnore) {}
}
byte[] bytes = output.toByteArray();
然而,这仍然花费尽可能多的内存一样大的文件,这只是现在的文件大小不是5次了,因为你最初与ArrayList<Integer>
做和byte[]
之后。
更新:您愿意为每次您的评论作为其存储在数据库中。您也可以在不将整个文件存储在Java内存中的情况下执行此操作。只需使用PreparedStatement#setBinaryStream()
将获得的InputStream
立即写入数据库。
final String SQL = "INSERT INTO file (filename, contentType, content) VALUES (?, ?, ?)";
String filename = FilenameUtils.getName(license.getName());
InputStream input = license.openStream();
Connection connection = null;
PreparedStatement statement = null;
try {
connection = database.getConnection();
statement = connection.prepareStatement(SQL);
statement.setString(1, filename);
statement.setString(2, getServletContext().getMimeType(filename));
statement.setBinaryStream(3, input);
statement.executeUpdate();
} catch (SQLException e) {
throw new ServletException("Saving file in DB failed", e);
} finally {
if (statement != null) try { statement.close(); } catch (SQLException logOrIgnore) {}
if (connection != null) try { connection .close(); } catch (SQLException logOrIgnore) {}
}
我更新了代码以反映@skaffman和@ Bozho的建议。我现在使用一个DiskFileItemFactory创建ServletFileUpload对象,通过该对象传递自定义参数。我也以正确的方式处理InputStream,并在finally块中关闭它。但是,这似乎还没有解决问题。这是我认为可能发生的事情。我正在使用一个derby数据库,它似乎是在与服务器相同的线程中打开的。我也将对象存储为Blob。数据库本身是否被读入内存并被保存? 感谢所有迄今为止的出色反馈! Scott – Scott 2010-06-09 22:42:33
您是否设法找到解决方案?我有同样的问题! – 2012-06-06 00:02:06
我在一个问题中没有见过这么多着名的SO-ers :) – gkiko 2015-03-11 13:04:53