Package org.jnode.command.file

Source Code of org.jnode.command.file.WcCommand$WcStream$ByteCountInputStream

/*
* $Id$
*
* Copyright (C) 2003-2014 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.command.file;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import org.jnode.shell.AbstractCommand;
import org.jnode.shell.syntax.Argument;
import org.jnode.shell.syntax.FileArgument;
import org.jnode.shell.syntax.FlagArgument;

/**
* Count the words, lines and bytes or characters in a file or stream.
*
* @see <a href="http://www.opengroup.org/onlinepubs/7990989775/xcu/wc.html">POSIX "wc" command</a>
* @author cy6erGn0m
* @author Yves Galante
*/
public class WcCommand extends AbstractCommand {

    private static final String STR_SUPER = "Print newline, word, and byte counts for each file.";
    private static final String STR_TOTAL = "total";
    private static final String STR_ERROR_DIR = "File is a directory : ";
    private static final String STR_ERROR_NOT_EXIST = "File not exist : ";
    private static final String STR_ERROR_CANT_READ = "File can't be read : ";
    private static final String STR_ERROR_IO_EX = "IO error";
    private static final String HELP_BYTES = "Write to the standard output the number of bytes.";
    private static final String HELP_LINES = "Write to the standard output the number of newline characters.";
    private static final String HELP_CHARS = "Write to the standard output the number of characters.";
    private static final String HELP_WORDS = "Write to the standard output the number of words.";
    private static final String HELP_MAX_CHARS = "Write to the standard output the number of characters of "
            + "the longest line.";

    private boolean printBytes = false;
    private boolean printLines = false;
    private boolean printChars = false;
    private boolean printWordsCount = false;
    private boolean printMaxCharsInLine = false;

    private final FileArgument filesArgs;
    private final FlagArgument bytesArgs;
    private final FlagArgument linesArgs;
    private final FlagArgument charsArgs;
    private final FlagArgument wordsArgs;
    private final FlagArgument maxChars;

    /**
     * Instantiates a new word count command.
     */
    public WcCommand() {
        super(STR_SUPER);
        filesArgs = new FileArgument("files", Argument.OPTIONAL | Argument.EXISTING | Argument.MULTIPLE);
        bytesArgs = new FlagArgument("bytes", Argument.OPTIONAL, HELP_BYTES);
        linesArgs = new FlagArgument("lines", Argument.OPTIONAL, HELP_LINES);
        charsArgs = new FlagArgument("chars", Argument.OPTIONAL, HELP_CHARS);
        wordsArgs = new FlagArgument("worlds", Argument.OPTIONAL, HELP_WORDS);
        maxChars  = new FlagArgument("maxCharLine", Argument.OPTIONAL, HELP_MAX_CHARS);
        registerArguments(filesArgs, bytesArgs, linesArgs, charsArgs, wordsArgs, maxChars);
    }
   
    @Override
    public void execute() {
        List<WcStream> results = new ArrayList<WcStream>(1);
        FileInputStream fis = null;
        // Initialize arguments
        initArgs();
        // Read from files
        if (filesArgs.isSet()) {
            for (File file : filesArgs.getValues()) {
                checkFile(file);
                try {
                    fis = new FileInputStream(file);
                    results.add(new WcStream().processStream(file.getName(), fis));
                } catch (IOException io) {
                    getError().getPrintWriter().println(STR_ERROR_IO_EX + " : " + file.getAbsolutePath());
                    exit(1);
                } finally {
                    if (fis != null) {
                        try {
                            fis.close();
                        } catch (IOException e) {
                            //
                        }
                        fis = null;
                    }
                }
            }
        } else {
            try {
                // Or read from input stream
                results.add(new WcStream().processStream(null, getInput().getInputStream()));
            } catch (IOException io) {
                getError().getPrintWriter().println(STR_ERROR_IO_EX);
                exit(1);
            }
        }
        // Print results
        printResults(getOutput().getPrintWriter(), results);
        exit(0);
    }

