1

Я начинаю с ответом от запроса HTTP:Как я могу gzip InputStream и возвращать InputStream?

InputStream responseInputStream = response.getEntityInputStream() 

Мне нужно GZIP этот ответ, поэтому я могу загрузить его на s3 и сохранить его прессует:

this.s3.putObject(new PutObjectRequest(bucketName, key, gzippedResponseInputStream, meta)); 

Я знаю, что я может получить массив byte[] из responseInputStream, а затем gzip их в новый InputStream. Однако это может быть очень неэффективным с большим объемом данных.

Я знаю, что были заданы одинаковые вопросы по SO, но я не нашел ничего, что, по-видимому, касалось конкретной необходимости запуска с InputStream и заканчивая gzipped InputStream.

Спасибо за помощь!

+1

Вы проверили этот ответ? http://stackoverflow.com/a/19326492/2588800 –

+0

Вау, спасибо @SvetlinZarev - это сработало! Я искал SO, пытаясь найти каждое «решение», которое я нашел, и ничто из этого не сработало до сих пор, но ваше предложение сделало трюк! Спасибо! – chaimp

ответ

3
public final class Example { 
    public static void main(String[] args) throws IOException, InterruptedException { 
     final PipedInputStream inputStream = new PipedInputStream(); 
     final PipedOutputStream outputStream = new PipedOutputStream(inputStream); 

     Thread compressorThread = new Thread() { 
      @Override 
      public void run() { 
       try (FileInputStream dataSource = new FileInputStream(args[0])) { 
        try (GZIPOutputStream sink = new GZIPOutputStream(outputStream)) { 
         final byte[] buffer = new byte[8 * 1024]; 
         for (int bytesRead = dataSource.read(buffer); bytesRead >= 0; bytesRead = dataSource.read(buffer)) { 
          sink.write(buffer, 0, bytesRead); 
         } 
        } 
       } catch (IOException ex) { 
        //TODO handle exception -> maybe use callable + executor 
       } 
      } 
     }; 
     compressorThread.start(); 

     try (FileOutputStream destination = new FileOutputStream(args[1])) { 
      final byte[] buffer = new byte[8 * 1024]; 
      for (int bytesRead = inputStream.read(buffer); bytesRead >= 0; bytesRead = inputStream.read(buffer)) { 
       destination.write(buffer, 0, bytesRead); 
      } 
     } 

     compressorThread.join(); 
    } 

} 

Вы правы, мой предыдущий пример был неправильным. Вы можете использовать потоки с потоками. Улов здесь заключается в том, что вы не можете использовать поток ввода и вывода из того же потока. Также не забудьте указать join() на написание. Вы можете проверить мой пример, supplyng два параметра:

  • арг [0] -> исходный файл
  • арг [1] -> адресат писать сжатое содержимое

PS: @ 11thdimension было несколько минут быстрее, с его водопроводными решениями потока, так что если вы нашли это полезное, пожалуйста, примите его ответ

+0

GZIPInputStream предназначен для взятия уже сжатых данных и их распаковки. Я действительно пробовал это уже до этого. Но это так ясно сказано в документации. Благодарим вас за быстрый ответ, но это неверно. – chaimp

+0

Спасибо @svetlin. Я закончил работу с решением, которое вы нашли в комментарии к вопросу, но я ценю это, и я верю, что он работает, поэтому я буду отмечать его как «принятый». – chaimp

3

Я думаю, что вы ищете PipedInputStream

Вот как это можно сделать.

public InputStrema getGZipStream() { 
    final PipedOutputStream pos = new PipedOutputStream(); 
    PipedInputStream pis = new PipedInputStream(); 

    try (final InputStream responseInputStream = response.getEntityInputStream(); 
    ){ 
     pis.connect(pos); 

     Thread thread = new Thread() { 
      public void run() { 
       startWriting(pos, responseInputStream); 
      } 
     }; 
     thread.start(); 
    } catch(Exception e) { 
     e.printStackTrace(); 
    } 

    return pis; 
} 

public void startWriting(OutputStream out, InputStream in) { 
    try (GZIPOutputStream gOut = GZIPOutputStream(out);) { 
     byte[] buffer = new byte[10240]; 
     int len = -1; 
     while ((len = in.read(buffer)) != -1) { 
      gOut.write(buffer, 0, len); 
     } 
    } catch (Exception ex) { 
     ex.printStackTrace(); 
    } finally { 
     try { 
      out.close(); 
     } catch(Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 

Я еще не протестировал этот код, пожалуйста, дайте мне знать, если это сработает.

+1

Это не работает, потому что вы закрываете 'pis', когда вы выходите из тела' try', поэтому вы возвращаете закрытый поток; –

+0

Я думал то же самое. Безопасно ли попытаться закрыть потоки в конце метода? В любом случае я изменю код для работы с ним. – 11thdimension

+0

Изменено, по крайней мере, у него не должно быть проблемы с закрытым потоком. – 11thdimension

Смежные вопросы