Skip to content

Instantly share code, notes, and snippets.

@grahamedgecombe
Created June 11, 2010 10:37
Show Gist options
  • Save grahamedgecombe/434341 to your computer and use it in GitHub Desktop.
Save grahamedgecombe/434341 to your computer and use it in GitHub Desktop.
A line counter utility, written in Java, to demonstrate the new NIO file API.
/*
* Copyright (C) 2010 Graham Edgecombe.
*
* 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/>.
*/
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Pattern;
/**
* A utility for counting the number of lines in a file.
* @author Graham Edgecombe
*/
public final class LineCounter extends SimpleFileVisitor<Path> {
/**
* The entry point of the application.
* @param args The command line arguments.
*/
public static void main(String[] args) {
if (args.length != 2) {
System.err.println("Usage:");
System.err.println(" " + LineCounter.class.getName() + " [path] [pattern]");
System.err.println();
System.err.println("Where [path] is the relative or absolute path and [pattern] is the regex pattern for matching countable files.");
return;
}
Pattern pattern = Pattern.compile(args[1]);
AtomicInteger fileCounter = new AtomicInteger();
AtomicInteger lineCounter = new AtomicInteger();
Path path = Paths.get(args[0]).normalize();
Files.walkFileTree(path, new LineCounter(pattern, fileCounter, lineCounter));
System.out.println(lineCounter.get() + " lines in " + fileCounter.get() + " files");
System.out.println(" in " + path + " and subdirectories");
System.out.println(" matching the pattern " + pattern);
}
/**
* The file name pattern.
*/
private final Pattern pattern;
/**
* The file counter.
*/
private final AtomicInteger fileCounter;
/**
* The line counter.
*/
private final AtomicInteger lineCounter;
/**
* Creates the line counter.
* @param pattern The pattern.
* @param fileCounter The file counter.
* @param lineCounter The line counter.
*/
public LineCounter(Pattern pattern, AtomicInteger fileCounter, AtomicInteger lineCounter) {
this.pattern = pattern;
this.fileCounter = fileCounter;
this.lineCounter = lineCounter;
}
/*
* (non-Javadoc)
* @see java.nio.file.SimpleFileVisitor#visitFile(java.lang.Object, java.nio.file.attribute.BasicFileAttributes)
*/
@Override
public FileVisitResult visitFile(Path path, BasicFileAttributes attributes) {
try {
if (pattern.matcher(path.toString()).find()) {
fileCounter.incrementAndGet();
FileChannel channel = FileChannel.open(path, StandardOpenOption.READ);
ByteBuffer buffer;
try {
buffer = channel.map(MapMode.READ_ONLY, 0, channel.size());
} finally {
channel.close();
}
int lines = 0;
for (int i = 0; i < buffer.remaining(); i++) {
byte b = buffer.get();
if (b == '\n') {
lines++;
}
}
lineCounter.addAndGet(lines);
}
return FileVisitResult.CONTINUE;
} catch (IOException ex) {
return FileVisitResult.TERMINATE;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment