This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-compress.git

commit b7ba0ced5c950e59214329ae7b102783a5807d2c
Author: Gary Gregory <garydgreg...@gmail.com>
AuthorDate: Mon Jan 15 20:01:04 2024 -0500

    Add SevenZFile.builder(), add SevenZFile.Builder, deprecate constructors
---
 src/changes/changes.xml                            |   3 +-
 .../apache/commons/compress/archivers/Lister.java  |   2 +-
 .../compress/archivers/examples/Expander.java      |   2 +-
 .../commons/compress/archivers/sevenz/CLI.java     |   8 +-
 .../compress/archivers/sevenz/SevenZFile.java      | 287 +++++++++++++++++----
 .../archivers/sevenz/SevenZFileOptions.java        |  37 ++-
 src/site/xdoc/examples.xml                         |   8 +-
 .../commons/compress/archivers/SevenZTest.java     |   6 +-
 .../compress/archivers/examples/ExpanderTest.java  |   4 +-
 .../archivers/examples/SevenZArchiverTest.java     |   2 +-
 .../compress/archivers/sevenz/SevenZFileTest.java  | 180 +++++++++----
 .../archivers/sevenz/SevenZOutputFileTest.java     |  17 +-
 12 files changed, 409 insertions(+), 147 deletions(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 8d0898977..5379eecdc 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -75,7 +75,8 @@ The <action> type attribute can be add,update,fix,remove.
       <action type="fix" dev="ggregory" due-to="Gary Gregory">Deprecate 
ByteUtils.fromLittleEndian(InputStream, int).</action>
       <action type="fix" dev="ggregory" due-to="Gary Gregory">Deprecate 
ByteUtils.toLittleEndian(DataOutput, long, int).</action>
       <!-- ADD -->
-      <action type="add" dev="ggregory" due-to="Gary Gregory">Add 
ZipFile.builder(), add ZipFile.Builder, deprecated constructors.</action>     
+      <action type="add" dev="ggregory" due-to="Gary Gregory">Add 
ZipFile.builder(), add ZipFile.Builder, deprecate constructors.</action>  
+      <action type="add" dev="ggregory" due-to="Gary Gregory">Add 
SevenZFile.builder(), add SevenZFile.Builder, deprecate constructors.</action>  
       <!-- UPDATE -->
       <action type="update" dev="ggregory" due-to="Gary Gregory">Bump 
commons-lang3 from 3.13.0 to 3.14.0.</action>
       <action type="update" dev="ggregory" due-to="Dependabot">Bump 
com.github.marschall:memoryfilesystem from 2.6.1 to 2.8.0 #444, #458.</action>
diff --git a/src/main/java/org/apache/commons/compress/archivers/Lister.java 
b/src/main/java/org/apache/commons/compress/archivers/Lister.java
index 77ce67024..6ca1de34d 100644
--- a/src/main/java/org/apache/commons/compress/archivers/Lister.java
+++ b/src/main/java/org/apache/commons/compress/archivers/Lister.java
@@ -61,7 +61,7 @@ public final class Lister {
     }
 
     private static void list7z(final File file) throws IOException {
-        try (SevenZFile sevenZFile = new SevenZFile(file)) {
+        try (SevenZFile sevenZFile = SevenZFile.builder().setFile(file).get()) 
{
             System.out.println("Created " + sevenZFile);
             ArchiveEntry entry;
             while ((entry = sevenZFile.getNextEntry()) != null) {
diff --git 
a/src/main/java/org/apache/commons/compress/archivers/examples/Expander.java 
b/src/main/java/org/apache/commons/compress/archivers/examples/Expander.java
index f8325891e..29ad6ec83 100644
--- a/src/main/java/org/apache/commons/compress/archivers/examples/Expander.java
+++ b/src/main/java/org/apache/commons/compress/archivers/examples/Expander.java
@@ -412,7 +412,7 @@ public class Expander {
             } else if (ArchiveStreamFactory.ZIP.equalsIgnoreCase(format)) {
                 
expand(c.track(ZipFile.builder().setSeekableByteChannel(archive).get()), 
targetDirectory);
             } else if (ArchiveStreamFactory.SEVEN_Z.equalsIgnoreCase(format)) {
-                expand(c.track(new SevenZFile(archive)), targetDirectory);
+                
expand(c.track(SevenZFile.builder().setSeekableByteChannel(archive).get()), 
targetDirectory);
             } else {
                 // never reached as prefersSeekableByteChannel only returns 
true for TAR, ZIP and 7z
                 throw new ArchiveException("Don't know how to handle format " 
+ format);
diff --git 
a/src/main/java/org/apache/commons/compress/archivers/sevenz/CLI.java 
b/src/main/java/org/apache/commons/compress/archivers/sevenz/CLI.java
index ffd144250..6abc3e7e1 100644
--- a/src/main/java/org/apache/commons/compress/archivers/sevenz/CLI.java
+++ b/src/main/java/org/apache/commons/compress/archivers/sevenz/CLI.java
@@ -91,11 +91,11 @@ public class CLI {
         }
         final Mode mode = grabMode(args);
         System.out.println(mode.getMessage() + " " + args[0]);
-        final File f = new File(args[0]);
-        if (!f.isFile()) {
-            System.err.println(f + " doesn't exist or is a directory");
+        final File file = new File(args[0]);
+        if (!file.isFile()) {
+            System.err.println(file + " doesn't exist or is a directory");
         }
-        try (SevenZFile archive = new SevenZFile(f)) {
+        try (SevenZFile archive = SevenZFile.builder().setFile(file).get()) {
             SevenZArchiveEntry ae;
             while ((ae = archive.getNextEntry()) != null) {
                 mode.takeAction(archive, ae);
diff --git 
a/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java 
b/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java
index 86d969cf1..0a3f4c630 100644
--- a/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java
+++ b/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java
@@ -32,6 +32,8 @@ import java.nio.ByteOrder;
 import java.nio.channels.Channels;
 import java.nio.channels.SeekableByteChannel;
 import java.nio.file.Files;
+import java.nio.file.OpenOption;
+import java.nio.file.Path;
 import java.nio.file.StandardOpenOption;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -51,6 +53,9 @@ import org.apache.commons.compress.utils.ByteUtils;
 import org.apache.commons.compress.utils.CRC32VerifyingInputStream;
 import org.apache.commons.compress.utils.IOUtils;
 import org.apache.commons.compress.utils.InputStreamStatistics;
+import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
+import org.apache.commons.io.build.AbstractOrigin.ByteArrayOrigin;
+import org.apache.commons.io.build.AbstractStreamBuilder;
 
 /**
  * Reads a 7z file, using SeekableByteChannel under the covers.
@@ -76,6 +81,7 @@ import 
org.apache.commons.compress.utils.InputStreamStatistics;
  * @since 1.6
  */
 public class SevenZFile implements Closeable {
+
     private static final class ArchiveStatistics {
         private int numberOfPackedStreams;
         private long numberOfCoders;
@@ -145,6 +151,147 @@ public class SevenZFile implements Closeable {
         }
     }
 
+    /**
+     * Builds new instances of {@link SevenZFile}.
+     *
+     * @since 1.26.0
+     */
+    public static class Builder extends AbstractStreamBuilder<SevenZFile, 
Builder> {
+
+        static final int MEMORY_LIMIT_IN_KB = Integer.MAX_VALUE;
+        static final boolean USE_DEFAULTNAME_FOR_UNNAMED_ENTRIES = false;
+        static final boolean TRY_TO_RECOVER_BROKEN_ARCHIVES = false;
+
+        private SeekableByteChannel seekableByteChannel;
+        private String defaultName = DEFAULT_FILE_NAME;
+        private byte[] password;
+        private int maxMemoryLimitKb = MEMORY_LIMIT_IN_KB;
+        private boolean useDefaultNameForUnnamedEntries = 
USE_DEFAULTNAME_FOR_UNNAMED_ENTRIES;
+        private boolean tryToRecoverBrokenArchives = 
TRY_TO_RECOVER_BROKEN_ARCHIVES;
+
+        @SuppressWarnings("resource") // Caller closes
+        @Override
+        public SevenZFile get() throws IOException {
+            final SeekableByteChannel actualChannel;
+            final String actualDescription;
+            if (seekableByteChannel != null) {
+                actualChannel = seekableByteChannel;
+                actualDescription = defaultName;
+            } else if (checkOrigin() instanceof ByteArrayOrigin) {
+                actualChannel = new 
SeekableInMemoryByteChannel(checkOrigin().getByteArray());
+                actualDescription = defaultName;
+            } else {
+                OpenOption[] openOptions = getOpenOptions();
+                if (openOptions.length == 0) {
+                    openOptions = new OpenOption[] { StandardOpenOption.READ };
+                }
+                final Path path = getPath();
+                actualChannel = Files.newByteChannel(path, openOptions);
+                actualDescription = path.toAbsolutePath().toString();
+            }
+            final boolean closeOnError = seekableByteChannel != null;
+            return new SevenZFile(actualChannel, actualDescription, password, 
closeOnError, maxMemoryLimitKb, useDefaultNameForUnnamedEntries,
+                    tryToRecoverBrokenArchives);
+        }
+
+        /**
+         * Sets the default name.
+         *
+         * @param defaultName the default name.
+         * @return this.
+         */
+        public Builder setDefaultName(final String defaultName) {
+            this.defaultName = defaultName;
+            return this;
+        }
+
+        /**
+         * Sets the maximum amount of memory in kilobytes to use for parsing 
the archive and during extraction.
+         * <p>
+         * Not all codecs honor this setting. Currently only LZMA and LZMA2 
are supported.
+         * </p>
+         *
+         * @param maxMemoryLimitKb the max memory limit in kilobytes.
+         * @return this.
+         */
+        public Builder setMaxMemoryLimitKb(final int maxMemoryLimitKb) {
+            this.maxMemoryLimitKb = maxMemoryLimitKb;
+            return this;
+        }
+
+        /**
+         * Sets the password.
+         *
+         * @param password the password.
+         * @return this.
+         */
+        public Builder setPassword(final byte[] password) {
+            this.password = password != null ? password.clone() : null;
+            return this;
+        }
+
+        /**
+         * Sets the password.
+         *
+         * @param password the password.
+         * @return this.
+         */
+        public Builder setPassword(final char[] password) {
+            this.password = password != null ? 
AES256SHA256Decoder.utf16Decode(password.clone()) : null;
+            return this;
+        }
+
+        /**
+         * Sets the password.
+         *
+         * @param password the password.
+         * @return this.
+         */
+        public Builder setPassword(final String password) {
+            this.password = password != null ? 
AES256SHA256Decoder.utf16Decode(password.toCharArray()) : null;
+            return this;
+        }
+
+        /**
+         * Sets the input channel.
+         *
+         * @param seekableByteChannel the input channel.
+         * @return this.
+         */
+        public Builder setSeekableByteChannel(final SeekableByteChannel 
seekableByteChannel) {
+            this.seekableByteChannel = seekableByteChannel;
+            return this;
+        }
+
+        /**
+         * Sets whether {@link SevenZFile} will try to recover broken archives 
where the CRC of the file's metadata is 0.
+         * <p>
+         * This special kind of broken archive is encountered when mutli 
volume archives are closed prematurely. If you enable this option SevenZFile 
will trust
+         * data that looks as if it could contain metadata of an archive and 
allocate big amounts of memory. It is strongly recommended to not enable this
+         * option without setting {@link #setMaxMemoryLimitKb(int)} at the 
same time.
+         * </p>
+         *
+         * @param tryToRecoverBrokenArchives whether {@link SevenZFile} will 
try to recover broken archives where the CRC of the file's metadata is 0.
+         * @return this.
+         */
+        public Builder setTryToRecoverBrokenArchives(final boolean 
tryToRecoverBrokenArchives) {
+            this.tryToRecoverBrokenArchives = tryToRecoverBrokenArchives;
+            return this;
+        }
+
+        /**
+         * Sets whether entries without a name should get their names set to 
the archive's default file name.
+         *
+         * @param useDefaultNameForUnnamedEntries whether entries without a 
name should get their names set to the archive's default file name.
+         * @return this.
+         */
+        public Builder setUseDefaultNameForUnnamedEntries(final boolean 
useDefaultNameForUnnamedEntries) {
+            this.useDefaultNameForUnnamedEntries = 
useDefaultNameForUnnamedEntries;
+            return this;
+        }
+
+    }
+
     static final int SIGNATURE_HEADER_SIZE = 32;
 
     private static final String DEFAULT_FILE_NAME = "unknown archive";
@@ -160,6 +307,16 @@ public class SevenZFile implements Closeable {
         return (int) value;
     }
 
+    /**
+     * Creates a new Builder.
+     *
+     * @return a new Builder.
+     * @since 1.26.0
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
     private static ByteBuffer checkEndOfFile(final ByteBuffer buf, final int 
expectRemaining) throws EOFException {
         final int remaining = buf.remaining();
         if (remaining < expectRemaining) {
@@ -203,7 +360,6 @@ public class SevenZFile implements Closeable {
         if (length < sevenZSignature.length) {
             return false;
         }
-
         for (int i = 0; i < sevenZSignature.length; i++) {
             if (signature[i] != sevenZSignature[i]) {
                 return false;
@@ -212,6 +368,10 @@ public class SevenZFile implements Closeable {
         return true;
     }
 
+    private static SeekableByteChannel newByteChannel(final File file) throws 
IOException {
+        return Files.newByteChannel(file.toPath(), 
EnumSet.of(StandardOpenOption.READ));
+    }
+
     private static long readUint64(final ByteBuffer in) throws IOException {
         // long rather than int as it might get shifted beyond the range of an 
int
         final long firstByte = getUnsignedByte(in);
@@ -242,33 +402,28 @@ public class SevenZFile implements Closeable {
     }
 
     private final String fileName;
-
     private SeekableByteChannel channel;
-
     private final Archive archive;
-
     private int currentEntryIndex = -1;
-
     private int currentFolderIndex = -1;
-
     private InputStream currentFolderInputStream;
-
     private byte[] password;
-
-    private final SevenZFileOptions options;
-
     private long compressedBytesReadFromCurrentEntry;
-
     private long uncompressedBytesReadFromCurrentEntry;
-
     private final ArrayList<InputStream> deferredBlockStreams = new 
ArrayList<>();
+    private final int maxMemoryLimitKb;
+    private final boolean useDefaultNameForUnnamedEntries;
+
+    private final boolean tryToRecoverBrokenArchives;
 
     /**
-     * Reads a file as unencrypted 7z archive
+     * Reads a file as unencrypted 7z archive.
      *
-     * @param fileName the file to read
-     * @throws IOException if reading the archive fails
+     * @param fileName the file to read.
+     * @throws IOException if reading the archive fails.
+     * @deprecated Use {@link Builder#get()}.
      */
+    @Deprecated
     public SevenZFile(final File fileName) throws IOException {
         this(fileName, SevenZFileOptions.DEFAULT);
     }
@@ -276,53 +431,60 @@ public class SevenZFile implements Closeable {
     /**
      * Reads a file as 7z archive
      *
-     * @param fileName the file to read
+     * @param file     the file to read
      * @param password optional password if the archive is encrypted - the 
byte array is supposed to be the UTF16-LE encoded representation of the 
password.
      * @throws IOException if reading the archive fails
-     * @deprecated use the char[]-arg version for the password instead
+     * @deprecated Use {@link Builder#get()}.
      */
+    @SuppressWarnings("resource") // caller closes
     @Deprecated
-    public SevenZFile(final File fileName, final byte[] password) throws 
IOException {
-        this(Files.newByteChannel(fileName.toPath(), 
EnumSet.of(StandardOpenOption.READ)), fileName.getAbsolutePath(), password, 
true,
-                SevenZFileOptions.DEFAULT);
+    public SevenZFile(final File file, final byte[] password) throws 
IOException {
+        this(newByteChannel(file), file.getAbsolutePath(), password, true, 
SevenZFileOptions.DEFAULT);
     }
 
     /**
      * Reads a file as 7z archive
      *
-     * @param fileName the file to read
+     * @param file     the file to read
      * @param password optional password if the archive is encrypted
      * @throws IOException if reading the archive fails
      * @since 1.17
+     * @deprecated Use {@link Builder#get()}.
      */
-    public SevenZFile(final File fileName, final char[] password) throws 
IOException {
-        this(fileName, password, SevenZFileOptions.DEFAULT);
+    @Deprecated
+    public SevenZFile(final File file, final char[] password) throws 
IOException {
+        this(file, password, SevenZFileOptions.DEFAULT);
     }
 
     /**
      * Reads a file as 7z archive with additional options.
      *
-     * @param fileName the file to read
+     * @param file     the file to read
      * @param password optional password if the archive is encrypted
      * @param options  the options to apply
      * @throws IOException if reading the archive fails or the memory limit 
(if set) is too small
      * @since 1.19
+     * @deprecated Use {@link Builder#get()}.
      */
-    public SevenZFile(final File fileName, final char[] password, final 
SevenZFileOptions options) throws IOException {
-        this(Files.newByteChannel(fileName.toPath(), 
EnumSet.of(StandardOpenOption.READ)), // NOSONAR
-                fileName.getAbsolutePath(), 
AES256SHA256Decoder.utf16Decode(password), true, options);
+    @SuppressWarnings("resource") // caller closes
+    @Deprecated
+    public SevenZFile(final File file, final char[] password, final 
SevenZFileOptions options) throws IOException {
+        this(newByteChannel(file), // NOSONAR
+                file.getAbsolutePath(), 
AES256SHA256Decoder.utf16Decode(password), true, options);
     }
 
     /**
      * Reads a file as unencrypted 7z archive
      *
-     * @param fileName the file to read
-     * @param options  the options to apply
+     * @param file    the file to read
+     * @param options the options to apply
      * @throws IOException if reading the archive fails or the memory limit 
(if set) is too small
      * @since 1.19
+     * @deprecated Use {@link Builder#get()}.
      */
-    public SevenZFile(final File fileName, final SevenZFileOptions options) 
throws IOException {
-        this(fileName, null, options);
+    @Deprecated
+    public SevenZFile(final File file, final SevenZFileOptions options) throws 
IOException {
+        this(file, null, options);
     }
 
     /**
@@ -334,7 +496,9 @@ public class SevenZFile implements Closeable {
      * @param channel the channel to read
      * @throws IOException if reading the archive fails
      * @since 1.13
+     * @deprecated Use {@link Builder#get()}.
      */
+    @Deprecated
     public SevenZFile(final SeekableByteChannel channel) throws IOException {
         this(channel, SevenZFileOptions.DEFAULT);
     }
@@ -349,7 +513,7 @@ public class SevenZFile implements Closeable {
      * @param password optional password if the archive is encrypted - the 
byte array is supposed to be the UTF16-LE encoded representation of the 
password.
      * @throws IOException if reading the archive fails
      * @since 1.13
-     * @deprecated use the char[]-arg version for the password instead
+     * @deprecated Use {@link Builder#get()}.
      */
     @Deprecated
     public SevenZFile(final SeekableByteChannel channel, final byte[] 
password) throws IOException {
@@ -366,7 +530,9 @@ public class SevenZFile implements Closeable {
      * @param password optional password if the archive is encrypted
      * @throws IOException if reading the archive fails
      * @since 1.17
+     * @deprecated Use {@link Builder#get()}.
      */
+    @Deprecated
     public SevenZFile(final SeekableByteChannel channel, final char[] 
password) throws IOException {
         this(channel, password, SevenZFileOptions.DEFAULT);
     }
@@ -382,7 +548,9 @@ public class SevenZFile implements Closeable {
      * @param options  the options to apply
      * @throws IOException if reading the archive fails or the memory limit 
(if set) is too small
      * @since 1.19
+     * @deprecated Use {@link Builder#get()}.
      */
+    @Deprecated
     public SevenZFile(final SeekableByteChannel channel, final char[] 
password, final SevenZFileOptions options) throws IOException {
         this(channel, DEFAULT_FILE_NAME, password, options);
     }
@@ -397,7 +565,9 @@ public class SevenZFile implements Closeable {
      * @param options the options to apply
      * @throws IOException if reading the archive fails or the memory limit 
(if set) is too small
      * @since 1.19
+     * @deprecated Use {@link Builder#get()}.
      */
+    @Deprecated
     public SevenZFile(final SeekableByteChannel channel, final 
SevenZFileOptions options) throws IOException {
         this(channel, DEFAULT_FILE_NAME, null, options);
     }
@@ -412,7 +582,9 @@ public class SevenZFile implements Closeable {
      * @param fileName name of the archive - only used for error reporting
      * @throws IOException if reading the archive fails
      * @since 1.17
+     * @deprecated Use {@link Builder#get()}.
      */
+    @Deprecated
     public SevenZFile(final SeekableByteChannel channel, final String 
fileName) throws IOException {
         this(channel, fileName, SevenZFileOptions.DEFAULT);
     }
@@ -428,19 +600,21 @@ public class SevenZFile implements Closeable {
      * @param password optional password if the archive is encrypted - the 
byte array is supposed to be the UTF16-LE encoded representation of the 
password.
      * @throws IOException if reading the archive fails
      * @since 1.13
-     * @deprecated use the char[]-arg version for the password instead
+     * @deprecated Use {@link Builder#get()}.
      */
     @Deprecated
     public SevenZFile(final SeekableByteChannel channel, final String 
fileName, final byte[] password) throws IOException {
         this(channel, fileName, password, false, SevenZFileOptions.DEFAULT);
     }
 
-    private SevenZFile(final SeekableByteChannel channel, final String 
fileName, final byte[] password, final boolean closeOnError,
-            final SevenZFileOptions options) throws IOException {
+    private SevenZFile(final SeekableByteChannel channel, final String 
fileName, final byte[] password, final boolean closeOnError, final int 
maxMemoryLimitKb,
+            final boolean useDefaultNameForUnnamedEntries, final boolean 
tryToRecoverBrokenArchives) throws IOException {
         boolean succeeded = false;
         this.channel = channel;
         this.fileName = fileName;
-        this.options = options;
+        this.maxMemoryLimitKb = maxMemoryLimitKb;
+        this.useDefaultNameForUnnamedEntries = useDefaultNameForUnnamedEntries;
+        this.tryToRecoverBrokenArchives = tryToRecoverBrokenArchives;
         try {
             archive = readHeaders(password);
             if (password != null) {
@@ -456,6 +630,24 @@ public class SevenZFile implements Closeable {
         }
     }
 
+    /**
+     * Constructs a new instance.
+     *
+     * @param channel      the channel to read.
+     * @param fileName     name of the archive - only used for error reporting.
+     * @param password     optional password if the archive is encrypted.
+     * @param closeOnError closes the channel on error.
+     * @param options      options.
+     * @throws IOException if reading the archive fails
+     * @deprecated Use {@link Builder#get()}.
+     */
+    @Deprecated
+    private SevenZFile(final SeekableByteChannel channel, final String 
fileName, final byte[] password, final boolean closeOnError,
+            final SevenZFileOptions options) throws IOException {
+        this(channel, fileName, password, closeOnError, 
options.getMaxMemoryLimitInKb(), options.getUseDefaultNameForUnnamedEntries(),
+                options.getTryToRecoverBrokenArchives());
+    }
+
     /**
      * Reads a SeekableByteChannel as 7z archive
      * <p>
@@ -467,7 +659,9 @@ public class SevenZFile implements Closeable {
      * @param password optional password if the archive is encrypted
      * @throws IOException if reading the archive fails
      * @since 1.17
+     * @deprecated Use {@link Builder#get()}.
      */
+    @Deprecated
     public SevenZFile(final SeekableByteChannel channel, final String 
fileName, final char[] password) throws IOException {
         this(channel, fileName, password, SevenZFileOptions.DEFAULT);
     }
@@ -484,7 +678,9 @@ public class SevenZFile implements Closeable {
      * @param options  the options to apply
      * @throws IOException if reading the archive fails or the memory limit 
(if set) is too small
      * @since 1.19
+     * @deprecated Use {@link Builder#get()}.
      */
+    @Deprecated
     public SevenZFile(final SeekableByteChannel channel, final String 
fileName, final char[] password, final SevenZFileOptions options) throws 
IOException {
         this(channel, fileName, AES256SHA256Decoder.utf16Decode(password), 
false, options);
     }
@@ -500,7 +696,9 @@ public class SevenZFile implements Closeable {
      * @param options  the options to apply
      * @throws IOException if reading the archive fails or the memory limit 
(if set) is too small
      * @since 1.19
+     * @deprecated Use {@link Builder#get()}.
      */
+    @Deprecated
     public SevenZFile(final SeekableByteChannel channel, final String 
fileName, final SevenZFileOptions options) throws IOException {
         this(channel, fileName, null, false, options);
     }
@@ -546,8 +744,7 @@ public class SevenZFile implements Closeable {
                 throw new IOException("Multi input/output stream coders are 
not yet supported");
             }
             final SevenZMethod method = 
SevenZMethod.byId(coder.decompressionMethodId);
-            inputStreamStack = Coders.addDecoder(fileName, inputStreamStack, 
folder.getUnpackSizeForCoder(coder), coder, password,
-                    options.getMaxMemoryLimitInKb());
+            inputStreamStack = Coders.addDecoder(fileName, inputStreamStack, 
folder.getUnpackSizeForCoder(coder), coder, password, maxMemoryLimitKb);
             methods.addFirst(new SevenZMethodConfiguration(method, 
Coders.findByMethod(method).getOptionsFromCoder(coder, inputStreamStack)));
         }
         entry.setContentMethods(methods);
@@ -558,8 +755,8 @@ public class SevenZFile implements Closeable {
     }
 
     /**
-     * Builds the decoding stream for the entry to be read. This method may be 
called from a random access(getInputStream) or sequential access(getNextEntry). 
If
-     * this method is called from a random access, some entries may need to be 
skipped(we put them to the deferredBlockStreams and skip them when actually
+     * Builds the decoding stream for the entry to be read. This method may be 
called from a random access(getInputStream) or sequential access(getNextEntry).
+     * If this method is called from a random access, some entries may need to 
be skipped(we put them to the deferredBlockStreams and skip them when actually
      * needed to improve the performance)
      *
      * @param entryIndex     the index of the entry to be read
@@ -808,7 +1005,7 @@ public class SevenZFile implements Closeable {
         }
         ++currentEntryIndex;
         final SevenZArchiveEntry entry = archive.files[currentEntryIndex];
-        if (entry.getName() == null && 
options.getUseDefaultNameForUnnamedEntries()) {
+        if (entry.getName() == null && useDefaultNameForUnnamedEntries) {
             entry.setName(getDefaultName());
         }
         buildDecodingStream(currentEntryIndex, false);
@@ -982,7 +1179,7 @@ public class SevenZFile implements Closeable {
         final int pos = header.position();
         final ArchiveStatistics stats = new ArchiveStatistics();
         sanityCheckStreamsInfo(header, stats);
-        stats.assertValidity(options.getMaxMemoryLimitInKb());
+        stats.assertValidity(maxMemoryLimitKb);
         header.position(pos);
 
         readStreamsInfo(header, archive);
@@ -1006,7 +1203,7 @@ public class SevenZFile implements Closeable {
                 throw new IOException("Multi input/output stream coders are 
not yet supported");
             }
             inputStreamStack = Coders.addDecoder(fileName, inputStreamStack, 
// NOSONAR
-                    folder.getUnpackSizeForCoder(coder), coder, password, 
options.getMaxMemoryLimitInKb());
+                    folder.getUnpackSizeForCoder(coder), coder, password, 
maxMemoryLimitKb);
         }
         if (folder.hasCrc) {
             inputStreamStack = new CRC32VerifyingInputStream(inputStreamStack, 
folder.getUnpackSize(), folder.crc);
@@ -1244,7 +1441,7 @@ public class SevenZFile implements Closeable {
     private void readHeader(final ByteBuffer header, final Archive archive) 
throws IOException {
         final int pos = header.position();
         final ArchiveStatistics stats = 
sanityCheckAndCollectStatistics(header);
-        stats.assertValidity(options.getMaxMemoryLimitInKb());
+        stats.assertValidity(maxMemoryLimitKb);
         header.position(pos);
 
         int nid = getUnsignedByte(header);
@@ -1308,7 +1505,7 @@ public class SevenZFile implements Closeable {
             return initializeArchive(readStartHeader(startHeaderCrc), 
password, true);
         }
         // No valid header found - probably first file of multipart archive 
was removed too early. Scan for end header.
-        if (options.getTryToRecoverBrokenArchives()) {
+        if (tryToRecoverBrokenArchives) {
             return tryToLocateEndHeader(password);
         }
         throw new IOException("archive seems to be invalid.\nYou may want to 
retry and enable the"
diff --git 
a/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFileOptions.java
 
b/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFileOptions.java
index 0a2b4f451..d7545784a 100644
--- 
a/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFileOptions.java
+++ 
b/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFileOptions.java
@@ -21,17 +21,21 @@ package org.apache.commons.compress.archivers.sevenz;
  *
  * @since 1.19
  * @Immutable
+ * @deprecated Use {@link SevenZFile.Builder}.
  */
+@Deprecated
 public class SevenZFileOptions {
+
     /**
      * Mutable builder for the immutable {@link SevenZFileOptions}.
      *
      * @since 1.19
      */
     public static class Builder {
-        private int maxMemoryLimitInKb = DEFAUL_MEMORY_LIMIT_IN_KB;
-        private boolean useDefaultNameForUnnamedEntries = 
DEFAULT_USE_DEFAULTNAME_FOR_UNNAMED_ENTRIES;
-        private boolean tryToRecoverBrokenArchives = 
DEFAULT_TRY_TO_RECOVER_BROKEN_ARCHIVES;
+
+        private int maxMemoryLimitKb = SevenZFile.Builder.MEMORY_LIMIT_IN_KB;
+        private boolean useDefaultNameForUnnamedEntries = 
SevenZFile.Builder.USE_DEFAULTNAME_FOR_UNNAMED_ENTRIES;
+        private boolean tryToRecoverBrokenArchives = 
SevenZFile.Builder.TRY_TO_RECOVER_BROKEN_ARCHIVES;
 
         /**
          * Builds the {@link SevenZFileOptions}.
@@ -39,12 +43,11 @@ public class SevenZFileOptions {
          * @return configured {@link SevenZFileOptions}.
          */
         public SevenZFileOptions build() {
-            return new SevenZFileOptions(maxMemoryLimitInKb, 
useDefaultNameForUnnamedEntries, tryToRecoverBrokenArchives);
+            return new SevenZFileOptions(maxMemoryLimitKb, 
useDefaultNameForUnnamedEntries, tryToRecoverBrokenArchives);
         }
 
         /**
          * Sets the maximum amount of memory to use for parsing the archive 
and during extraction.
-         *
          * <p>
          * Not all codecs will honor this setting. Currently only LZMA and 
LZMA2 are supported.
          * </p>
@@ -53,12 +56,12 @@ public class SevenZFileOptions {
          * @return the reconfigured builder
          */
         public Builder withMaxMemoryLimitInKb(final int maxMemoryLimitInKb) {
-            this.maxMemoryLimitInKb = maxMemoryLimitInKb;
+            this.maxMemoryLimitKb = maxMemoryLimitInKb;
             return this;
         }
 
         /**
-         * Sets whether {@link SevenZFile} will try to revover broken archives 
where the CRC of the file's metadata is 0.
+         * Sets whether {@link SevenZFile} will try to recover broken archives 
where the CRC of the file's metadata is 0.
          * <p>
          * This special kind of broken archive is encountered when mutli 
volume archives are closed prematurely. If you enable this option SevenZFile 
will trust
          * data that looks as if it could contain metadata of an archive and 
allocate big amounts of memory. It is strongly recommended to not enable this
@@ -86,20 +89,15 @@ public class SevenZFileOptions {
         }
     }
 
-    private static final int DEFAUL_MEMORY_LIMIT_IN_KB = Integer.MAX_VALUE;
-    private static final boolean DEFAULT_USE_DEFAULTNAME_FOR_UNNAMED_ENTRIES = 
false;
-
-    private static final boolean DEFAULT_TRY_TO_RECOVER_BROKEN_ARCHIVES = 
false;
     /**
      * The default options.
-     *
      * <ul>
      * <li>no memory limit</li>
      * <li>don't modify the name of unnamed entries</li>
      * </ul>
      */
-    public static final SevenZFileOptions DEFAULT = new 
SevenZFileOptions(DEFAUL_MEMORY_LIMIT_IN_KB, 
DEFAULT_USE_DEFAULTNAME_FOR_UNNAMED_ENTRIES,
-            DEFAULT_TRY_TO_RECOVER_BROKEN_ARCHIVES);
+    public static final SevenZFileOptions DEFAULT = new 
SevenZFileOptions(SevenZFile.Builder.MEMORY_LIMIT_IN_KB,
+            SevenZFile.Builder.USE_DEFAULTNAME_FOR_UNNAMED_ENTRIES, 
SevenZFile.Builder.TRY_TO_RECOVER_BROKEN_ARCHIVES);
 
     /**
      * Obtains a builder for SevenZFileOptions.
@@ -110,21 +108,18 @@ public class SevenZFileOptions {
         return new Builder();
     }
 
-    private final int maxMemoryLimitInKb;
-
+    private final int maxMemoryLimitKb;
     private final boolean useDefaultNameForUnnamedEntries;
-
     private final boolean tryToRecoverBrokenArchives;
 
-    private SevenZFileOptions(final int maxMemoryLimitInKb, final boolean 
useDefaultNameForUnnamedEntries, final boolean tryToRecoverBrokenArchives) {
-        this.maxMemoryLimitInKb = maxMemoryLimitInKb;
+    private SevenZFileOptions(final int maxMemoryLimitKb, final boolean 
useDefaultNameForUnnamedEntries, final boolean tryToRecoverBrokenArchives) {
+        this.maxMemoryLimitKb = maxMemoryLimitKb;
         this.useDefaultNameForUnnamedEntries = useDefaultNameForUnnamedEntries;
         this.tryToRecoverBrokenArchives = tryToRecoverBrokenArchives;
     }
 
     /**
      * Gets the maximum amount of memory to use for parsing the archive and 
during extraction.
-     *
      * <p>
      * Not all codecs will honor this setting. Currently only LZMA and LZMA2 
are supported.
      * </p>
@@ -132,7 +127,7 @@ public class SevenZFileOptions {
      * @return the maximum amount of memory to use for extraction
      */
     public int getMaxMemoryLimitInKb() {
-        return maxMemoryLimitInKb;
+        return maxMemoryLimitKb;
     }
 
     /**
diff --git a/src/site/xdoc/examples.xml b/src/site/xdoc/examples.xml
index 830f8bbea..cba989804 100644
--- a/src/site/xdoc/examples.xml
+++ b/src/site/xdoc/examples.xml
@@ -433,13 +433,13 @@ LOOP UNTIL entry.getSize() HAS BEEN READ {
 
         <h4><a name="Recovering from Certain Broken 7z 
Archives"></a>Recovering from Certain Broken 7z Archives</h4>
 
-        <p>Starting with Compress 1.19 <code>SevenZFile</code> tries
+        <p><code>SevenZFile</code> tries
         to recover archives that look as if they were part of a
         multi-volume archive where the first volume has been removed
         too early.</p>
 
-        <p>Starting with Compress 1.21 this option has to be enabled
-        explicitly in <code>SevenZFileOptions</code>. The way recovery
+        <p>This option has to be enabled
+        explicitly in <code>SevenZFile.Builder</code>. The way recovery
         works is by Compress scanning an archive from the end for
         something that might look like valid 7z metadata and use that,
         if it can successfully parse the block of data. When doing so
@@ -447,7 +447,7 @@ LOOP UNTIL entry.getSize() HAS BEEN READ {
         metadata of very large archives which in turn may make
         Compress allocate a lot of memory. Therefore we strongly
         recommend you also set a memory limit inside the
-        <code>SevenZFileOptions</code> if you enable recovery.</p>
+        <code>SevenZFile.Builder</code> if you enable recovery.</p>
       </subsection>
 
       <subsection name="ar">
diff --git 
a/src/test/java/org/apache/commons/compress/archivers/SevenZTest.java 
b/src/test/java/org/apache/commons/compress/archivers/SevenZTest.java
index aa16e5b54..aa4c44627 100644
--- a/src/test/java/org/apache/commons/compress/archivers/SevenZTest.java
+++ b/src/test/java/org/apache/commons/compress/archivers/SevenZTest.java
@@ -92,7 +92,7 @@ public class SevenZTest extends AbstractTest {
 
     private void multiByteReadConsistentlyReturnsMinusOneAtEof(final 
SevenZMethod method) throws Exception {
         createArchive(method);
-        try (SevenZFile archive = new SevenZFile(output)) {
+        try (SevenZFile archive = SevenZFile.builder().setFile(output).get()) {
             multiByteReadConsistentlyReturnsMinusOneAtEof(archive);
         }
     }
@@ -120,7 +120,7 @@ public class SevenZTest extends AbstractTest {
 
     private void singleByteReadConsistentlyReturnsMinusOneAtEof(final 
SevenZMethod method) throws Exception {
         createArchive(method);
-        try (SevenZFile archive = new SevenZFile(output)) {
+        try (SevenZFile archive = SevenZFile.builder().setFile(output).get()) {
             singleByteReadConsistentlyReturnsMinusOneAtEof(archive);
         }
     }
@@ -155,7 +155,7 @@ public class SevenZTest extends AbstractTest {
 
     private void testSevenZArchiveCreation(final SevenZMethod method) throws 
Exception {
         createArchive(method);
-        try (SevenZFile archive = new SevenZFile(output)) {
+        try (SevenZFile archive = SevenZFile.builder().setFile(output).get()) {
             SevenZArchiveEntry entry;
 
             entry = archive.getNextEntry();
diff --git 
a/src/test/java/org/apache/commons/compress/archivers/examples/ExpanderTest.java
 
b/src/test/java/org/apache/commons/compress/archivers/examples/ExpanderTest.java
index 712052e5c..1de43778f 100644
--- 
a/src/test/java/org/apache/commons/compress/archivers/examples/ExpanderTest.java
+++ 
b/src/test/java/org/apache/commons/compress/archivers/examples/ExpanderTest.java
@@ -222,8 +222,8 @@ public class ExpanderTest extends AbstractTest {
     @Test
     public void testSevenZFileVersion() throws IOException {
         setup7z();
-        try (SevenZFile f = new SevenZFile(archive)) {
-            new Expander().expand(f, tempResultDir);
+        try (SevenZFile file = SevenZFile.builder().setFile(archive).get()) {
+            new Expander().expand(file, tempResultDir);
         }
         verifyTargetDir();
     }
diff --git 
a/src/test/java/org/apache/commons/compress/archivers/examples/SevenZArchiverTest.java
 
b/src/test/java/org/apache/commons/compress/archivers/examples/SevenZArchiverTest.java
index a7fa5fdf7..d17f2b534 100644
--- 
a/src/test/java/org/apache/commons/compress/archivers/examples/SevenZArchiverTest.java
+++ 
b/src/test/java/org/apache/commons/compress/archivers/examples/SevenZArchiverTest.java
@@ -107,7 +107,7 @@ public class SevenZArchiverTest extends AbstractTest {
     }
 
     private void verifyContent() throws IOException {
-        try (SevenZFile z = new SevenZFile(target)) {
+        try (SevenZFile z = SevenZFile.builder().setFile(target).get()) {
             assertDir("a", z.getNextEntry());
             assertDir("a/b", z.getNextEntry());
             final ArchiveEntry n = z.getNextEntry();
diff --git 
a/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZFileTest.java
 
b/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZFileTest.java
index 2abc70f70..a70499c5f 100644
--- 
a/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZFileTest.java
+++ 
b/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZFileTest.java
@@ -87,7 +87,7 @@ public class SevenZFileTest extends AbstractTest {
     }
 
     private void checkHelloWorld(final String fileName) throws Exception {
-        try (SevenZFile sevenZFile = new SevenZFile(getFile(fileName))) {
+        try (SevenZFile sevenZFile = getSevenZFile(fileName)) {
             final SevenZArchiveEntry entry = sevenZFile.getNextEntry();
             assertEquals("Hello world.txt", entry.getName());
             assertDates(entry, "2013-05-07T19:40:48Z", null, null);
@@ -103,6 +103,10 @@ public class SevenZFileTest extends AbstractTest {
         }
     }
 
+    private SevenZFile getSevenZFile(final String specialPath) throws 
IOException {
+        return SevenZFile.builder().setFile(getFile(specialPath)).get();
+    }
+
     private byte[] read(final SevenZFile sevenZFile, final SevenZArchiveEntry 
entry) throws IOException {
         try (InputStream inputStream = sevenZFile.getInputStream(entry)) {
             return IOUtils.toByteArray(inputStream);
@@ -146,7 +150,12 @@ public class SevenZFileTest extends AbstractTest {
 
     @Test
     public void test7zMultiVolumeUnarchive() throws Exception {
-        try (SevenZFile sevenZFile = new 
SevenZFile(MultiReadOnlySeekableByteChannel.forFiles(getFile("bla-multi.7z.001"),
 getFile("bla-multi.7z.002")))) {
+        try (@SuppressWarnings("deprecation")
+        SevenZFile sevenZFile = new 
SevenZFile(MultiReadOnlySeekableByteChannel.forFiles(getFile("bla-multi.7z.001"),
 getFile("bla-multi.7z.002")))) {
+            test7zUnarchive(sevenZFile, SevenZMethod.LZMA2);
+        }
+        try (SevenZFile sevenZFile = SevenZFile.builder()
+                
.setSeekableByteChannel(MultiReadOnlySeekableByteChannel.forFiles(getFile("bla-multi.7z.001"),
 getFile("bla-multi.7z.002"))).get()) {
             test7zUnarchive(sevenZFile, SevenZMethod.LZMA2);
         }
     }
@@ -156,29 +165,37 @@ public class SevenZFileTest extends AbstractTest {
         test7zUnarchive(getFile("bla.7z"), SevenZMethod.LZMA);
     }
 
-    private void test7zUnarchive(final File f, final SevenZMethod m) throws 
Exception {
-        test7zUnarchive(f, m, false);
+    private void test7zUnarchive(final File file, final SevenZMethod method) 
throws Exception {
+        test7zUnarchive(file, method, false);
     }
 
-    private void test7zUnarchive(final File f, final SevenZMethod m, final 
boolean tryToRecoverBrokenArchives) throws Exception {
-        test7zUnarchive(f, m, (char[]) null, tryToRecoverBrokenArchives);
+    private void test7zUnarchive(final File file, final SevenZMethod method, 
final boolean tryToRecoverBrokenArchives) throws Exception {
+        test7zUnarchive(file, method, (char[]) null, 
tryToRecoverBrokenArchives);
     }
 
-    private void test7zUnarchive(final File f, final SevenZMethod m, final 
byte[] password) throws Exception {
-        try (SevenZFile sevenZFile = new SevenZFile(f, password)) {
-            test7zUnarchive(sevenZFile, m);
+    private void test7zUnarchive(final File file, final SevenZMethod method, 
final byte[] password) throws Exception {
+        try (@SuppressWarnings("deprecation")
+        SevenZFile sevenZFile = new SevenZFile(file, password)) {
+            test7zUnarchive(sevenZFile, method);
+        }
+        try (SevenZFile sevenZFile = 
SevenZFile.builder().setFile(file).setPassword(password).get()) {
+            test7zUnarchive(sevenZFile, method);
         }
     }
 
-    private void test7zUnarchive(final File f, final SevenZMethod m, final 
char[] password) throws Exception {
-        test7zUnarchive(f, m, password, false);
+    private void test7zUnarchive(final File file, final SevenZMethod m, final 
char[] password) throws Exception {
+        test7zUnarchive(file, m, password, false);
     }
 
-    private void test7zUnarchive(final File f, final SevenZMethod m, final 
char[] password, final boolean tryToRecoverBrokenArchives) throws Exception {
-        try (SevenZFile sevenZFile = new SevenZFile(f, password,
+    private void test7zUnarchive(final File file, final SevenZMethod m, final 
char[] password, final boolean tryToRecoverBrokenArchives) throws Exception {
+        try (@SuppressWarnings("deprecation")
+        SevenZFile sevenZFile = new SevenZFile(file, password,
                 
SevenZFileOptions.builder().withTryToRecoverBrokenArchives(tryToRecoverBrokenArchives).build()))
 {
             test7zUnarchive(sevenZFile, m);
         }
+        try (SevenZFile sevenZFile = 
SevenZFile.builder().setFile(file).setPassword(password).setTryToRecoverBrokenArchives(tryToRecoverBrokenArchives).get())
 {
+            test7zUnarchive(sevenZFile, m);
+        }
     }
 
     private void test7zUnarchive(final SevenZFile sevenZFile, final 
SevenZMethod m) throws Exception {
@@ -213,7 +230,7 @@ public class SevenZFileTest extends AbstractTest {
 
     @Test
     public void testAllEmptyFilesArchive() throws Exception {
-        try (SevenZFile archive = new 
SevenZFile(getFile("7z-empty-mhc-off.7z"))) {
+        try (SevenZFile archive = getSevenZFile("7z-empty-mhc-off.7z")) {
             final SevenZArchiveEntry e = archive.getNextEntry();
             assertNotNull(e);
             assertEquals("empty", e.getName());
@@ -227,7 +244,7 @@ public class SevenZFileTest extends AbstractTest {
      */
     @Test
     public void testCompressedHeaderWithNonDefaultDictionarySize() throws 
Exception {
-        try (SevenZFile sevenZFile = new 
SevenZFile(getFile("COMPRESS-256.7z"))) {
+        try (SevenZFile sevenZFile = getSevenZFile("COMPRESS-256.7z")) {
             int count = 0;
             while (sevenZFile.getNextEntry() != null) {
                 count++;
@@ -238,7 +255,7 @@ public class SevenZFileTest extends AbstractTest {
 
     @Test
     public void testEncryptedArchiveRequiresPassword() throws Exception {
-        final PasswordRequiredException ex = 
assertThrows(PasswordRequiredException.class, () -> new 
SevenZFile(getFile("bla.encrypted.7z")).close(),
+        final PasswordRequiredException ex = 
assertThrows(PasswordRequiredException.class, () -> 
getSevenZFile("bla.encrypted.7z").close(),
                 "shouldn't decrypt without a password");
         final String msg = ex.getMessage();
         assertTrue(msg.startsWith("Cannot read encrypted content from "), 
"Should start with whining about being unable to decrypt");
@@ -248,8 +265,8 @@ public class SevenZFileTest extends AbstractTest {
 
     @Test
     public void testExtractNonExistSpecifiedFile() throws Exception {
-        try (SevenZFile sevenZFile = new 
SevenZFile(getFile("COMPRESS-256.7z"));
-                SevenZFile anotherSevenZFile = new 
SevenZFile(getFile("bla.7z"))) {
+        try (SevenZFile sevenZFile = getSevenZFile("COMPRESS-256.7z");
+                SevenZFile anotherSevenZFile = getSevenZFile("bla.7z")) {
             for (final SevenZArchiveEntry nonExistEntry : 
anotherSevenZFile.getEntries()) {
                 assertThrows(IllegalArgumentException.class, () -> 
sevenZFile.getInputStream(nonExistEntry));
             }
@@ -258,7 +275,33 @@ public class SevenZFileTest extends AbstractTest {
 
     @Test
     public void testExtractSpecifiedFile() throws Exception {
-        try (SevenZFile sevenZFile = new 
SevenZFile(getFile("COMPRESS-256.7z"))) {
+        try (SevenZFile sevenZFile = getSevenZFile("COMPRESS-256.7z")) {
+            final String testTxtContents = 
"111111111111111111111111111000101011\n" + 
"111111111111111111111111111000101011\n"
+                    + "111111111111111111111111111000101011\n" + 
"111111111111111111111111111000101011\n" + 
"111111111111111111111111111000101011\n"
+                    + "111111111111111111111111111000101011\n" + 
"111111111111111111111111111000101011\n" + 
"111111111111111111111111111000101011\n"
+                    + "111111111111111111111111111000101011\n" + 
"111111111111111111111111111000101011";
+
+            for (final SevenZArchiveEntry entry : sevenZFile.getEntries()) {
+                if 
(entry.getName().equals("commons-compress-1.7-src/src/test/resources/test.txt"))
 {
+                    final byte[] contents = new byte[(int) entry.getSize()];
+                    int off = 0;
+                    final InputStream inputStream = 
sevenZFile.getInputStream(entry);
+                    while (off < contents.length) {
+                        final int bytesRead = inputStream.read(contents, off, 
contents.length - off);
+                        assert bytesRead >= 0;
+                        off += bytesRead;
+                    }
+                    assertEquals(testTxtContents, new String(contents, UTF_8));
+                    break;
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testExtractSpecifiedFileDeprecated() throws Exception {
+        try (@SuppressWarnings("deprecation")
+        SevenZFile sevenZFile = new SevenZFile(getFile("COMPRESS-256.7z"))) {
             final String testTxtContents = 
"111111111111111111111111111000101011\n" + 
"111111111111111111111111111000101011\n"
                     + "111111111111111111111111111000101011\n" + 
"111111111111111111111111111000101011\n" + 
"111111111111111111111111111000101011\n"
                     + "111111111111111111111111111000101011\n" + 
"111111111111111111111111111000101011\n" + 
"111111111111111111111111111000101011\n"
@@ -282,17 +325,23 @@ public class SevenZFileTest extends AbstractTest {
     }
 
     @Test
-    public void testGetDefaultNameWorksAsExpected() throws Exception {
-        try (SevenZFile sevenZFile = new 
SevenZFile(getFile("bla.deflate64.7z"))) {
+    public void testGetDefaultName() throws Exception {
+        try (SevenZFile sevenZFile = getSevenZFile("bla.deflate64.7z")) {
             assertEquals("bla.deflate64", sevenZFile.getDefaultName());
         }
-        try (SevenZFile sevenZFile = new 
SevenZFile(Files.newByteChannel(getFile("bla.deflate64.7z").toPath()))) {
+        try (SevenZFile sevenZFile = 
SevenZFile.builder().setSeekableByteChannel(Files.newByteChannel(getFile("bla.deflate64.7z").toPath())).get())
 {
             assertNull(sevenZFile.getDefaultName());
         }
-        try (SevenZFile sevenZFile = new 
SevenZFile(Files.newByteChannel(getFile("bla.deflate64.7z").toPath()), "foo")) {
+        try (@SuppressWarnings("deprecation")
+        SevenZFile sevenZFile = new 
SevenZFile(Files.newByteChannel(getFile("bla.deflate64.7z").toPath()), "foo")) {
+            assertEquals("foo~", sevenZFile.getDefaultName());
+        }
+        try (SevenZFile sevenZFile = 
SevenZFile.builder().setSeekableByteChannel(Files.newByteChannel(getFile("bla.deflate64.7z").toPath()))
+                .setDefaultName("foo").get()) {
             assertEquals("foo~", sevenZFile.getDefaultName());
         }
-        try (SevenZFile sevenZFile = new 
SevenZFile(Files.newByteChannel(getFile("bla.deflate64.7z").toPath()), ".foo")) 
{
+        try (SevenZFile sevenZFile = 
SevenZFile.builder().setSeekableByteChannel(Files.newByteChannel(getFile("bla.deflate64.7z").toPath()))
+                .setDefaultName(".foo").get()) {
             assertEquals(".foo~", sevenZFile.getDefaultName());
         }
     }
@@ -300,7 +349,7 @@ public class SevenZFileTest extends AbstractTest {
     @Test
     public void testGetEntriesOfUnarchiveInMemoryTest() throws IOException {
         final byte[] data = readAllBytes("bla.7z");
-        try (SevenZFile sevenZFile = new SevenZFile(new 
SeekableInMemoryByteChannel(data))) {
+        try (SevenZFile sevenZFile = 
SevenZFile.builder().setSeekableByteChannel(new 
SeekableInMemoryByteChannel(data)).get()) {
             final Iterable<SevenZArchiveEntry> entries = 
sevenZFile.getEntries();
             final Iterator<SevenZArchiveEntry> iter = entries.iterator();
             SevenZArchiveEntry entry = iter.next();
@@ -313,7 +362,7 @@ public class SevenZFileTest extends AbstractTest {
 
     @Test
     public void testGetEntriesOfUnarchiveTest() throws IOException {
-        try (SevenZFile sevenZFile = new SevenZFile(getFile("bla.7z"))) {
+        try (SevenZFile sevenZFile = getSevenZFile("bla.7z")) {
             final Iterable<SevenZArchiveEntry> entries = 
sevenZFile.getEntries();
             final Iterator<SevenZArchiveEntry> iter = entries.iterator();
             SevenZArchiveEntry entry = iter.next();
@@ -326,7 +375,17 @@ public class SevenZFileTest extends AbstractTest {
 
     @Test
     public void testGivenNameWinsOverDefaultName() throws Exception {
-        try (SevenZFile sevenZFile = new SevenZFile(getFile("bla.7z"), 
SevenZFileOptions.builder().withUseDefaultNameForUnnamedEntries(true).build())) 
{
+        try (@SuppressWarnings("deprecation")
+        SevenZFile sevenZFile = new SevenZFile(getFile("bla.7z"), 
SevenZFileOptions.builder().withUseDefaultNameForUnnamedEntries(true).build())) 
{
+            SevenZArchiveEntry ae = sevenZFile.getNextEntry();
+            assertNotNull(ae);
+            assertEquals("test1.xml", ae.getName());
+            ae = sevenZFile.getNextEntry();
+            assertNotNull(ae);
+            assertEquals("test2.xml", ae.getName());
+            assertNull(sevenZFile.getNextEntry());
+        }
+        try (SevenZFile sevenZFile = 
SevenZFile.builder().setFile(getFile("bla.7z")).setUseDefaultNameForUnnamedEntries(true).get())
 {
             SevenZArchiveEntry ae = sevenZFile.getNextEntry();
             assertNotNull(ae);
             assertEquals("test1.xml", ae.getName());
@@ -342,10 +401,10 @@ public class SevenZFileTest extends AbstractTest {
      */
     @Test
     public void testHandlesEmptyArchiveWithFilesInfo() throws Exception {
-        final File f = newTempFile("empty.7z");
-        try (SevenZOutputFile s = new SevenZOutputFile(f)) {
+        final File file = newTempFile("empty.7z");
+        try (SevenZOutputFile s = new SevenZOutputFile(file)) {
         }
-        try (SevenZFile z = new SevenZFile(f)) {
+        try (SevenZFile z = SevenZFile.builder().setFile(file).get()) {
             assertFalse(z.getEntries().iterator().hasNext());
             assertNull(z.getNextEntry());
         }
@@ -356,7 +415,7 @@ public class SevenZFileTest extends AbstractTest {
      */
     @Test
     public void testHandlesEmptyArchiveWithoutFilesInfo() throws Exception {
-        try (SevenZFile z = new SevenZFile(getFile("COMPRESS-492.7z"))) {
+        try (SevenZFile z = getSevenZFile("COMPRESS-492.7z")) {
             assertFalse(z.getEntries().iterator().hasNext());
             assertNull(z.getNextEntry());
         }
@@ -375,7 +434,7 @@ public class SevenZFileTest extends AbstractTest {
     @Test
     public void testLimitExtractionMemory() {
         assertThrows(MemoryLimitException.class, () -> {
-            try (SevenZFile sevenZFile = new SevenZFile(getFile("bla.7z"), 
SevenZFileOptions.builder().withMaxMemoryLimitInKb(1).build())) {
+            try (SevenZFile sevenZFile = 
SevenZFile.builder().setFile(getFile("bla.7z")).setMaxMemoryLimitKb(1).get()) {
                 // Do nothing. Exception should be thrown
             }
         });
@@ -383,7 +442,7 @@ public class SevenZFileTest extends AbstractTest {
 
     @Test
     public void testNoNameCanBeReplacedByDefaultName() throws Exception {
-        try (SevenZFile sevenZFile = new SevenZFile(getFile("bla-nonames.7z"), 
SevenZFileOptions.builder().withUseDefaultNameForUnnamedEntries(true).build())) 
{
+        try (SevenZFile sevenZFile = 
SevenZFile.builder().setFile(getFile("bla-nonames.7z")).setUseDefaultNameForUnnamedEntries(true).get())
 {
             SevenZArchiveEntry ae = sevenZFile.getNextEntry();
             assertNotNull(ae);
             assertEquals("bla-nonames", ae.getName());
@@ -396,7 +455,7 @@ public class SevenZFileTest extends AbstractTest {
 
     @Test
     public void testNoNameMeansNoNameByDefault() throws Exception {
-        try (SevenZFile sevenZFile = new 
SevenZFile(getFile("bla-nonames.7z"))) {
+        try (SevenZFile sevenZFile = getSevenZFile("bla-nonames.7z")) {
             SevenZArchiveEntry ae = sevenZFile.getNextEntry();
             assertNotNull(ae);
             assertNull(ae.getName());
@@ -416,18 +475,29 @@ public class SevenZFileTest extends AbstractTest {
         testFiles.add(getPath("COMPRESS-542-endheadercorrupted2.7z"));
 
         for (final Path file : testFiles) {
-            final IOException e = assertThrows(IOException.class, () -> {
-                try (SevenZFile sevenZFile = new 
SevenZFile(Files.newByteChannel(file),
-                        
SevenZFileOptions.builder().withTryToRecoverBrokenArchives(true).build())) {
-                }
-            }, "Expected IOException: start header corrupt and unable to guess 
end header");
-            assertEquals("Start header corrupt and unable to guess end 
header", e.getMessage());
+            {
+                final IOException e = assertThrows(IOException.class, () -> {
+                    try (@SuppressWarnings("deprecation")
+                    SevenZFile sevenZFile = new 
SevenZFile(Files.newByteChannel(file),
+                            
SevenZFileOptions.builder().withTryToRecoverBrokenArchives(true).build())) {
+                    }
+                }, "Expected IOException: start header corrupt and unable to 
guess end header");
+                assertEquals("Start header corrupt and unable to guess end 
header", e.getMessage());
+            }
+            {
+                final IOException e = assertThrows(IOException.class, () -> {
+                    try (SevenZFile sevenZFile = 
SevenZFile.builder().setSeekableByteChannel(Files.newByteChannel(file)).setTryToRecoverBrokenArchives(true)
+                            .get()) {
+                    }
+                }, "Expected IOException: start header corrupt and unable to 
guess end header");
+                assertEquals("Start header corrupt and unable to guess end 
header", e.getMessage());
+            }
         }
     }
 
     @Test
     public void testRandomAccessMultipleReadSameFile() throws Exception {
-        try (SevenZFile sevenZFile = new 
SevenZFile(getFile("COMPRESS-256.7z"))) {
+        try (SevenZFile sevenZFile = getSevenZFile("COMPRESS-256.7z")) {
             final String testTxtContents = 
"111111111111111111111111111000101011\n" + 
"111111111111111111111111111000101011\n"
                     + "111111111111111111111111111000101011\n" + 
"111111111111111111111111111000101011\n" + 
"111111111111111111111111111000101011\n"
                     + "111111111111111111111111111000101011\n" + 
"111111111111111111111111111000101011\n" + 
"111111111111111111111111111000101011\n"
@@ -462,7 +532,7 @@ public class SevenZFileTest extends AbstractTest {
 
     @Test
     public void testRandomAccessTogetherWithSequentialAccess() throws 
Exception {
-        try (SevenZFile sevenZFile = new 
SevenZFile(getFile("COMPRESS-256.7z"))) {
+        try (SevenZFile sevenZFile = getSevenZFile("COMPRESS-256.7z")) {
             // @formatter:off
             final String testTxtContents = 
"111111111111111111111111111000101011\n"
                     + "111111111111111111111111111000101011\n"
@@ -536,7 +606,7 @@ public class SevenZFileTest extends AbstractTest {
 
     @Test
     public void testRandomAccessWhenJumpingBackwards() throws Exception {
-        try (SevenZFile sevenZFile = new 
SevenZFile(getFile("COMPRESS-256.7z"))) {
+        try (SevenZFile sevenZFile = getSevenZFile("COMPRESS-256.7z")) {
             final String testTxtContents = 
"111111111111111111111111111000101011\n" + 
"111111111111111111111111111000101011\n"
                     + "111111111111111111111111111000101011\n" + 
"111111111111111111111111111000101011\n" + 
"111111111111111111111111111000101011\n"
                     + "111111111111111111111111111000101011\n" + 
"111111111111111111111111111000101011\n" + 
"111111111111111111111111111000101011\n"
@@ -593,7 +663,7 @@ public class SevenZFileTest extends AbstractTest {
 
     @Test
     public void testRandomAccessWhenJumpingForwards() throws Exception {
-        try (SevenZFile sevenZFile = new 
SevenZFile(getFile("COMPRESS-256.7z"))) {
+        try (SevenZFile sevenZFile = getSevenZFile("COMPRESS-256.7z")) {
             final String testTxtContents = 
"111111111111111111111111111000101011\n" + 
"111111111111111111111111111000101011\n"
                     + "111111111111111111111111111000101011\n" + 
"111111111111111111111111111000101011\n" + 
"111111111111111111111111111000101011\n"
                     + "111111111111111111111111111000101011\n" + 
"111111111111111111111111111000101011\n" + 
"111111111111111111111111111000101011\n"
@@ -642,7 +712,7 @@ public class SevenZFileTest extends AbstractTest {
     public void testRandomlySkippingEntries() throws Exception {
         // Read sequential reference.
         final Map<String, byte[]> entriesByName = new HashMap<>();
-        try (SevenZFile archive = new 
SevenZFile(getFile("COMPRESS-320/Copy.7z"))) {
+        try (SevenZFile archive = getSevenZFile("COMPRESS-320/Copy.7z")) {
             SevenZArchiveEntry entry;
             while ((entry = archive.getNextEntry()) != null) {
                 if (entry.hasStream()) {
@@ -661,7 +731,7 @@ public class SevenZFileTest extends AbstractTest {
         // TODO: use randomized testing for predictable, but different, 
randomness.
         final Random rnd = new Random(0xdeadbeef);
         for (final String fileName : variants) {
-            try (SevenZFile archive = new SevenZFile(getFile("COMPRESS-320/" + 
fileName))) {
+            try (SevenZFile archive = getSevenZFile("COMPRESS-320/" + 
fileName)) {
 
                 SevenZArchiveEntry entry;
                 while ((entry = archive.getNextEntry()) != null) {
@@ -683,7 +753,7 @@ public class SevenZFileTest extends AbstractTest {
 
     @Test
     public void testReadBigSevenZipFile() throws IOException {
-        try (SevenZFile sevenZFile = new 
SevenZFile(getFile("COMPRESS-592.7z"))) {
+        try (SevenZFile sevenZFile = getSevenZFile("COMPRESS-592.7z")) {
             SevenZArchiveEntry entry = sevenZFile.getNextEntry();
             while (entry != null) {
                 if (entry.hasStream()) {
@@ -700,7 +770,7 @@ public class SevenZFileTest extends AbstractTest {
      */
     @Test
     public void testReadEntriesOfSize0() throws IOException {
-        try (SevenZFile sevenZFile = new 
SevenZFile(getFile("COMPRESS-348.7z"))) {
+        try (SevenZFile sevenZFile = getSevenZFile("COMPRESS-348.7z")) {
             int entries = 0;
             SevenZArchiveEntry entry = sevenZFile.getNextEntry();
             while (entry != null) {
@@ -730,7 +800,7 @@ public class SevenZFileTest extends AbstractTest {
             outArchive.closeArchiveEntry();
         }
 
-        try (SevenZFile archive = new SevenZFile(output)) {
+        try (SevenZFile archive = SevenZFile.builder().setFile(output).get()) {
             final SevenZArchiveEntry entry = archive.getNextEntry();
             final SevenZMethodConfiguration m = 
entry.getContentMethods().iterator().next();
             assertEquals(SevenZMethod.DELTA_FILTER, m.getMethod());
@@ -750,7 +820,7 @@ public class SevenZFileTest extends AbstractTest {
             outArchive.closeArchiveEntry();
         }
 
-        try (SevenZFile archive = new SevenZFile(output)) {
+        try (SevenZFile archive = SevenZFile.builder().setFile(output).get()) {
             final SevenZArchiveEntry entry = archive.getNextEntry();
             final SevenZMethodConfiguration m = 
entry.getContentMethods().iterator().next();
             assertEquals(SevenZMethod.LZMA2, m.getMethod());
@@ -760,7 +830,7 @@ public class SevenZFileTest extends AbstractTest {
 
     @Test
     public void testReadTimesFromFile() throws IOException {
-        try (SevenZFile sevenZFile = new SevenZFile(getFile("times.7z"))) {
+        try (SevenZFile sevenZFile = getSevenZFile("times.7z")) {
             SevenZArchiveEntry entry = sevenZFile.getNextEntry();
             assertNotNull(entry);
             assertEquals("test", entry.getName());
@@ -786,7 +856,7 @@ public class SevenZFileTest extends AbstractTest {
 
     @Test
     public void testRetrieveInputStreamForAllEntriesMultipleTimes() throws 
IOException {
-        try (SevenZFile sevenZFile = new SevenZFile(getFile("bla.7z"))) {
+        try (SevenZFile sevenZFile = getSevenZFile("bla.7z")) {
             for (final SevenZArchiveEntry entry : sevenZFile.getEntries()) {
                 final byte[] firstRead = read(sevenZFile, entry);
                 final byte[] secondRead = read(sevenZFile, entry);
@@ -808,7 +878,7 @@ public class SevenZFileTest extends AbstractTest {
             Files.deleteIfExists(inputFile);
         }
 
-        try (SevenZFile sevenZFile = new SevenZFile(newTempFile("test.7z"))) {
+        try (SevenZFile sevenZFile = 
SevenZFile.builder().setFile(newTempFile("test.7z")).get()) {
             for (final SevenZArchiveEntry entry : sevenZFile.getEntries()) {
                 final byte[] firstRead = read(sevenZFile, entry);
                 final byte[] secondRead = read(sevenZFile, entry);
@@ -819,7 +889,7 @@ public class SevenZFileTest extends AbstractTest {
 
     @Test
     public void testRetrieveInputStreamForShuffledEntries() throws IOException 
{
-        try (SevenZFile sevenZFile = new 
SevenZFile(getFile("COMPRESS-348.7z"))) {
+        try (SevenZFile sevenZFile = getSevenZFile("COMPRESS-348.7z")) {
             final List<SevenZArchiveEntry> entries = 
(List<SevenZArchiveEntry>) sevenZFile.getEntries();
             Collections.shuffle(entries);
             for (final SevenZArchiveEntry entry : entries) {
@@ -830,7 +900,7 @@ public class SevenZFileTest extends AbstractTest {
 
     @Test
     public void testSevenZWithEOS() throws IOException {
-        try (SevenZFile sevenZFile = new 
SevenZFile(getFile("lzma-with-eos.7z"))) {
+        try (SevenZFile sevenZFile = getSevenZFile("lzma-with-eos.7z")) {
             final List<SevenZArchiveEntry> entries = 
(List<SevenZArchiveEntry>) sevenZFile.getEntries();
             for (final SevenZArchiveEntry entry : entries) {
                 read(sevenZFile, entry);
diff --git 
a/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFileTest.java
 
b/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFileTest.java
index a3834bb46..d2c031974 100644
--- 
a/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFileTest.java
+++ 
b/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFileTest.java
@@ -101,7 +101,7 @@ public class SevenZOutputFileTest extends AbstractTest {
             addFile(outArchive, 0, true);
         }
 
-        try (SevenZFile archive = new SevenZFile(output)) {
+        try (SevenZFile archive = SevenZFile.builder().setFile(output).get()) {
             assertEquals(Boolean.TRUE, verifyFile(archive, 0, methods));
         }
     }
@@ -111,7 +111,7 @@ public class SevenZOutputFileTest extends AbstractTest {
             outArchive.setContentMethods(methods);
             addFile(outArchive, 0, true);
         }
-        try (SevenZFile archive = new SevenZFile(new 
SeekableInMemoryByteChannel(output.array()), "in memory")) {
+        try (SevenZFile archive = 
SevenZFile.builder().setByteArray(output.array()).setDefaultName("in 
memory").get()) {
             assertEquals(Boolean.TRUE, verifyFile(archive, 0, methods));
         }
     }
@@ -142,7 +142,7 @@ public class SevenZOutputFileTest extends AbstractTest {
             addFile(outArchive, 1, true, Arrays.asList(new 
SevenZMethodConfiguration(SevenZMethod.BZIP2)));
         }
 
-        try (SevenZFile archive = new SevenZFile(output)) {
+        try (SevenZFile archive = SevenZFile.builder().setFile(output).get()) {
             assertEquals(Boolean.TRUE, verifyFile(archive, 0, 
Arrays.asList(new SevenZMethodConfiguration(SevenZMethod.LZMA2))));
             assertEquals(Boolean.TRUE, verifyFile(archive, 1, 
Arrays.asList(new SevenZMethodConfiguration(SevenZMethod.BZIP2))));
         }
@@ -336,7 +336,7 @@ public class SevenZOutputFileTest extends AbstractTest {
             outArchive.finish();
         }
 
-        try (SevenZFile archive = new SevenZFile(output)) {
+        try (SevenZFile archive = SevenZFile.builder().setFile(output).get()) {
             SevenZArchiveEntry entry = archive.getNextEntry();
             assert entry != null;
             assertEquals("foo/", entry.getName());
@@ -444,7 +444,7 @@ public class SevenZOutputFileTest extends AbstractTest {
             outArchive.closeArchiveEntry();
         }
 
-        try (SevenZFile archive = new SevenZFile(output)) {
+        try (SevenZFile archive = SevenZFile.builder().setFile(output).get()) {
             final SevenZArchiveEntry entry = archive.getNextEntry();
             assert entry != null;
             assertEquals("foo/", entry.getName());
@@ -486,13 +486,12 @@ public class SevenZOutputFileTest extends AbstractTest {
         }
 
         // Is archive really password-based encrypted ?
-        try (SevenZFile archive = new SevenZFile(output)) {
+        try (SevenZFile archive = SevenZFile.builder().setFile(output).get()) {
             assertThrows(
-
                     PasswordRequiredException.class, () -> verifyFile(archive, 
0), "A password should be needed");
         }
 
-        try (SevenZFile archive = new SevenZFile(output, "foo".toCharArray())) 
{
+        try (SevenZFile archive = 
SevenZFile.builder().setFile(output).setPassword("foo").get()) {
             assertEquals(Boolean.TRUE, verifyFile(archive, 0, 1, null));
             assertEquals(Boolean.TRUE, verifyFile(archive, 1, 16, null));
             assertEquals(Boolean.TRUE, verifyFile(archive, 2, 32, null));
@@ -615,7 +614,7 @@ public class SevenZOutputFileTest extends AbstractTest {
     private void verifyCompress252(final File output, final int numberOfFiles, 
final int numberOfNonEmptyFiles) throws Exception {
         int filesFound = 0;
         int nonEmptyFilesFound = 0;
-        try (SevenZFile archive = new SevenZFile(output)) {
+        try (SevenZFile archive = SevenZFile.builder().setFile(output).get()) {
             verifyDir(archive);
             Boolean b = verifyFile(archive, filesFound++);
             while (b != null) {

Reply via email to