Repository: commons-compress
Updated Branches:
  refs/heads/master 9e32a2ce7 -> 87f0f2ec3


COMPRESS-327 write 7z archives to arbirary SeekableByteChannels - needs 
optimization


Project: http://git-wip-us.apache.org/repos/asf/commons-compress/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-compress/commit/87f0f2ec
Tree: http://git-wip-us.apache.org/repos/asf/commons-compress/tree/87f0f2ec
Diff: http://git-wip-us.apache.org/repos/asf/commons-compress/diff/87f0f2ec

Branch: refs/heads/master
Commit: 87f0f2ec35c600cae7a17621455c00e24256011a
Parents: 9e32a2c
Author: Stefan Bodewig <bode...@apache.org>
Authored: Wed Oct 12 15:54:07 2016 +0200
Committer: Stefan Bodewig <bode...@apache.org>
Committed: Wed Oct 12 15:54:07 2016 +0200

----------------------------------------------------------------------
 .../archivers/sevenz/SevenZOutputFile.java      | 144 +++++++++++--------
 1 file changed, 85 insertions(+), 59 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-compress/blob/87f0f2ec/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFile.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFile.java
 
b/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFile.java
index c2c0171..2a13003 100644
--- 
a/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFile.java
+++ 
b/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFile.java
@@ -24,11 +24,15 @@ import java.io.DataOutputStream;
 import java.io.File;
 import java.io.IOException;
 import java.io.OutputStream;
-import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+import java.nio.channels.SeekableByteChannel;
+import java.nio.file.Files;
+import java.nio.file.StandardOpenOption;
 import java.util.ArrayList;
 import java.util.BitSet;
 import java.util.Collections;
 import java.util.Date;
+import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.List;
 import java.util.LinkedList;
