Search code examples
codenameone

Codename One API to append / merge files


To merge Storage files in Codename One I elaborated this solution:

    /**
     * Merges the given list of Storage files in the output Storage file.
     * @param toBeMerged
     * @param output
     * @throws IOException 
     */
    public static synchronized void mergeStorageFiles(List<String> toBeMerged, String output) throws IOException {

        if (toBeMerged.contains(output)) {
            throw new IllegalArgumentException("The output file cannot be contained in the toBeMerged list of input files.");
        }

        // Note: the temporary file used for merging is placed in the FileSystemStorage because it offers the method
        // openOutputStream(String file, int offset) that allows appending to a stream. Storage doesn't have a such method.

        long writtenBytes = 0;
        String tempFile = FileSystemStorage.getInstance().getAppHomePath() + "/tempFileUsedInMerge";
        for (String partialFile : toBeMerged) {
            InputStream in = Storage.getInstance().createInputStream(partialFile);
            OutputStream out = FileSystemStorage.getInstance().openOutputStream(tempFile, (int) writtenBytes);
            Util.copy(in, out);
            writtenBytes = FileSystemStorage.getInstance().getLength(tempFile);
        }
        Util.copy(FileSystemStorage.getInstance().openInputStream(tempFile), Storage.getInstance().createOutputStream(output));
        FileSystemStorage.getInstance().delete(tempFile);
    }

This solution is based on the API FileSystemStorage.openOutputStream(String file, int offset), that is the only API that I found to allow to append the content of a file to another.

Are there other API that can be used to append or merge files?

Thank you


Solution

  • Since you end up copying everything to a Storage entry I don't see the value of using FileSystemStorage as an intermediate merging tool.

    The only reason I can think of is integrity of the output file (e.g. if failure happens while writing) but that can happen here too. You can guarantee integrity by setting a flag e.g. creating a file called "writeLock" and deleting it when write has finished successfully.

    To be clear I would copy like this which is simpler/faster:

    try(OutputStream out = Storage.getInstance().createOutputStream(output)) {
        for (String partialFile : toBeMerged) {
            try(InputStream in = Storage.getInstance().createInputStream(partialFile)) {
                Util.copyNoClose(in, out, 8192);
            }
        }
    }