Home | History | Annotate | Download | only in io
      1 package org.jf.dexlib2.writer.io;
      2 
      3 import com.google.common.io.ByteStreams;
      4 
      5 import javax.annotation.Nonnull;
      6 import javax.annotation.Nullable;
      7 import java.io.*;
      8 
      9 /**
     10  * A deferred output stream that uses a file as its backing store, with a in-memory intermediate buffer.
     11  */
     12 public class FileDeferredOutputStream extends DeferredOutputStream {
     13     private static final int DEFAULT_BUFFER_SIZE = 4 * 1024;
     14 
     15     @Nonnull private final File backingFile;
     16     @Nonnull private final NakedBufferedOutputStream output;
     17     private int writtenBytes;
     18 
     19     public FileDeferredOutputStream(@Nonnull File backingFile) throws FileNotFoundException {
     20         this(backingFile, DEFAULT_BUFFER_SIZE);
     21     }
     22 
     23     public FileDeferredOutputStream(@Nonnull File backingFile, int bufferSize) throws FileNotFoundException {
     24         this.backingFile = backingFile;
     25         output = new NakedBufferedOutputStream(new FileOutputStream(backingFile), bufferSize);
     26     }
     27 
     28     @Override public void writeTo(@Nonnull OutputStream dest) throws IOException {
     29         byte[] outBuf = output.getBuffer();
     30         int count = output.getCount();
     31         output.resetBuffer();
     32         output.close();
     33 
     34         // did we actually write something out to disk?
     35         if (count != writtenBytes) {
     36             InputStream fis = new FileInputStream(backingFile);
     37             ByteStreams.copy(fis, dest);
     38             backingFile.delete();
     39         }
     40 
     41         dest.write(outBuf, 0, count);
     42     }
     43 
     44     @Override public void write(int i) throws IOException {
     45         output.write(i);
     46         writtenBytes++;
     47     }
     48 
     49     @Override public void write(byte[] bytes) throws IOException {
     50         output.write(bytes);
     51         writtenBytes += bytes.length;
     52     }
     53 
     54     @Override public void write(byte[] bytes, int off, int len) throws IOException {
     55         output.write(bytes, off, len);
     56         writtenBytes += len;
     57     }
     58 
     59     @Override public void flush() throws IOException {
     60         output.flush();
     61     }
     62 
     63     @Override public void close() throws IOException {
     64         output.close();
     65     }
     66 
     67     private static class NakedBufferedOutputStream extends BufferedOutputStream {
     68         public NakedBufferedOutputStream(OutputStream outputStream) {
     69             super(outputStream);
     70         }
     71 
     72         public NakedBufferedOutputStream(OutputStream outputStream, int i) {
     73             super(outputStream, i);
     74         }
     75 
     76         public int getCount() {
     77             return count;
     78         }
     79 
     80         public void resetBuffer() {
     81             count = 0;
     82         }
     83 
     84         public byte[] getBuffer() {
     85             return buf;
     86         }
     87     }
     88 
     89     @Nonnull
     90     public static DeferredOutputStreamFactory getFactory(@Nullable File containingDirectory) {
     91         return getFactory(containingDirectory, DEFAULT_BUFFER_SIZE);
     92     }
     93 
     94     @Nonnull
     95     public static DeferredOutputStreamFactory getFactory(@Nullable final File containingDirectory,
     96                                                          final int bufferSize) {
     97         return new DeferredOutputStreamFactory() {
     98             @Override public DeferredOutputStream makeDeferredOutputStream() throws IOException {
     99                 File tempFile = File.createTempFile("dexlibtmp", null, containingDirectory);
    100                 return new FileDeferredOutputStream(tempFile, bufferSize);
    101             }
    102         };
    103     }
    104 }
    105