alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (Grep.java)

This example Java source code file (Grep.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

file, grep, ioexception, list, numberformatexception, option, pattern, regex, stream, there, uncheckedioexception, unexpected, util

The Grep.java Java example source code

/*
 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Oracle nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * This source code is provided to illustrate the usage of a given feature
 * or technique and has been deliberately simplified. Additional steps
 * required for a production-quality application, such as security checks,
 * input validation, and proper error handling, might not be present in
 * this sample code.
 */

import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toList;

/**
 * Grep prints lines matching a regex. See {@link #printUsageAndExit(String...)}
 * method for instructions and command line parameters. This sample shows
 * examples of using next features:
 * <ul>
 * <li>Lambda and bulk operations. Working with streams:
 * map(...),filter(...),flatMap(...),limit(...) methods.</li>
 * <li>Static method reference for printing values.
 * <li>New Collections API forEach(...) method.
 * <li>Try-with-resources feature.
 * <li>new Files.walk(...), Files.lines(...) API.
 * <li>Streams that need to be closed.
 * </ul>
 *
 */
public class Grep {

    private static void printUsageAndExit(String... str) {
        System.out.println("Usage: " + Grep.class.getSimpleName()
                + " [OPTION]... PATTERN FILE...");
        System.out.println("Search for PATTERN in each FILE. "
                + "If FILE is a directory then whole file tree of the directory"
                + " will be processed.");
        System.out.println("Example: grep -m 100 'hello world' menu.h main.c");
        System.out.println("Options:");
        System.out.println("    -m NUM: stop analysis after NUM matches");
        Arrays.asList(str).forEach(System.err::println);
        System.exit(1);
    }

    /**
     * The main method for the Grep program. Run program with empty argument
     * list to see possible arguments.
     *
     * @param args the argument list for Grep.
     * @throws java.io.IOException If an I/O error occurs.
     */
    public static void main(String[] args) throws IOException {
        long maxCount = Long.MAX_VALUE;
        if (args.length < 2) {
            printUsageAndExit();
        }
        int i = 0;
        //parse OPTIONS
        while (args[i].startsWith("-")) {
            switch (args[i]) {
                case "-m":
                    try {
                        maxCount = Long.parseLong(args[++i]);
                    } catch (NumberFormatException ex) {
                        printUsageAndExit(ex.toString());
                    }
                    break;
                default:
                    printUsageAndExit("Unexpected option " + args[i]);
            }
            i++;
        }
        //parse PATTERN
        Pattern pattern = Pattern.compile(args[i++]);
        if (i == args.length) {
            printUsageAndExit("There are no files for input");
        }

        try {
            /*
            * First obtain the list of all paths.
            * For a small number of arguments there is little to be gained
            * by producing this list in parallel. For one argument
            * there will be no parallelism.
            *
            * File names are converted to paths. If a path is a directory then
            * Stream is populated with whole file tree of the directory by
            * flatMap() method. Files are filtered from directories.
            */
            List<Path> files = Arrays.stream(args, i, args.length)
                    .map(Paths::get)
                    // flatMap will ensure each I/O-based stream will be closed
                    .flatMap(Grep::getPathStream)
                    .filter(Files::isRegularFile)
                    .collect(toList());
            /*
            * Then operate on that list in parallel.
            * This is likely to give a more even distribution of work for
            * parallel execution.
            *
            * Lines are extracted from files. Lines are filtered by pattern.
            * Stream is limited by number of matches. Each remaining string is
            * displayed in std output by method reference System.out::println.
            */
            files.parallelStream()
                    // flatMap will ensure each I/O-based stream will be closed
                    .flatMap(Grep::path2Lines)
                    .filter(pattern.asPredicate())
                    .limit(maxCount)
                    .forEachOrdered(System.out::println);
        } catch (UncheckedIOException ioe) {
            printUsageAndExit(ioe.toString());
        }
    }

    /**
     * Flattens file system hierarchy into a stream. This code is not inlined
     * for the reason of Files.walk() throwing a checked IOException that must
     * be caught.
     *
     * @param path - the file or directory
     * @return Whole file tree starting from path, a stream with one element -
     * the path itself - if it is a file.
     */
    private static Stream<Path> getPathStream(Path path) {
        try {
            return Files.walk(path);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    /**
     * Produces a stream of lines from a file. The result is a stream in order
     * to close it later. This code is not inlined for the reason of
     * Files.lines() throwing a checked IOException that must be caught.
     *
     * @param path - the file to read
     * @return stream of lines from the file
     */
    private static Stream<String> path2Lines(Path path) {
        try {
            return Files.lines(path);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java Grep.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.