Sample code for 30+ languages & platforms
PureBasic

Streaming Compression

See more Compression Examples

Compress and decompress using a stream.

Chilkat PureBasic Downloads

PureBasic
IncludeFile "CkTask.pb"
IncludeFile "CkCompression.pb"
IncludeFile "CkStream.pb"
IncludeFile "CkFileAccess.pb"

Procedure ChilkatExample()

    success.i = 0

    ; This example assumes the Chilkat API to have been previously unlocked.
    ; See Global Unlock Sample for sample code.

    fac.i = CkFileAccess::ckCreate()
    If fac.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    compress.i = CkCompression::ckCreate()
    If compress.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    CkCompression::setCkAlgorithm(compress, "deflate")

    streamC.i = CkStream::ckCreate()
    If streamC.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    ; This example sets the source and sink of the stream to files.
    ; A stream can have use other streams as a source or sink,
    ; or the application can itself be the source/sink by directly
    ; reading or writing a stream.  (See below for an example of this..)
    CkStream::setCkSourceFile(streamC, "qa_data/hamlet.xml")
    CkStream::setCkSinkFile(streamC, "qa_output/hamlet_compressed.dat")

    ; Compress from source to sink.
    success = CkCompression::ckCompressStream(compress,streamC)
    If success <> 1
        Debug CkCompression::ckLastErrorText(compress)
        CkFileAccess::ckDispose(fac)
        CkCompression::ckDispose(compress)
        CkStream::ckDispose(streamC)
        ProcedureReturn
    EndIf

    Debug "File-to-file deflate compression successful."
    ; Note: The FileSize method returns a signed 32-bit integer.  If the file is potentially larger than 2GB, call FileSizeStr instead to return
    ; the size of the file as a string, then convert to an integer value.
    Debug "Original size = " + Str(CkFileAccess::ckFileSize(fac,CkStream::ckSourceFile(streamC)))
    Debug "Compressed size = " + Str(CkFileAccess::ckFileSize(fac,CkStream::ckSinkFile(streamC)))

    ; Now do file-to-file decompression
    streamD.i = CkStream::ckCreate()
    If streamD.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    CkStream::setCkSourceFile(streamD, "qa_output/hamlet_compressed.dat")
    CkStream::setCkSinkFile(streamD, "qa_output/hamlet_restored.xml")

    ; Decompress from source to sink.
    success = CkCompression::ckDecompressStream(compress,streamD)
    If success <> 1
        Debug CkCompression::ckLastErrorText(compress)
        CkFileAccess::ckDispose(fac)
        CkCompression::ckDispose(compress)
        CkStream::ckDispose(streamC)
        CkStream::ckDispose(streamD)
        ProcedureReturn
    EndIf

    Debug "File-to-file deflate decompression successful."

    ; Let's double-check to see that the files are equal in size and content:

    bFilesEqual.i = CkFileAccess::ckFileContentsEqual(fac,CkStream::ckSourceFile(streamC),CkStream::ckSinkFile(streamD))
    If bFilesEqual <> 1
        Debug "The output file is not equal to the input file!"
    Else
        Debug "The file was successfully compressed and decompressed."
    EndIf

    ; ---------------------------------------------------------------------
    ; Now let's decompress again, but this time w/ the application reading
    ; the decompressed data directly from a stream.
    streamA.i = CkStream::ckCreate()
    If streamA.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    CkStream::setCkSourceFile(streamA, "qa_output/hamlet_compressed.dat")

    ; Start decompressing in a background thread.
    task.i = CkCompression::ckDecompressStreamAsync(compress,streamA)
    success = CkTask::ckRun(task)

    ; Read decompressed data from streamA:
    decompressedText.s
    While (CkStream::ckEndOfStream(streamA) <> 1)
        If CkStream::ckDataAvailable(streamA) = 1
            decompressedText = CkStream::ckReadString(streamA)
            Debug decompressedText
        EndIf

    Wend

    ; Let's make sure the background task finished and that the decompress was successful.
    ; It should already be the case that the task is finished.
    While (CkTask::ckFinished(task) <> 1)
        CkTask::ckSleepMs(task,20)
    Wend

    ; The decompressor may have finished, but it is possible that data
    ; remains to be flushed.  
    If CkStream::ckDataAvailable(streamA) = 1
        decompressedText = CkStream::ckReadString(streamA)
        Debug decompressedText
    EndIf

    ; Did streamA succeed in reading the entire file?
    If CkTask::ckTaskSuccess(task) <> 1
        Debug "async decompress failed:"
        Debug CkTask::ckResultErrorText(task)
        success = 0
    EndIf

    Debug "The async decompress was successful."


    CkFileAccess::ckDispose(fac)
    CkCompression::ckDispose(compress)
    CkStream::ckDispose(streamC)
    CkStream::ckDispose(streamD)
    CkStream::ckDispose(streamA)


    ProcedureReturn
EndProcedure