    private void checkFile(File file) {
        if (!file.exists()) {
            getError().getPrintWriter().println(STR_ERROR_NOT_EXIST + ' ' + file.getAbsolutePath());
            exit(1);
        } else if (file.isDirectory()) {
            getError().getPrintWriter().println(STR_ERROR_DIR + ' ' + file.getAbsolutePath());
            exit(1);
        } else if (!file.canRead()) {
            getError().getPrintWriter().println(STR_ERROR_CANT_READ + ' ' + file.getAbsolutePath());
            exit(1);
        }
    }

    /**
     * Initialize arguments.
     */
    private void initArgs() {
        if (bytesArgs.isSet() || linesArgs.isSet() || charsArgs.isSet() || wordsArgs.isSet()
                || maxChars.isSet()) {
            printBytes = bytesArgs.isSet();
            printChars = charsArgs.isSet();
            printLines = linesArgs.isSet();
            printWordsCount = wordsArgs.isSet();
            printMaxCharsInLine = maxChars.isSet();
        } else {
            // Default arguments
            printLines = true;
            printBytes = true;
            printChars = false;
            printWordsCount = true;
            printMaxCharsInLine = false;
        }
    }

    /**
     * Prints results.
     *
     * @param printWriter the print writer
     * @param listWc the world count stream list
     */
    private void printResults(PrintWriter printWriter, List<WcStream> listWc) {

        long totalBytesRead = 0;
        long totalCharsCount = 0;
        long totalLinesCount = 0;
        long totalWordsCount = 0;
        long maxCharsInLine = 0;
        int paddingSize = 0;

        for (WcStream wc : listWc) {
            totalBytesRead += wc.getBytesRead();
            totalCharsCount += wc.getCharsCount();
            totalLinesCount += wc.getLinesCount();
            totalWordsCount += wc.getWordsCount();
            if (maxCharsInLine < wc.getMaxCharsInLine()) {
                maxCharsInLine = wc.getMaxCharsInLine();
            }
        }
        // Compute the padding size for printing result on a table
        paddingSize = Long.toString(
                Math.max(totalBytesRead, Math.max(totalCharsCount, Math.max(totalLinesCount, totalWordsCount))))
                .length();

        for (WcStream wc : listWc) {
            printLine(printWriter, paddingSize, wc.getLinesCount(), wc.getWordsCount(), wc.getCharsCount(), wc
                    .getBytesRead(), wc.getMaxCharsInLine());
            if (wc.getFileName() != null) {
                printWriter.print(' ' + wc.getFileName());
            }
            printWriter.println();
        }
        // need print total line ?
        if (listWc.size() > 1) {
            printLine(printWriter, paddingSize, totalLinesCount, totalWordsCount, totalCharsCount, totalBytesRead,
                    maxCharsInLine);
            printWriter.println(' ' + STR_TOTAL);
        }
        printWriter.flush();
    }

    /**
     * Print a line result
     *
     * @param printWriter
     * @param paddingSize
     * @param linesCount
     * @param wordsCount
     * @param charsCount
     * @param bytesRead
     * @param charsInLine
     */
    private void printLine(PrintWriter printWriter, int paddingSize, long linesCount,
            long wordsCount, long charsCount, long bytesRead, long charsInLine) {
        boolean first = true;
        if (printLines) {
            print(printWriter, first, paddingSize, linesCount);
            first = false;
        }
        if (printWordsCount) {
            print(printWriter, first, paddingSize, wordsCount);
            first = false;
        }
        if (printChars) {
            print(printWriter, first, paddingSize, charsCount);
            first = false;
        }
        if (printBytes) {
            print(printWriter, first, paddingSize, bytesRead);
            first = false;
        }
        if (printMaxCharsInLine) {
            print(printWriter, first, paddingSize, charsInLine);
            first = false;
        }
    }

    /**
     * Print a result
     *
     * @param printWriter
     * @param first
     * @param paddingSize
     * @param value
     */
    private void print(PrintWriter printWriter, boolean first, int paddingSize, long value) {
        StringBuffer sValue = new StringBuffer(paddingSize + 1);

        sValue.append(value);
        while (sValue.length() < paddingSize) {
            sValue.insert(0, ' ');
        }
        if (!first) {
            sValue.insert(0, ' ');
        }
        printWriter.print(sValue);
    }

