CIB merge technical documentation (EN)

11. Quick start

This chapter gives you a short overview of possible use of CIB merge from a customer application. The examples do not use the full functional range, but demonstrate the basic principle of using CIB merge.

For your specific use case, please contact CIB Support for further examples.


Note:

For quick use of CIB merge via the CIB runshell from the command line, there are ready-made examples in the transfer package. The calls of the CIB runshell are predefined in batch files.


Integrating CIB merge as C++ Codebeispiel

In the chapter Use case examples there are already code examples available, which demonstrate, how CIB merge can be called from C++. One example shows the call of CIB merge transferring several single parameters and another example using a parameter file.

If you want to integrate CIB merge directly into your C++ application, CIB Support will be glad to provide you with an example.


Integrating CIB merge as Java code example

In the chapter Use case examples there are already code examples available, which demonstrate, how CIB merge can be called from JAVA. One example shows the call of CIB merge transferring several single parameters and another example using a parameter file.

If you want to integrate CIB merge directly into your JAVA application, CIB Support will be glad to provide you with an example.


Integrating CIB merge as VB code example

If you want to integrate CIB merge directly into your VB application, CIB Support will be glad to provide you with an example“.


Integrating CIB merge as Delphi code example

If you want to integrate CIB merge directly into your Delphi application, CIB Support will be glad to provide you with an example.


Note for using GZIP on JAVA

CIB merge allows ZLIB compression with multiple headers with -z. Under JAVA it is not possible to unpack such files immediately with the GZIP class.

Therefore the example code below supports this:

/*
 * Created on 01.08.2006
 * <p>
 * It was not possible to take the FilterInputStream as a base class because I
 * had to call super(gzin) in the constructor. This is supposed to be the first
 * line but there gzin is not initialized yet. Further is was not possible to
 * call super(new ExtendedGZIPInputStream(...)) because the nested class cannot
 * access the not then initialized enclosing class.
 * </p>
 */
package de.cib.java.util.zip;
 
import java.io.ByteArrayInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.util.zip.GZIPInputStream;
 
/**
 * <p>
 * This is a GZIPInputStream capable of reading a gzipped input stream
 * consisting of multiple members.
 * </p>
 * <p>
 * See RFC 1952 about gzip and multiple members.
 * </p>
 * <p>
 * This implementation is based upon the java.io.GZIPInputStream which is not
 * capable of reading further than the first member. For further information on
 * the implementation see the comment for the java file.
 * </p>
 *
 * @author CIB consulting GmbH, Tammo Wüsthoff
 */
public class MultipleMemberGZIPInputStream extends InputStream {
 
    /**
     * I need some data which is not public. So I have to subclass.
     *
     * @author Tammo
     */
   protected class ExtendedGZIPInputStream extends GZIPInputStream {
 
        /**
* Uses a default buffer size     *          * @param in         *            gzipped input stream         * @throws IOException         */        protected ExtendedGZIPInputStream(InputStream in) throws IOException {            super(in);
        } 
        /**         * @param in         *            gzipped input stream         * @param size         *            buffer size         * @throws java.io.IOException         */        public ExtendedGZIPInputStream(InputStream in, int size)                throws IOException {            super(in, size);
        }         /**        * @return a new InputStream with the unprocessed bytes only or null if         *         there were none         */        public InputStream createInputStreamForUnprocessedBytes() {            final int n = getRemaining();            if (n > 0) {                return new ByteArrayInputStream(buf, len - n, n);            }            return null;
        } 
        /**         * @return number of unprocessed bytes         */        public int getRemaining() {            return inf == null ? 0 : inf.getRemaining();
        } 
        /**         * @return true iff there is unprocessed data         */        public boolean hasRemaining() {            return getRemaining() > 0;
        }
    }
 
    /**
     * Unfortunately the trailer is checked in the unprocessed part of the
     * buffer inside the original GZIPInputStream. Well, if I want to continue
     * with the unprocessed data then I have to skip the trailer again. The
     * readTrailer() is private. So I have to guess the length. But the 8 bytes
     * are part of the specification RFC 1952.
     */    protected static final int trailerLength = 8;
 
    /**
     * gzipped input stream maybe with prepended unprocessed data
     */     protected InputStream base;
 
