将inputstream传递给其他线程时读取失败

时间:2015-08-02 01:14:56

标签: java android multithreading httpurlconnection

我正在尝试将InputStream写入MultiPartEntity,但我一直在点击:

08-01 17:25:13.523    2737-2787/com.[project].[package].test E/Volley﹕ [12495] BasicNetwork.performRequest: Unexpected response code 401 for https://api.[project].com/
08-01 17:25:13.603    2737-2737/com.[project].[package].test W/System.err﹕ com.android.volley.NoConnectionError: java.io.IOException: read failed: EBADF (Bad file number)
08-01 17:25:13.603    2737-2737/com.[project].[package].test W/System.err﹕ at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:151)
08-01 17:25:13.603    2737-2737/com.[project].[package].test W/System.err﹕ at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:112)
08-01 17:25:13.604    2737-2737/com.[project].[package].test W/System.err﹕ Caused by: java.io.IOException: read failed: EBADF (Bad file number)
08-01 17:25:13.605    2737-2737/com.[project].[package].test W/System.err﹕ at libcore.io.IoBridge.read(IoBridge.java:482)
08-01 17:25:13.605    2737-2737/com.[project].[package].test W/System.err﹕ at java.io.FileInputStream.read(FileInputStream.java:177)
08-01 17:25:13.605    2737-2737/com.[project].[package].test W/System.err﹕ at java.io.InputStream.read(InputStream.java:162)
08-01 17:25:13.605    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.entity.mime.content.InputStreamBody.writeTo(InputStreamBody.java:91)
08-01 17:25:13.605    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.entity.mime.AbstractMultipartForm.doWriteTo(AbstractMultipartForm.java:150)
08-01 17:25:13.606    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.entity.mime.AbstractMultipartForm.writeTo(AbstractMultipartForm.java:173)
08-01 17:25:13.606    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.entity.mime.MultipartFormEntity.writeTo(MultipartFormEntity.java:97)
08-01 17:25:13.606    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.impl.execchain.RequestEntityProxy.writeTo(RequestEntityProxy.java:116)
08-01 17:25:13.606    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.impl.DefaultBHttpClientConnection.sendRequestEntity(DefaultBHttpClientConnection.java:155)
08-01 17:25:13.606    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.impl.conn.CPoolProxy.sendRequestEntity(CPoolProxy.java:149)
08-01 17:25:13.606    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.protocol.HttpRequestExecutor.doSendRequest(HttpRequestExecutor.java:242)
08-01 17:25:13.607    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:124)
08-01 17:25:13.607    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:260)
08-01 17:25:13.607    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195)
08-01 17:25:13.607    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)
08-01 17:25:13.607    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:178)
08-01 17:25:13.607    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
08-01 17:25:13.607    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)
08-01 17:25:13.608    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57)
08-01 17:25:13.608    2737-2737/com.[project].[package].test W/System.err﹕ at com.android.volley.toolbox.HttpClientStack.performRequest(HttpClientStack.java:87)
08-01 17:25:13.608    2737-2737/com.[project].[package].test W/System.err﹕ at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:96)
08-01 17:25:13.608    2737-2737/com.[project].[package].test W/System.err﹕ ... 1 more
08-01 17:25:13.609    2737-2737/com.[project].[package].test W/System.err﹕ Caused by: android.system.ErrnoException: read failed: EBADF (Bad file number)
08-01 17:25:13.610    2737-2737/com.[project].[package].test W/System.err﹕ at libcore.io.Posix.readBytes(Native Method)
08-01 17:25:13.610    2737-2737/com.[project].[package].test W/System.err﹕ at libcore.io.Posix.read(Posix.java:165)
08-01 17:25:13.610    2737-2737/com.[project].[package].test W/System.err﹕ at libcore.io.BlockGuardOs.read(BlockGuardOs.java:230)
08-01 17:25:13.610    2737-2737/com.[project].[package].test W/System.err﹕ at libcore.io.IoBridge.read(IoBridge.java:472)
08-01 17:25:13.610    2737-2737/com.[project].[package].test W/System.err﹕ ... 21 more

该流是从FileInputStream

返回的AssetFileDescriptor.createInputStream()

我在这里得到AssetFileDescriptor

AssetFileDescriptor file = getContext().getContentResolver().openAssetFileDescriptor(person,
                    "r");

然后将其添加到多部分:

multipartRequest.addFileBody("file", file.createInputStream());

正在使用MultipartEntityBuilder

public void addFileBody(String name, InputStream in){
    multipartEntityBuilder.addBinaryBody(name, in);
}

我正在使用HttpURLConnection 我在这里写这个主体:

这个(连同整个连接)发生在不同的线程上

private static void addBodyIfExists(HttpURLConnection connection, Request<?> request)
        throws IOException, AuthFailureError {
    if(request.getEntity() != null){
        connection.setDoOutput(true);
        connection.addRequestProperty(HEADER_CONTENT_TYPE, request.getBodyContentType());
        connection.setChunkedStreamingMode(0);
        OutputStream out = connection.getOutputStream();
        request.getEntity().writeTo(out);
        out.flush();
        out.close();
    } else {

我尝试使用谷歌搜索,但我发现的最重要的是,它很可能是关闭了InputStream,但是我不会在任何地方关闭它。

编辑:似乎问题是我试图从一个单独的线程发出请求,因为当它发生在同一个线程上时,一切正常。

TL; DR: 线程A获取文件流并创建请求对象,将流添加到对象。 线程B启动并获取所述对象,打开连接,并尝试读取流/写入连接,此时发生读取错误。

1 个答案:

答案 0 :(得分:1)

[[ Turns out that s/he is reading an asset and sending it to the remote so this answer doesn't really help. I'm going to leave it up as a placeholder for now. ]]

System.err﹕ Caused by: android.system.ErrnoException: read failed: EBADF (Bad file number)

As @EJP mentioned, this is trying to tell you that by the time the background thread goes to read from the stream, it has been closed.

Since this seems to be a web-client, I suspect you are trying to read a file from a GET or POST response and the response container has been shutdown and closed by the time the thread goes to read it.

There are a couple of ways to fix this:

  • The thread making the request could read in the file itself and then pass the bytes in a buffer to the background thread for processing.

  • The thread making the request could read in the file and save it in a temporary file on disk and then hand of the temp file name to the background thread.

But regardless, the thread handling the web-request has to complete the IO on the request before the web-request container is closed.