@@ -43,7 +47,7 @@ import org.apache.commons.compress.utils.CountingOutputStream;
  * @since 1.6
  */
 public class SevenZOutputFile implements Closeable {
-    private final RandomAccessFile file;
+    private final SeekableByteChannel channel;
     private final List<SevenZArchiveEntry> files = new ArrayList<>();
     private int numNonEmptyStreams = 0;
     private final CRC32 crc32 = new CRC32();
@@ -55,18 +59,30 @@ public class SevenZOutputFile implements Closeable {
     private Iterable<? extends SevenZMethodConfiguration> contentMethods =
             Collections.singletonList(new 
SevenZMethodConfiguration(SevenZMethod.LZMA2));
     private final Map<SevenZArchiveEntry, long[]> additionalSizes = new 
HashMap<>();
-    
+
     /**
      * Opens file to write a 7z archive to.
      *
-     * @param filename name of the file to write to
+     * @param filename the file to write to
      * @throws IOException if opening the file fails
      */
     public SevenZOutputFile(final File filename) throws IOException {
-        file = new RandomAccessFile(filename, "rw");
-        file.seek(SevenZFile.SIGNATURE_HEADER_SIZE);
+        this(Files.newByteChannel(filename.toPath(),
+            EnumSet.of(StandardOpenOption.CREATE, StandardOpenOption.WRITE,
+                       StandardOpenOption.TRUNCATE_EXISTING)));
+    }
+
+    /**
+     * Prepares channel to write a 7z archive to.
+     *
+     * @param channel the channel to write to
+     * @throws IOException if the channel cannot be positioned properly
+     */
+    public SevenZOutputFile(final SeekableByteChannel channel) throws 
IOException {
+        this.channel = channel;
+        channel.position(SevenZFile.SIGNATURE_HEADER_SIZE);
     }
-    
+
     /**
      * Sets the default compression method to use for entry contents - the
      * default is LZMA2.
@@ -111,9 +127,9 @@ public class SevenZOutputFile implements Closeable {
         if (!finished) {
             finish();
         }
-        file.close();
+        channel.close();
     }
-    
+
     /**
      * Create an archive entry using the inputFile and entryName provided.
      * 
@@ -145,7 +161,7 @@ public class SevenZOutputFile implements Closeable {
         final SevenZArchiveEntry entry = (SevenZArchiveEntry) archiveEntry;
         files.add(entry);
     }
-    
+
     /**
      * Closes the archive entry.
      * @throws IOException on error
@@ -193,7 +209,7 @@ public class SevenZOutputFile implements Closeable {
     public void write(final int b) throws IOException {
         getCurrentOutputStream().write(b);
     }
-    
+
     /**
      * Writes a byte array to the current archive entry.
      * @param b The byte array to be written.
@@ -202,7 +218,7 @@ public class SevenZOutputFile implements Closeable {
     public void write(final byte[] b) throws IOException {
         write(b, 0, b.length);
     }
-    
+
     /**
      * Writes part of a byte array to the current archive entry.
      * @param b The byte array to be written.
@@ -215,7 +231,7 @@ public class SevenZOutputFile implements Closeable {
             getCurrentOutputStream().write(b, off, len);
         }
     }
-    
+
     /**
      * Finishes the addition of entries to this archive, without closing it.
      * 
@@ -226,26 +242,31 @@ public class SevenZOutputFile implements Closeable {
             throw new IOException("This archive has already been finished");
         }
         finished = true;
-        
-        final long headerPosition = file.getFilePointer();
-        
+
+        final long headerPosition = channel.position();
+
+        // TODO use a properly sized buffer for both write operations
+        // and re-write writeHeader and the startHeaderStream
+        // operations to work on ByteBuffer directly.
         final ByteArrayOutputStream headerBaos = new ByteArrayOutputStream();
         final DataOutputStream header = new DataOutputStream(headerBaos);
-        
+
         writeHeader(header);
         header.flush();
         final byte[] headerBytes = headerBaos.toByteArray();
-        file.write(headerBytes);
-        
+        channel.write(ByteBuffer.wrap(headerBytes));
+
         final CRC32 crc32 = new CRC32();
-        
+
         // signature header
-        file.seek(0);
-        file.write(SevenZFile.sevenZSignature);
+        channel.position(0);
+        ByteBuffer bb = ByteBuffer.allocate(SevenZFile.sevenZSignature.length 
+ 2);
+        bb.put(SevenZFile.sevenZSignature);
         // version
-        file.write(0);
-        file.write(2);
-        
+        bb.put((byte) 0).put((byte) 2);
+        bb.flip();
+        channel.write(bb);
+
         // start header
         final ByteArrayOutputStream startHeaderBaos = new 
ByteArrayOutputStream();
         final DataOutputStream startHeaderStream = new 
DataOutputStream(startHeaderBaos);
@@ -258,10 +279,13 @@ public class SevenZOutputFile implements Closeable {
         final byte[] startHeaderBytes = startHeaderBaos.toByteArray();
         crc32.reset();
         crc32.update(startHeaderBytes);
-        file.writeInt(Integer.reverseBytes((int) crc32.getValue()));
-        file.write(startHeaderBytes);
+        bb = ByteBuffer.allocate(startHeaderBytes.length + 4);
+        bb.putInt(Integer.reverseBytes((int) crc32.getValue()));
+        bb.put(startHeaderBytes);
+        bb.flip();
+        channel.write(bb);
     }
-    
+
     /*
      * Creation of output stream is deferred until data is actually
      * written as some codecs might write header information even for
@@ -300,13 +324,13 @@ public class SevenZOutputFile implements Closeable {
                 super.write(b);
                 crc32.update(b);
             }
-    
+
             @Override
             public void write(final byte[] b) throws IOException {
                 super.write(b);
                 crc32.update(b);
             }
-    
+
             @Override
             public void write(final byte[] b, final int off, final int len)
                 throws IOException {
@@ -323,37 +347,37 @@ public class SevenZOutputFile implements Closeable {
 
     private void writeHeader(final DataOutput header) throws IOException {
         header.write(NID.kHeader);
-        
+
         header.write(NID.kMainStreamsInfo);
         writeStreamsInfo(header);
         writeFilesInfo(header);
         header.write(NID.kEnd);
     }
-    
+
     private void writeStreamsInfo(final DataOutput header) throws IOException {
         if (numNonEmptyStreams > 0) {
             writePackInfo(header);
             writeUnpackInfo(header);
         }
-        
+
         writeSubStreamsInfo(header);
-        
+
         header.write(NID.kEnd);
     }
-    
+
     private void writePackInfo(final DataOutput header) throws IOException {
         header.write(NID.kPackInfo);
-        
+
         writeUint64(header, 0);
         writeUint64(header, 0xffffFFFFL & numNonEmptyStreams);
-        
+
         header.write(NID.kSize);
         for (final SevenZArchiveEntry entry : files) {
             if (entry.hasStream()) {
                 writeUint64(header, entry.getCompressedSize());
             }
         }
-        
+
         header.write(NID.kCRC);
         header.write(1); // "allAreDefined" == true
         for (final SevenZArchiveEntry entry : files) {
@@ -361,13 +385,13 @@ public class SevenZOutputFile implements Closeable {
                 header.writeInt(Integer.reverseBytes((int) 
entry.getCompressedCrcValue()));
             }
         }
-        
+
         header.write(NID.kEnd);
     }
-    
+
     private void writeUnpackInfo(final DataOutput header) throws IOException {
         header.write(NID.kUnpackInfo);
-        
+
         header.write(NID.kFolder);
         writeUint64(header, numNonEmptyStreams);
         header.write(0);
@@ -389,7 +413,7 @@ public class SevenZOutputFile implements Closeable {
                 writeUint64(header, entry.getSize());
             }
         }
-        
+
         header.write(NID.kCRC);
         header.write(1); // "allAreDefined" == true
         for (final SevenZArchiveEntry entry : files) {
@@ -397,10 +421,10 @@ public class SevenZOutputFile implements Closeable {
                 header.writeInt(Integer.reverseBytes((int) 
entry.getCrcValue()));
             }
         }
-        
+
         header.write(NID.kEnd);
     }
-    
+
     private void writeFolder(final DataOutput header, final SevenZArchiveEntry 
entry) throws IOException {
         final ByteArrayOutputStream bos = new ByteArrayOutputStream();
         int numCoders = 0;
@@ -434,10 +458,10 @@ public class SevenZOutputFile implements Closeable {
             bos.write(properties);
         }
     }
-    
+
     private void writeSubStreamsInfo(final DataOutput header) throws 
IOException {
         header.write(NID.kSubStreamsInfo);
-//        
+//
 //        header.write(NID.kCRC);
 //        header.write(1);
 //        for (final SevenZArchiveEntry entry : files) {
@@ -445,13 +469,13 @@ public class SevenZOutputFile implements Closeable {
 //                header.writeInt(Integer.reverseBytes(entry.getCrc()));
 //            }
 //        }
-//        
+//
         header.write(NID.kEnd);
     }
-    
+
     private void writeFilesInfo(final DataOutput header) throws IOException {
         header.write(NID.kFilesInfo);
-        
+
         writeUint64(header, files.size());
 
         writeFileEmptyStreams(header);
@@ -464,7 +488,7 @@ public class SevenZOutputFile implements Closeable {
         writeFileWindowsAttributes(header);
         header.write(NID.kEnd);
     }
-    
+
     private void writeFileEmptyStreams(final DataOutput header) throws 
IOException {
         boolean hasEmptyStreams = false;
         for (final SevenZArchiveEntry entry : files) {
@@ -488,7 +512,7 @@ public class SevenZOutputFile implements Closeable {
             header.write(contents);
         }
     }
-    
+
     private void writeFileEmptyFiles(final DataOutput header) throws 
IOException {
         boolean hasEmptyFiles = false;
         int emptyStreamCounter = 0;
@@ -511,7 +535,7 @@ public class SevenZOutputFile implements Closeable {
             header.write(contents);
         }
     }
-    
+
     private void writeFileAntiItems(final DataOutput header) throws 
IOException {
         boolean hasAntiItems = false;
         final BitSet antiItems = new BitSet(0);
@@ -534,10 +558,10 @@ public class SevenZOutputFile implements Closeable {
             header.write(contents);
         }
     }
-    
+
     private void writeFileNames(final DataOutput header) throws IOException {
         header.write(NID.kName);
-        
+
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
         final DataOutputStream out = new DataOutputStream(baos);
         out.write(0);
@@ -740,27 +764,29 @@ public class SevenZOutputFile implements Closeable {
     private class OutputStreamWrapper extends OutputStream {
         @Override
         public void write(final int b) throws IOException {
-            file.write(b);
+            // TODO use a cached ByteBuffer
+            channel.write(ByteBuffer.wrap(new byte[] {(byte) b }));
             compressedCrc32.update(b);
             fileBytesWritten++;
         }
-    
+
         @Override
         public void write(final byte[] b) throws IOException {
             OutputStreamWrapper.this.write(b, 0, b.length);
         }
-    
+
         @Override
         public void write(final byte[] b, final int off, final int len)
             throws IOException {
-            file.write(b, off, len);
+            // TODO use a cached ByteBuffer
+            channel.write(ByteBuffer.wrap(b, off, len));
             compressedCrc32.update(b, off, len);
             fileBytesWritten += len;
         }
 
         @Override
         public void flush() throws IOException {
-            // no reason to flush a RandomAccessFile
+            // no reason to flush the channel
         }
 
         @Override

Reply via email to