Home | History | Annotate | Download | only in shared
      1 // Copyright 2016 Google Inc. All rights reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 package com.google.archivepatcher.shared;
     16 
     17 import java.io.File;
     18 import java.io.IOException;
     19 import java.io.OutputStream;
     20 import java.io.RandomAccessFile;
     21 
     22 /**
     23  * An {@link OutputStream} backed by a file that will be written serially. Allows pre-allocating
     24  * the space for a stream as a file and then writing to that file as a stream. Call {@link #flush()}
     25  * to force the data to be written to the backing storage.
     26  */
     27 public class RandomAccessFileOutputStream extends OutputStream {
     28   /**
     29    * The backing {@link RandomAccessFile}.
     30    */
     31   private final RandomAccessFile raf;
     32 
     33   /**
     34    * Constructs a new instance that will immediately open the specified file for writing and set
     35    * the length to the specified value.
     36    * @param outputFile the file to wrap
     37    * @param expectedSize if greater than or equal to zero, the size to set the file to immediately;
     38    * otherwise, the file size is not set
     39    * @throws IOException if unable to open the file for writing or set the size
     40    */
     41   public RandomAccessFileOutputStream(File outputFile, long expectedSize) throws IOException {
     42     this.raf = getRandomAccessFile(outputFile);
     43     if (expectedSize >= 0) {
     44       raf.setLength(expectedSize);
     45       if (raf.length() != expectedSize) {
     46         throw new IOException("Unable to set the file size");
     47       }
     48     }
     49   }
     50 
     51   /**
     52    * Given a {@link File}, get a writeable {@link RandomAccessFile} reference for it.
     53    * @param file the file
     54    * @return as described
     55    * @throws IOException if unable to open the file
     56    */
     57   protected RandomAccessFile getRandomAccessFile(File file) throws IOException {
     58     return new RandomAccessFile(file, "rw");
     59   }
     60 
     61   @Override
     62   public void write(int b) throws IOException {
     63     raf.write(b);
     64   }
     65 
     66   @Override
     67   public void write(byte[] b) throws IOException {
     68     write(b, 0, b.length);
     69   }
     70 
     71   @Override
     72   public void write(byte[] b, int off, int len) throws IOException {
     73     raf.write(b, off, len);
     74   }
     75 
     76   @Override
     77   public void flush() throws IOException {
     78     raf.getChannel().force(true);
     79   }
     80 
     81   @Override
     82   public void close() throws IOException {
     83     flush();
     84     raf.close();
     85   }
     86 }
     87