I needed to be able to iterate over the first n number of files in a directory, without bringing them all back at once using File.list()
. This is simple enough to do in Java 7 using the new DirectoryStream
interface, but I only had access to Java 6 for this project.
Similar functionality can be reproduced using calls to native operating system functions using Java Native Access.
This example works on Linux but could easily be adapted for Windows.
DirectoryStream.java
package org.adrianwalker; import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.Pointer; import com.sun.jna.Structure; import java.io.Closeable; import java.io.File; import java.io.IOException; import java.util.Iterator; import java.util.NoSuchElementException; public final class DirectoryStream implements Iterable<File>, Closeable { private String dirName; private POSIX posix; private Pointer dirp; public DirectoryStream(final String dirName) { this.dirName = dirName; this.posix = (POSIX) Native.loadLibrary("c", POSIX.class); } @Override public Iterator<File> iterator() { return new Iterator<File>() { private boolean gotNext = false; private Dirent file; @Override public boolean hasNext() { if (!gotNext) { getNext(); } return file != null; } @Override public File next() { if (!gotNext) { getNext(); } if (null == file) { throw new NoSuchElementException(); } gotNext = false; return new File(dirName, file.getName()); } @Override public void remove() { throw new UnsupportedOperationException(); } private void getNext() { if (null == dirp) { dirp = posix.opendir(dirName); } file = posix.readdir(dirp); gotNext = true; } }; } @Override public void close() throws IOException { posix.closedir(dirp); } public interface POSIX extends Library { public Pointer opendir(String dirname); Dirent readdir(Pointer dirp); int closedir(Pointer dirp); } public static final class Dirent extends Structure { public long d_ino; public long d_off; public short d_reclen; public char d_type; public char[] d_name = new char[256]; public String getName() { return getPointer().getString(8 + 8 + 2 + 1, false); } public long getInode() { return getPointer().getLong(0); } public void setUseMemory(Pointer p) { useMemory(p); } } }
Example usage:-
Main.java
package org.adrianwalker; import java.io.File; import java.io.IOException; public final class Main { private static final int MAX_FILES = 10; private static final String CURRENT_DIR = "."; private static final String PARENT_DIR = ".."; public static void main(final String[] args) throws IOException { String dirName = "/tmp/files"; DirectoryStream directoryStream = new DirectoryStream(dirName); int fileCount = 0; for (File file : directoryStream) { String name = file.getName(); if (name.equals(CURRENT_DIR) || name.equals(PARENT_DIR)) { continue; } if (fileCount++ == MAX_FILES) { break; } System.out.println(file); } } }
Source Code
- JNA DirectoryStream Maven Project - jna-directorystream.zip
Usage
Build the project with 'mvn clean install
' and run the Main
class.