java.lang.NegativeArraySizeException:-1 使用 URLConnection 在 Android 上下载文件
java.lang.NegativeArraySizeException: -1 downloading file on Android with URLConnection
所以我尝试在我的应用程序中实现这个下载文件的功能,但是我没有成功,想知道为什么。这是代码:
public class Receiver extends BroadcastReceiver {
public static void downloadFile(String url, File outputFile) {
try {
URL u = new URL(url);
URLConnection conn = u.openConnection();
int contentLength = conn.getContentLength();
DataInputStream stream = new DataInputStream(u.openStream());
byte[] buffer = new byte[contentLength];
stream.readFully(buffer);
stream.close();
DataOutputStream fos = new DataOutputStream(new FileOutputStream(outputFile));
fos.write(buffer);
fos.flush();
fos.close();
} catch(FileNotFoundException e) {
Log.i("FileNotFoundException", "file not found"); // swallow a 404
} catch (IOException e) {
Log.i("IOException", "io exc"); // swallow a 404
}
}
Handler handler;
@Override
public void onReceive(Context context, Intent intent) {
final String link = "https://images.app.goo.gl/zjcreNXUrrihcWnD6";
String path = Environment.getExternalStorageDirectory().toString()+ "/Downloads";
final File empty_file = new File(path);
new Thread(new Runnable() {
@Override
public void run() {
downloadFile(link, empty_file);
}
}).start();
}
}
我收到这些错误:
2020-07-07 14:09:23.142 26313-26371/com.example.downloader E/AndroidRuntime: FATAL EXCEPTION: Thread-2
Process: com.example.downloader, PID: 26313
java.lang.NegativeArraySizeException: -1
at com.example.downloader.Receiver.downloadFile(Receiver.java:39)
at com.example.downloader.Receiver.run(Receiver.java:66)
at java.lang.Thread.run(Thread.java:919)
第 39 行是:
byte[] buffer = new byte[contentLength];
可能主要问题是线程的错误使用。
老实说,我是 Android 的新手,很难解决这个问题,也许你可以在 [=29= 中推荐一些好的 material 或与 Threads/URLs 相关的教程] (我已经搜索了很多,但仍然很难)。当然,对于我做错了什么的直接建议,我将不胜感激。
如果 HTTP 服务器事先不知道响应的大小,它可以发送内容长度为 -1 的响应。
不要分配整个文件大小的缓冲区,而是将其设置为合理的大小(例如 8K 字节)并使用循环流式传输文件;例如
byte[] buffer = new byte[8192];
int count;
while ((count = in.read(buffer)) > 0) {
out.write(buffer, 0, count);
}
这种方法有几个优点。它在内容长度为 -1 时起作用,如果内容长度非常大,它可以保护您免受 OOME 问题。 (不过 检查 内容长度仍然有意义......以避免填满设备文件系统。)
我注意到您当前的版本还有其他问题。
您正在以可能导致文件描述符泄漏的方式管理流。我建议您了解...并使用... JAVA 8 尝试使用资源 语法。
这是可疑的:
Log.i("IOException", "io exc"); // swallow a 404
假设所有 IOException
在那个 catch 块中被捕获都是由于 404 响应是不安全的。评论(至少!)不准确。
所以我尝试在我的应用程序中实现这个下载文件的功能,但是我没有成功,想知道为什么。这是代码:
public class Receiver extends BroadcastReceiver {
public static void downloadFile(String url, File outputFile) {
try {
URL u = new URL(url);
URLConnection conn = u.openConnection();
int contentLength = conn.getContentLength();
DataInputStream stream = new DataInputStream(u.openStream());
byte[] buffer = new byte[contentLength];
stream.readFully(buffer);
stream.close();
DataOutputStream fos = new DataOutputStream(new FileOutputStream(outputFile));
fos.write(buffer);
fos.flush();
fos.close();
} catch(FileNotFoundException e) {
Log.i("FileNotFoundException", "file not found"); // swallow a 404
} catch (IOException e) {
Log.i("IOException", "io exc"); // swallow a 404
}
}
Handler handler;
@Override
public void onReceive(Context context, Intent intent) {
final String link = "https://images.app.goo.gl/zjcreNXUrrihcWnD6";
String path = Environment.getExternalStorageDirectory().toString()+ "/Downloads";
final File empty_file = new File(path);
new Thread(new Runnable() {
@Override
public void run() {
downloadFile(link, empty_file);
}
}).start();
}
}
我收到这些错误:
2020-07-07 14:09:23.142 26313-26371/com.example.downloader E/AndroidRuntime: FATAL EXCEPTION: Thread-2
Process: com.example.downloader, PID: 26313
java.lang.NegativeArraySizeException: -1
at com.example.downloader.Receiver.downloadFile(Receiver.java:39)
at com.example.downloader.Receiver.run(Receiver.java:66)
at java.lang.Thread.run(Thread.java:919)
第 39 行是:
byte[] buffer = new byte[contentLength];
可能主要问题是线程的错误使用。
老实说,我是 Android 的新手,很难解决这个问题,也许你可以在 [=29= 中推荐一些好的 material 或与 Threads/URLs 相关的教程] (我已经搜索了很多,但仍然很难)。当然,对于我做错了什么的直接建议,我将不胜感激。
如果 HTTP 服务器事先不知道响应的大小,它可以发送内容长度为 -1 的响应。
不要分配整个文件大小的缓冲区,而是将其设置为合理的大小(例如 8K 字节)并使用循环流式传输文件;例如
byte[] buffer = new byte[8192];
int count;
while ((count = in.read(buffer)) > 0) {
out.write(buffer, 0, count);
}
这种方法有几个优点。它在内容长度为 -1 时起作用,如果内容长度非常大,它可以保护您免受 OOME 问题。 (不过 检查 内容长度仍然有意义......以避免填满设备文件系统。)
我注意到您当前的版本还有其他问题。
您正在以可能导致文件描述符泄漏的方式管理流。我建议您了解...并使用... JAVA 8 尝试使用资源 语法。
这是可疑的:
Log.i("IOException", "io exc"); // swallow a 404
假设所有
IOException
在那个 catch 块中被捕获都是由于 404 响应是不安全的。评论(至少!)不准确。