Zip DetectFileFormat

On such cases when no specific standard is known, and you have 4 other similar functions in other Aspose SDKs, I’d refer to them to keep the maximum similarity :slight_smile:

Hi @usernameisalreadyinuse,
We have released the functionality you requested in version 23.2.
You can use IArchive interface.

Hello,
ArchiveFormatDetector is obsolete: Use static methods of ArchiveInstanceInfo class instead
Is this the correct method of the new build?

ArchiveInstanceInfo.GetArchiveFormatInfo(MyStream).Format.ToString

Hello @australian.dev.nerds,
Yes, you should use ArchiveInstanceInfo.GetArchiveFormatInfo.
Don’t forget to do null checking as this method can return null if the archive format is not detected.

hello,
I was trying to update my code to support all file formats without needing a switch-case to create all possibile archive types (IArchive) but I’m confused about how to do that.

I have tried to dynamically instantiate the returned class type but (Aspose.Zip.IArchive)Activator.CreateInstance(archiveInfo.FormatInfo.Class, archiveStream) gives this error: “System.MissingMethodException: Constructor on type ‘Aspose.Zip.Archive’ not found” (with different class types).

I would have expected to have a public factory that can create an IArchive from a Stream, am I missing something?

Thanks.

I had to resort to this implementation…

Aspose.Zip.IArchive asposeArchive;
switch (archiveInfo.FormatInfo.Format)
{
	case Aspose.Zip.ArchiveInfo.ArchiveFormat.Zip: asposeArchive = new Aspose.Zip.Archive(archive); break;
	case Aspose.Zip.ArchiveInfo.ArchiveFormat.Rar: asposeArchive = new Aspose.Zip.Rar.RarArchive(archive); break;
	...

I have found 2 bugs with this implementation:

First bug (TAR)

Using GetArchiveInstanceInfo seems to advance the Stream position and, when creating the Aspose.Zip.Tar.TarArchive I get this unhandled exception:

System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: startIndex

ParseNumbers.StringToLong(String s, Int32 radix, Int32 flags, Int32* currPos)
Convert.ToInt64(String value, Int32 fromBase)
#=z_Xb5ypSU2vOHGU42$qpZmdLwWZqCJMaetg==.#=zejiznR9npslztnevLDU1SkE=(Byte[] #=zxAcbvzQ=)
#=z_Xb5ypSU2vOHGU42$qpZmdLwWZqCJMaetg==.#=zel0RQJI=(Byte[] #=zxAcbvzQ=)
#=z8q8sH0tshhPGrFZmRnfm9hsgJfNzx8QwbQ==.#=zel0RQJI=(Byte[] #=zxAcbvzQ=)
#=zKUg1pZhD3qF$a_pgDRaAkvGI0S$gtpo9gA==.#=zO$iAeiYzP9CRJaAG3KkB6CQ=(Byte[] #=zxAcbvzQ=)
#=zKUg1pZhD3qF$a_pgDRaAkvGI0S$gtpo9gA==.#=zD2J5JkQoGHx_owAIJQ==(Stream #=zZ$ROlXe$AGO8)
#=zKUg1pZhD3qF$a_pgDRaAkvGI0S$gtpo9gA==.#=zz6EMF7J9K6QXMoqMRQ==(Stream #=zZ$ROlXe$AGO8)
TarArchive.#=zzbacll8=(Stream #=zZ$ROlXe$AGO8)
TarArchive.ctor(Stream sourceStream)
<>c__DisplayClass32_0.b__0() line 527
Task1.InnerInvoke() Task.Execute() --- End of stack trace from previous location where exception was thrown --- TaskAwaiter.ThrowForNonSuccess(Task task) TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) TaskAwaiter1.GetResult()
d__3.MoveNext() line 71
— End of stack trace from previous location where exception was thrown —
TaskAwaiter.ThrowForNonSuccess(Task task)
TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
ThreadOperations.ExecuteWithAbortSafety(Action action)

The workaround is to reset the stream position after calling GetArchiveInstanceInfo and before calling the archive constructor.

Note that, if the stream is not seekable, this cannot be done.

I think that the GetArchiveInstanceInfo method should cache the initial bytes when they are read to detect the format (magic bytes?) and than reuse those cached bytes to feed the correct instance of the archive in order to allow unseekable streams to be used.

Second bug (XZ)

When reading the attached file (198 Bytes) I get this exception (with and without calling GetArchiveInstanceInfo):

  • The XZ file is wrapped in a 7z archive because the forum does not allow this extension.
  • The XZ file was created with 7Zip 22

new Aspose.Zip.Xz.XzArchive(File.OpenRead("sample.txt.xz"))

System.IndexOutOfRangeException: Index was outside the bounds of the array.

#=zhDBwbx5Ry8Eh7RYaAMiFHNCvkmZNFyNK3w==.#=zel0RQJI=(Stream #=zfx$wlbHoiZMhq1Imkw==)
#=zJUOV9Jv7zDU83QN13Gy5Tfu9jz3ePiWzcg==.#=zel0RQJI=(Stream #=zfx$wlbHoiZMhq1Imkw==, XzCheckType #=zeok_4mc=, #=zxoLcKbeeq3l6ArhkvR5OVHDTMiIFD27njA== #=zRQCX57Q=)
XzArchive.#=zNp7LwfU=(Stream #=zSq3tOVY=)
XzArchive.ctor(Stream source)
d__3.MoveNext() line 69
— End of stack trace from previous location where exception was thrown —
TaskAwaiter.ThrowForNonSuccess(Task task)
TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
ThreadOperations.ExecuteWithAbortSafety(Action action)

Hello @usernameisalreadyinuse, We opened a ZIPNET-1001 issue for this bug and let you know on any progress with it.

Hi @usernameisalreadyinuse,
You need to use ArchiveFactory.GetArchive(Stream stream) to achive that.

I should also note that Activator.CreateInstance is not suitable for achieving your goal, since different types have different constructors.

Hello,
I’m just testing the function using the new build, does it differ between Zip and Zipx?
How to detect?
Thanks

Hello. It seems it is impossible to distinguish:

WinZip’s ZIPX standard is based on PKZip’s ZIP format specifications, with only difference of employing newer data compression algorithms - BZip2, LZMA / LZMA2 (XZ), PPMd and others (superseding classic Deflate / Deflate64 algorithm) - and employing custom pre-compression filters(WavPack, MP3 and JPEG filter) to improve compression of images and other media data structures.

We support Store, Deflate, Deflate64™, Bzip2, Lzma, Xz, PPMd compression methods for ZIP container.
Deflate64™ is a trademark of PKWARE Inc.