這裏
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