    /**
     * The Class WcStream.
     */
    private static class WcStream {

        /**
         * The Class ByteCountInputStream.
         */
        private static class ByteCountInputStream extends InputStream {

            private InputStream inputStream;

            private long bytesRead = 0;

            /**
             * Instantiates a new byte count input stream.
             *
             * @param in
             *            the input stream
             */
            private ByteCountInputStream(InputStream in) {
                super();
                inputStream = in;
            }

            /**
             * Gets the bytes read.
             *
             * @return the bytes read
             */
            public long getBytesRead() {
                return bytesRead;
            }

            @Override
            public int read() throws IOException {
                int rchar = inputStream.read();
                if (rchar != -1) {
                    bytesRead++;
                }
                return rchar;
            }

            @Override
            public int read(byte[] b, int off, int len) throws IOException {
                int wasRead = inputStream.read(b, off, len);
                if (wasRead > 0) {
                    bytesRead += wasRead;
                }
                return wasRead;
            }

            @Override
            public int read(byte[] b) throws IOException {
                int wasRead = inputStream.read(b);
                if (wasRead > 0) {
                    bytesRead += wasRead;
                }
                return wasRead;
            }

            @Override
            public int available() throws IOException {
                return inputStream.available();
            }

            @Override
            public boolean markSupported() {
                return false;
            }

            @Override
            public long skip(long n) throws IOException {
                long rChar = inputStream.skip(n);
                if (rChar > 0) {
                    bytesRead += rChar;
                }
                return rChar;
            }
        }

        private String fileName = null;

        private long bytesRead = 0;

        private long charsCount = 0;

        private long linesCount = 0;

        private long wordsCount = 0;

        private int maxCharsInLine = 0;

        private int charsInLine = 0;

        private WcStream() {
            // default constructor
        }

        public String getFileName() {
            return fileName;
        }

        public long getBytesRead() {
            return bytesRead;
        }

        public long getCharsCount() {
            return charsCount;
        }

        public long getLinesCount() {
            return linesCount;
        }

        public long getWordsCount() {
            return wordsCount;
        }

        public int getMaxCharsInLine() {
            return maxCharsInLine;
        }

        /**
         * Process the stream.
         *
         * @param fileName
         *            the file name, can be null
         * @param inputStream
         *            the input stream
         *
         * @throws IOException
         *             Signals that an I/O exception has occurred.
         */
        private WcStream processStream(String name, InputStream inputStream) throws IOException {
            ByteCountInputStream bic = new ByteCountInputStream(inputStream);
            InputStreamReader reader = null;
            fileName = name;

            reader = new InputStreamReader(bic);
            boolean wasR = false;
            boolean wasWord = false;
            int iChar = reader.read();
            for (; iChar >= 0; iChar = reader.read()) {
                char cChar = (char) iChar;
                if (cChar == '\r') {
                    wasWord = false;
                    wasR = true;
                    linesCount++;
                    charsCount++;
                    if (charsInLine > maxCharsInLine) {
                        maxCharsInLine = charsInLine;
                        charsInLine = 0;
                    }
                } else if (cChar == '\n') {
                    if (!wasR) {
                        linesCount++;
                        if (charsInLine > maxCharsInLine) {
                            maxCharsInLine = charsInLine;
                            charsInLine = 0;
                        }
                    }
                    wasWord = false;
                    wasR = false;
                    charsCount++;
                } else if (cChar == ' ' || cChar == '\t') {
                    wasR = false;
                    wasWord = false;
                    charsCount++;
                    charsInLine++;
                } else {
                    if (!wasWord) {
                        wasWord = true;
                        wordsCount++;
                    }
                    charsCount++;
                    charsInLine++;
                }
            }
            bytesRead = bic.getBytesRead();
            return this;
        }
    }

    /**
     * The main method.
     *
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        new WcCommand().execute(args);
    }
}
TOP

Related Classes of org.jnode.command.file.WcCommand$WcStream$ByteCountInputStream

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.