&引用;java.net.SocketException:Socket已关闭;在读取S3文件时

&引用;java.net.SocketException:Socket已关闭;在读取S3文件时,java,file-io,amazon-s3,Java,File Io,Amazon S3,我试图从S3中读取一个csv文本文件,然后将它的每一行发送到一个分布式队列以处理它们 当尝试读取它时,我在读取文件的不同位置(在不同的执行中)得到了“java.net.SocketException:socketisclosed”异常。代码如下: AmazonS3 s3 = new AmazonS3Client(new PropertiesCredentials(MyClass.class.getResourceAsStream("myCredentials.properties")

我试图从S3中读取一个csv文本文件,然后将它的每一行发送到一个分布式队列以处理它们

当尝试读取它时,我在读取文件的不同位置(在不同的执行中)得到了“java.net.SocketException:socketisclosed”异常。代码如下:

      AmazonS3 s3 = new AmazonS3Client(new PropertiesCredentials(MyClass.class.getResourceAsStream("myCredentials.properties")));

        String bucketName = "myBucket";
        String key = "myFile";  

        S3Object object = s3.getObject(new GetObjectRequest(bucketName, key));

        InputStream in = object.getObjectContent();

        BufferedReader readerS3 = new BufferedReader(new InputStreamReader(in, Charset.forName(fileInfo.getEncoding())));

        try {
            String line = null;
            while ((line = readerS3.readLine()) != null) {
                // Sending the line to a distributed queue
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
有没有办法解决这个问题

更新:


此异常发生在我第二次运行该方法时,如果我停止整个程序并再次运行它,那么第一次运行该方法时,它工作正常。

关闭套接字的输入流或输出流,或关闭套接字周围的任何流/读写器包装,关闭套接字(因此分别关闭输出流或输入流).

也许你应该用finally而不是in关闭readerS3。也就是说,关闭最外面的对象,这可以关闭它的包裹子对象

如果您先“in”关闭,则InputStreamReader和BufferedReader仍处于打开状态,如果他们试图对其包装的对象执行任何操作,则该对象将被关闭。

正如问题注释中的“jsn”所建议的,问题是您需要配置
AmazonS3


谢谢,@jsn,你的建议是我的问题

我有一个只返回InputStream的方法,这样AmazonS3对象就会被垃圾收集,并导致它关闭InputStream


我已经让它保留了对AmazonS3对象的引用,这解决了我的问题。

无需继续重新初始化s3

在onCreate上,调用初始化s3Object和s3Client

然后在异步任务中使用调用

通过这种方式,s3客户机将保留相同的数据,并且在执行while读取时永远不会关闭与s3的套接字连接。要聪明,要学习

S3Client s3Client;
S3Object s3Object;

onCreate() {
 s3Client = new AmazonS3Client(new BasicSessionCredentials(Constants.ACCESS_KEY_ID, Constants.SECRET_KEY, Constants.TOKEN));

 object = new S3Object();
}

doinbackground() {
      object = s3Client.getObject(new GetObjectRequest(Constants.getBucket(), id +".png"));
 }

我也有同样的问题,这个主题帮助我解决了这个问题:

基本上,我为每个文件创建了一个新的S3Client对象,但有一次这个对象被垃圾收集。因此,我没有这样做,而是将我的类转换为使用单例:

private static AmazonS3 s3Client;
  static {
    s3Client = new AmazonS3Client(new BasicAWSCredentials(AWSKey, AWSSecretKey));
  }

  public AmazonS3 getService() {
    return s3Client;
  }

不,但它在Structs Action类中尝试运行此操作,同时保留对所有这些对象的显式引用(如果正在使用且尚未尝试过):
S3Client
S3Object
Amazon3Client
。GC拾取对象和关闭连接可能有问题。文件有多大?您可能需要更改套接字超时(可能是0?->无限)<代码>http://docs.amazonwebservices.com/AWSJavaSDK/latest/javadoc/com/amazonaws/ClientConfiguration.html#getSocketTimeout()错误的URL(无法编辑注释),好的URL->本地变量不受GC约束。它们指向的对象是。您在某处过早地关闭了套接字。这是代码中的错误,不是服务器或网络问题。但在循环执行期间没有关闭任何流/读取器/写入器。@Fgblanch它在循环执行之后,在下次调用该方法之前关闭。和/或您正在关闭套接字或它的某个流。无限超时的缺点是什么?您能举个例子说明如何保留引用吗?制作一个这样的类变量,并将其设置为
private final AmazonS3 s3
private static AmazonS3 s3Client;
  static {
    s3Client = new AmazonS3Client(new BasicAWSCredentials(AWSKey, AWSSecretKey));
  }

  public AmazonS3 getService() {
    return s3Client;
  }