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

Java 将inputstream传递到其他线程时读取失败,java,android,multithreading,httpurlconnection,Java,Android,Multithreading,Httpurlconnection,我正试图将输入流写入多端口,但我一直在点击: 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].tes

我正试图将
输入流
写入
多端口
,但我一直在点击:

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
该流是从AssetFileDescriptor.createInputStream()返回的
FileInputStream

这里我得到了
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连接,请求)
抛出IOException、AuthFailureError{
if(request.getEntity()!=null){
connection.setDoOutput(真);
connection.addRequestProperty(HEADER\u CONTENT\u TYPE,request.getBodyContentType());
connection.setChunkedStreamingMode(0);
OutputStream out=connection.getOutputStream();
request.getEntity().writeTo(out);
out.flush();
out.close();
}否则{
我试着用谷歌搜索它,但我能发现的是,输入流很可能已经关闭,但我没有在任何地方关闭它

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

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

[[结果表明,他/她正在读取一个资产并将其发送到远程,因此此答案没有真正的帮助。我现在将其作为占位符保留。]]

System.err﹕ 原因:android.system.ErrnoException:读取失败:EBADF(错误文件号)

正如@EJP所提到的,这试图告诉您,当后台线程从流中读取时,它已经被关闭

由于这似乎是一个web客户机,我怀疑您正在尝试从GET或POST响应读取文件,而响应容器在线程读取它时已经关闭

有几种方法可以解决此问题:

  • 发出请求的线程可以读取文件本身,然后将缓冲区中的字节传递给后台线程进行处理

  • 发出请求的线程可以读入文件并将其保存在磁盘上的临时文件中,然后将临时文件名交给后台线程


但无论如何,处理web请求的线程必须在关闭web请求容器之前完成请求上的IO。

在发送消息之前,您正在关闭
文件。@EJP“我尝试用谷歌搜索它,但我所能发现的是,很可能InputStream已关闭,但我没有在任何地方关闭它。”在我调用multipartRequest.addFileBody(“file”,file.createInputStream())之后,我不会对file做任何其他事情,也不会在任何时候关闭流,除非这是异常的意思。文件是关闭的。没有两种方法。事实上,涉及到两个线程(为什么?)使代码更可能不按您的想法运行。@EJP线程B是处理所有网络调用的后台线程。关闭文件很好,在我发布问题之前,我就知道了,但这并不能解决问题,我需要知道原因。此外,如果是在某个地方关闭了,它会当所有事情都发生在一个线程上时,它没有任何意义,除非我对线程和流的工作方式有一些误解。流来自一个
AssetFileDescriptor
,我找不到任何应该关闭它的理由,我要关闭它的唯一位置是在我读过它后的另一个线程上。嗯javadocs说:“你拥有这个描述符,并负责在完成后关闭它”。看起来确实有人在关闭它。也许可以在InputStream.close()或其他东西上设置一个断点,看看会弹出什么?
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 {