Android:打开文件太多错误

时间:2013-06-05 01:08:42

标签: android httpurlconnection android-file

我有以下操作,每3秒运行一次 基本上它从服务器下载文件并每隔3秒将其保存到本地文件中 以下代码完成了一段时间的工作。

public class DownloadTask extends AsyncTask<String, Void, String>{

    @Override
    protected String doInBackground(String... params) {
        downloadCommandFile( eventUrl);
        return null;
    }


}

private void downloadCommandFile(String dlUrl){
    int count;
    try {
        URL url = new URL( dlUrl );
        NetUtils.trustAllHosts();
        HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
        con.setDoInput(true);
        con.setDoOutput(true);
        con.connect();
        int fileSize = con.getContentLength();
        Log.d(TAG, "Download file size = " + fileSize );
        InputStream is = url.openStream();
        String dir = Environment.getExternalStorageDirectory() + Utils.DL_DIRECTORY;
        File file = new File( dir );
        if( !file.exists() ){
            file.mkdir();
        }

        FileOutputStream fos = new FileOutputStream(file + Utils.DL_FILE);
        byte data[] = new byte[1024];
        long total = 0;

        while( (count = is.read(data)) != -1 ){
            total += count;
            fos.write(data, 0, count);
        }

        is.close();
        fos.close();
        con.disconnect(); // close connection


    } catch (Exception e) {
        Log.e(TAG, "DOWNLOAD ERROR = " + e.toString() );
    }

}

一切正常,但如果我让它运行5到10分钟,我会收到以下错误。

  

06-04 19:40:40.872:E / NativeCrypto(6320):AppData :: create pipe(2)   失败:打开过多的文件06-04 19:40:40.892:E / NativeCrypto(6320):   AppData :: create pipe(2)失败:打开文件太多06-04   19:40:40.892:E / EventService(6320):DOWNLOAD ERROR =   javax.net.ssl.SSLException:无法创建应用程序数据

过去两天我一直在做一些研究 有人建议他们打开很多连接,比如https://stackoverflow.com/a/13990490/1503155,但我仍然无法弄清楚问题是什么。
可能导致问题的任何想法?
提前谢谢。

2 个答案:

答案 0 :(得分:4)

我认为你得到这个错误是因为你有太多文件同时打开,这意味着你有太多异步任务在同一时间运行(每个异步任务打开一个文件),如果你这么说就有意义了你每3秒跑一个新的。

您应该尝试使用线程池执行程序限制同时运行的异步任务的数量。

答案 1 :(得分:1)

尝试使用OkHttp

您的问题没有太多线程,尽管这是导致问题浮出水面的原因。

正如注释中提到的@stdout一样,除非您另外指定,否则AsyncTask已在所有AsyncTask中共有并共享的线程池中运行。这里的问题是,文件描述符未及时正确关闭。

问题是您的文件描述符关闭得不够快。

我为此花费了数小时/天/周的时间,做了所有您想设置的小的读取/连接超时并使用finally块来关闭连接,输入流,输出流等的操作。但是我们从来没有找到了可行的解决方案。 HttpsUrlConnection似乎存在某种缺陷。

因此,我们尝试用OkHttp替代HttpsUrlConnection和瞧!它开箱即用。

因此,如果您对此感到挣扎,并且很难解决它,建议您也尝试使用OkHttp。

以下是基本知识:

一旦添加了Maven依赖项,就可以执行以下操作来下载文件:

OkHttpClient okHttpClient = new OkHttpClient.Builder().build();

OutputStream output = null;

try {
  Request request   = new Request.Builder().url( download_url ).build();
  Response response = okHttpClient.newCall( request ).execute();

  if ( !response.isSuccessful() ) {
    throw new FileNotFoundException();
  }

  output = new FileOutputStream( output_path );

  output.write( response.body().bytes() );
}
finally {
  // Ensure streams are closed, even if there's an exception.
  if ( output != null ) output.flush();
  if ( output != null ) output.close();
}

切换到OkHttp会立即解决我们泄漏的文件描述符问题,因此即使您被卡住了也值得尝试,即使以增加另一个库依赖项为代价。