0

I need help on WinZip commandlines. I currently have a commandline which works fine but crushes if the folder is more than 4GB. I have very large Tiffs files which are more than 100MB. I would like to split the file when it gets to 2GB.

here is my code

Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click
        deleteCount = 0
        Dim i, x As Integer
        Dim reNamedTo As String
        Dim newFileURL, newFolderURL As String
        Dim folderInfo As New System.Text.StringBuilder()

        Dim processedNumberCount As Integer = 0
        Dim numberOfErrors As Integer = 0
        Dim fileSucessfullyDone As Integer
        '  cboPattern.SelectedIndex = 0
        btnList_Click(sender, e)

        For i = 0 To ListBoxFoldersToBeDone.Items.Count - 1
            newFolderURL = ListBoxFoldersToBeDone.Items(i).ToString
            Try
                'must download winZip command line 32 / 64 bit depending on the verion of winZip u have
                Dim dirInfo As New System.IO.DirectoryInfo(newFolderURL)
                Dim folderName As String = (dirInfo.Name)
                reNamedTo = newFolderURL & "\" & folderName & ".zip"


                lblFolderBeingDone.Text = reNamedTo
                psiProcess.FileName = "C:\Program Files\Winzip\wzzip.exe"
                psiProcess.WorkingDirectory = newFolderURL
                psiProcess.WindowStyle = ProcessWindowStyle.Minimized
                psiProcess.ErrorDialog = False
                psiProcess.CreateNoWindow = True
                '  psiProcess.Arguments = ("" & " -a -p -r -m """ & reNamedTo & """ *.tif")
                psiProcess.Arguments = ("" & " -a -p -r """ & reNamedTo & """ *.tif")

                udtProc = Process.Start(psiProcess)
                udtProc.WaitForExit()
                'lblDeletingFiles.Text = reNamedTo
                processedNumberCount = processedNumberCount + 1
                lblCountItemsDone.Text = processedNumberCount.ToString
                pBar1.Value = processedNumberCount
                initStatusBar(processedNumberCount)
                listBoxFoldersDone.Items.Add(reNamedTo)
                deleteAfterZip(newFolderURL)
            Catch ex As Exception
                numberOfErrors = numberOfErrors + 1
                listBoxErrorFolders.Items.Add(reNamedTo)
            End Try
        Next

        udtProc.Close()
        listBoxFiles.Items.Clear()
        Dim title As String = "TIFF Files Zip Completed"
        Dim msg As String = "Process Complete , " & processedNumberCount & " files processed successfully.  " & numberOfErrors.ToString & " error(s) encountered"
        MessageBox.Show(msg, title)
        lblFolderBeingDone.Text = "-"

    End Sub
Amen Jlili
  • 1,884
  • 4
  • 28
  • 51
taff kavhu
  • 11
  • 2
  • Where do you declare `psiprocess`? – Amen Jlili Feb 26 '15 at 14:39
  • This is untested but with 7-zip (http://www.7-zip.org/) you can use the -v{size}[b|k|m|g] (bytes, kilo, mega, giga) option; i.e. v2g will split the archive into chunks of 2GB. – tezzo Feb 26 '15 at 16:36

1 Answers1

0

Would you be open to a different solution that doesn't use WinZip at all? The .Net runtime actually has compression built into it and recent versions have made it even easier to us to use.

For the code below to work you need to have .Net 4.5 and you need to add a reference to both System.IO.Compression and System.IO.Compression.FileSystem in your project. It walks a given folder, adds files to a zip file, and creates new zip files once a maximum byte threshold is reached. The only downside of this code is that the maximum byte threshold is calculated based on the uncompressed file length because the compressed size isn't known until later. However, based on your requirements this should be a problem.

The code's comments should hopefully explain everything. There are two methods, one takes an optional array of file extensions that you don't want to compress. To use the code to compress your desktop to a folder in your "My Documents" folder using a byte threshold of 50MB you'd just do something like:

Dim FolderToCompress = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
Dim FolderToSaveZipTo = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "ZIPs")

CompressFolder(FolderToCompress, FolderToSaveZipTo, "MyArchive", 1024 * 1024 * 50)

And here's the code:

''' <summary>
''' Compress a given folder splitting the zip files based on a supplied maximum uncompressed file length.
''' </summary>
''' <param name="folderToCompress">The folder to compress.</param>
''' <param name="folderToSaveZipFilesTo">The folder to save the compress files to.</param>
''' <param name="zipFileNameWithoutExtension">The file excluding the .zip extension to save to.</param>
''' <param name="maximumBytesToCompressPerFile">The maximum number of uncompress bytes that will be put into each zip file.</param>
''' <param name="fileExtensionsNotToCompress">An array of file extensions, including the leading period, to store only and not compress.</param>
Public Shared Sub CompressFolder(
                                    folderToCompress As String,
                                    folderToSaveZipFilesTo As String,
                                    zipFileNameWithoutExtension As String,
                                    maximumBytesToCompressPerFile As Long,
                                    fileExtensionsNotToCompress() As String
                                )
    ''Create the directory if it doesn't exist already
    Directory.CreateDirectory(folderToSaveZipFilesTo)

    ''Create a formattable string that increments an index each time
    Dim FileNameFormatForZip = zipFileNameWithoutExtension & "_{0}.zip"
    Dim CurrentZipFileIndex = 0

    ''The total amount of uncompressed files process so far
    Dim CurrentUncompressedBytesProcessedSoFar As Long = 0

    ''Objects that we'll init below
    Dim FileStreamForZip As Stream = Nothing
    Dim Zip As ZipArchive = Nothing

    ''Loop through each file in the given directory including all child directories
    For Each FI In Directory.EnumerateFiles(folderToCompress, "*.*", SearchOption.AllDirectories)

        ''Get the local file name relative to the parent directory
        Dim LocalName = FI.Replace(folderToCompress, "").TrimStart("\"c)

        ''If we don't currently have a stream created, create one
        If FileStreamForZip Is Nothing Then
            Dim FileToSaveZipTo = Path.Combine(folderToSaveZipFilesTo, String.Format(FileNameFormatForZip, CurrentZipFileIndex))
            FileStreamForZip = New FileStream(FileToSaveZipTo, FileMode.Create, FileAccess.Write, FileShare.None)

            Zip = New ZipArchive(FileStreamForZip, ZipArchiveMode.Create)
        End If

        ''Set a default compression level
        Dim CompressionLevel = System.IO.Compression.CompressionLevel.Optimal

        ''However, if the current file extension is on our do not compress list then only set it to store
        If fileExtensionsNotToCompress.Contains(New System.IO.FileInfo(FI).Extension) Then
            CompressionLevel = Compression.CompressionLevel.NoCompression
        End If

        ''Create our zip entry
        Dim ZE = Zip.CreateEntry(LocalName, CompressionLevel)

        ''Add our file's contents to the entry
        Using ZipStream = ZE.Open()
            Using FileStream = File.Open(FI, FileMode.Open, FileAccess.Read, FileShare.Read)
                FileStream.CopyTo(ZipStream)
            End Using
        End Using

        ''Increment our file byte counter by the uncompressed file's original size
        ''Unfortunately we can't use the ZE.CompressedLength because that is only available
        ''during the reading of a ZIP file
        CurrentUncompressedBytesProcessedSoFar += New System.IO.FileInfo(FI).Length

        ''If we're over the threshold for maximum bytes
        If CurrentUncompressedBytesProcessedSoFar >= maximumBytesToCompressPerFile Then

            ''Clean up and dispose of our objects
            Zip.Dispose()
            Zip = Nothing
            FileStreamForZip.Dispose()
            FileStreamForZip = Nothing

            ''Reset our counter
            CurrentUncompressedBytesProcessedSoFar = 0

            ''Increment the current file index
            CurrentZipFileIndex += 1
        End If
    Next

    ''Clean up
    If Zip IsNot Nothing Then
        Zip.Dispose()
        Zip = Nothing
    End If

    If FileStreamForZip IsNot Nothing Then
        FileStreamForZip.Dispose()
        FileStreamForZip = Nothing
    End If
End Sub

''' <summary>
''' Compress a given folder splitting the zip files based on a supplied maximum uncompressed file length.
''' </summary>
''' <param name="folderToCompress">The folder to compress.</param>
''' <param name="folderToSaveZipFilesTo">The folder to save the compress files to.</param>
''' <param name="zipFileNameWithoutExtension">The file excluding the .zip extension to save to.</param>
''' <param name="maximumBytesToCompressPerFile">The maximum number of uncompress bytes that will be put into each zip file.</param>
Public Shared Sub CompressFolder(folderToCompress As String, folderToSaveZipFilesTo As String, zipFileNameWithoutExtension As String, maximumBytesToCompressPerFile As Long )
    CompressFolder(folderToCompress, folderToSaveZipFilesTo, zipFileNameWithoutExtension, maximumBytesToCompressPerFile, {".zip", ".mp4", ".wmv"})

End Sub
Chris Haas
  • 53,986
  • 12
  • 141
  • 274