    /**
     * from time to time newly constructed input stream (once per gzip member)
     */    protected ExtendedGZIPInputStream gzin;
 
    /**
     * buffer size if given, -1 else, used for reconstruction of the member gzip
     */    private final int size;
 
    /**
     * Uses a default buffer size
     *
     * @param in     *            gzipped input stream
     * @throws IOException
     */    public MultipleMemberGZIPInputStream(InputStream in) throws IOException {        super();        base = in;
size = -1;        gzin = new ExtendedGZIPInputStream(in);
    }
 
    /**
     * @param in     *            gzipped input stream
     * @param size     *            buffer size
     * @throws IOException
     */
    public MultipleMemberGZIPInputStream(InputStream in, int size)
            throws IOException {
        super();
        base = in;
        this.size = size;
        gzin = new ExtendedGZIPInputStream(in, size);
    }
 
    /**
     * @see java.io.InputStream#available()
     */    public int available() throws IOException {        if (gzin.available() > 0 || base.available() > 0 || gzin.hasRemaining())            return 1;        return 0;
    }
 
    /**
     * @see java.io.InputStream#close()
     */    public void close() throws IOException {        gzin.close();
    }
 
    /**
     * @see java.io.InputStream#mark(int)
     */    public synchronized void mark(int readlimit) {        gzin.mark(readlimit);
    }
 
    /**
     * @see java.io.InputStream#markSupported()
     */    public boolean markSupported() {        return gzin.markSupported();
    }
 
    /**
     * read a single byte retrying if a gzip member ends just here
     *
     * @see java.io.InputStream#read()
     */
   public int read() throws IOException {        int value;        do {            value = gzin.read();
        } while (value == -1 && retry());        return value;
    }
 
    /**
     * @see java.io.InputStream#read(byte[])
     */
    public int read(byte[] b) throws IOException {        return read(b, 0, b.length);
    }
 
    /**
     * read a sequence of bytes retrying if a gzip member ends just here
     *
     * @see java.io.InputStream#read(byte[], int, int)
     */    public int read(byte[] b, int off, int len) throws IOException {        int n;        do {            n = gzin.read(b, off, len);
        } while (n == -1 && retry());        return n;
    }
 
    /**
     * @see java.io.InputStream#reset()
     */    public synchronized void reset() throws IOException {        gzin.reset();
    }
 
    /**
     * If unprocessed input is available then prepend the remaining bytes to the
     * input and skip the trailer. If no unprocessed input is available or after
     * skipping the trailer look if there are more bytes in the input. If yes
     * then make a new gzip input.
     *
     * @return true iff further data available
     * @throws IOException
     */
    protected boolean retry() throws IOException {        InputStream unprocessed = gzin.createInputStreamForUnprocessedBytes();        if (unprocessed != null) {
            base = new SequenceInputStream(unprocessed, base);            base.skip(Math.min(trailerLength, gzin.getRemaining()));
        }
        // well, looking if there are more bytes using available fails for
// several reasons; other solution: try to initialize gzin; this should        // read the gzip header or give eof        try {            if (size == -1) {                gzin = new ExtendedGZIPInputStream(base);            } else {                gzin = new ExtendedGZIPInputStream(base, size);            }
        } catch (EOFException e) {            return false;
        }        return true;
    }
 
    /**
     * @see java.io.InputStream#skip(long)
     */    public long skip(long n) throws IOException {        return gzin.skip(n);
    }
}
 
    private static void testGunzip() {
        try {
            FileInputStream fin = new FileInputStream(                    "d:\\cib\\temp\\output.rtf");
            MultipleMemberGZIPInputStream gzin = new MultipleMemberGZIPInputStream(
                    fin);
            StringBuffer stringbuffer = new StringBuffer();
            final int size = 512;
            byte[] bytebuffer = new byte[size];
            char[] charbuffer = new char[size * 4];
            int read;
            while ((read = gzin.read(bytebuffer)) != -1) {
                int converted = ByteToCharConverter.getDefault().convert(
                        bytebuffer, 0, read, charbuffer, 0, charbuffer.length);
                stringbuffer.append(charbuffer, 0, converted);
            }
            String output = stringbuffer.toString();
            System.out.println(output);
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    }