【问题标题】:java.lang.NegativeArraySizeException: -1 downloading file on Android with URLConnectionjava.lang.NegativeArraySizeException: -1 在 Android 上使用 URLConnection 下载文件
【发布时间】:2020-07-08 08:41:57
【问题描述】:

所以我尝试在我的应用程序中实现https://stackoverflow.com/a/1718140/13592426这个用于下载文件的功能,但我没有成功,并想找出原因。代码如下:

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$1.run(Receiver.java:66)
    at java.lang.Thread.run(Thread.java:919)

第 39 行是:

byte[] buffer = new byte[contentLength];

也许主要的问题在于线程的错误使用。

老实说,我是 Android 新手,很难解决这个问题,也许你可以推荐一些与 Android 中的线程/URL 相关的好材料或教程(我已经搜索了很多,但仍然很难)。当然,对于我做错了什么,我会很感激直接的建议。

【问题讨论】:

    标签: java android multithreading urlconnection


    【解决方案1】:

    如果 HTTP 服务器事先不知道响应的大小,它可以发送内容长度为 -1 的响应。

    不要分配整个文件大小的缓冲区,而是将其设置为合理的大小(例如 8K 字节)并使用循环流式传输文件;例如

    byte[] buffer = new byte[8192];
    int count;
    while ((count = in.read(buffer)) > 0) {
        out.write(buffer, 0, count);
    }
    

    这种方法有几个优点。它在内容长度为 -1 时起作用,如果内容长度非常大,它可以保护您免受 OOME 问题的影响。 (尽管检查内容长度仍然有意义......以避免填充设备文件系统。)


    我注意到您当前的版本还有其他问题。

    1. 您正在以可能导致文件描述符泄漏的方式管理流。我建议您了解 ... 并使用 ... JAVA 8 尝试使用资源 语法。

    2. 这是可疑的:

       Log.i("IOException", "io exc"); // swallow a 404
      

      假设在该 catch 块中捕获的所有 IOExceptions 都是由于 404 响应是不安全的。评论(至少!)不准确。

    【讨论】:

    • 感谢您的建议!我的错只是复制粘贴了某人的功能,但是您对缓冲区大小的建议很有帮助。其他的我会在学习更多关于 Java 和 Android 的同时尝试考虑,再次感谢!
    • 现在我仍然遇到“找不到文件”的问题,但至少服务器一切正常
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-12
    • 1970-01-01
    • 2016-03-09
    • 1970-01-01
    • 2017-01-24
    • 2017-02-21
    • 1970-01-01
    相关资源
    最近更新 更多