sk.baka.aedict.indexer.SodMain.java Source code

Java tutorial

Introduction

Here is the source code for sk.baka.aedict.indexer.SodMain.java

Source

/**
Aedict - an EDICT browser for Android
Copyright (C) 2009 Martin Vysny
    
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
    
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
    
You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package sk.baka.aedict.indexer;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.GZIPOutputStream;
import org.apache.commons.io.IOUtils;

/**
 * Indexes the SOD images. Expects a directory with unpacked SOD archive contents - essentially a bunch of png files named
 * [KANJI].png. This directory is packed to a huge file, packed with gzip, with the following contents:
 * <h4>The header:</h4>
 * 4 byte int - number of kanji entries; for each entry: 2-byte UTF-16 kanji character, 4-byte png offset in the file.
 * The entries are ordered by the "offset" value, ascending.
 *<h4>The contents:</h4>
 * Basically just a streams of PNG images, one after another.
 * @author Martin Vysny
 */
public class SodMain {

    /**
     * Runs the indexer.
     * @param args requires a single parameter: the unpacked sod-utf8.tar.gz location.
     */
    public static void main(String[] args) throws Exception {
        new SodMain(args).run();
    }

    private final File sodUtf8Location;

    private SodMain(String[] args) throws IOException {
        sodUtf8Location = new File(args[0]);
        if (!sodUtf8Location.exists()) {
            throw new IOException(sodUtf8Location + " does not exist");
        }
    }

    private final Map<Character, File> pngLengths = new HashMap<Character, File>();

    private void run() throws IOException {
        computePngLengths();
        createPackedFile();
        System.out.println("Done");
    }

    private void computePngLengths() {
        // list all png files
        final File[] pngs = sodUtf8Location.listFiles(new FilenameFilter() {

            public boolean accept(File dir, String name) {
                return name.endsWith(".png");
            }
        });
        for (final File png : pngs) {
            final String kanji = png.getName().substring(0, png.getName().length() - 4);
            if (kanji.length() != 1) {
                throw new RuntimeException(
                        "Found a png file " + png + " with an invalid name (the name must be [KANJI].png");
            }
            pngLengths.put(kanji.charAt(0), png);
        }
    }

    private void createPackedFile() throws IOException {
        System.out.println("Packaging " + pngLengths.size() + " pngs");
        final DataOutputStream out = new DataOutputStream(
                new GZIPOutputStream(new FileOutputStream("target/sod.dat.gz")));
        try {
            // write index table
            int offset = pngLengths.size() * 6 + 4;
            out.writeInt(pngLengths.size());
            final List<Character> kanjis = new ArrayList<Character>(pngLengths.keySet());
            for (final Character kanji : kanjis) {
                out.writeChar(kanji);
                out.writeInt(offset);
                offset += (int) pngLengths.get(kanji).length();
            }
            // write png contents
            for (final Character kanji : kanjis) {
                final InputStream in = new FileInputStream(pngLengths.get(kanji));
                try {
                    IOUtils.copy(in, out);
                } finally {
                    IOUtils.closeQuietly(in);
                }
            }
        } finally {
            IOUtils.closeQuietly(out);
        }
    }
}