Java dir/files list - java

I am trying to list all directories and files within a certain directory, but while "D:\data" works, "D:\" doesn't. "D" is a secondary disk.
This is the exception:
Exception in thread "main" java.lang.NullPointerException
at java.util.Objects.requireNonNull(Objects.java:203)
at java.util.Arrays$ArrayList.<init>(Arrays.java:3813)
at java.util.Arrays.asList(Arrays.java:3800)
at project.1.scavenger.listf(scavenger.java:19)
at project.1.scavenger.listf(scavenger.java:30)
at project.1.scavenger.listf(scavenger.java:30)
at project.1.main(Project1.java:28)
Java Result: 1
BUILD SUCCESSFUL (total time: 0 seconds)
Code:
public static List<File> listf(String directoryName) throws IOException {
File directory = new File(directoryName);
List<File> resultList = new ArrayList<File>();
// get all the files from a directory
File[] fList = directory.listFiles();
resultList.addAll(Arrays.asList(fList));
for (File file : fList) {
if (file.isFile()) {
System.out.println(file.getAbsolutePath());
try {
System.out.println(scavenger.checkmime(file.getAbsolutePath()));
} catch (Exception ex) {
}
} else if (file.isDirectory()) {
resultList.addAll(listf(file.getAbsolutePath()));
}
}
// System.out.println(fList);
return resultList;
}
public static String checkmime(String fl) throws MalformedURLException, IOException {
File file = new File(fl);
String mimeType = file.toURL().openConnection().getContentType();
// System.out.println(mimeType);
return mimeType;
}
What's wrong with my code?

Removed error from your version
In your recursion you never ask for null values. Do it and it should run like this:
public static List<File> listf(String directoryName) throws IOException {
File directory = new File(directoryName);
List<File> resultList = new ArrayList<>();
// get all the files from a directory
File[] fList = directory.listFiles();
// this was missing
if (fList == null) {
return null;
}
resultList.addAll(Arrays.asList(fList));
for (File file : fList) {
if (file.isFile()) {
System.out.println(file.getAbsolutePath());
try {
System.out.println(checkmime(file.getAbsolutePath()));
} catch (Exception ex) {
}
} else if (file.isDirectory()) {
// ask here if it was null
List<File> files = listf(file.getAbsolutePath());
if (files != null) {
resultList.addAll(files);
}
}
}
//System.out.println(fList);
return resultList;
}
Why D:\data works and D:\ not
In every root of a drive in a Windows System is a hidden folder structure called $RECYCLE.BIN. In this folder windows stores for each user (sid) an own folder with deleted data (links to it). But a normal user is only allowed to get the first level and not the user folder (with sid value as name).
(German Windows: Papierkorb = Trash)
A maybe much better solution:
A maybe better way of doing such searchings in tree's is to create an Iterator over the directory tree (like a composite iterator). This solution also uses only Java NIO features, so the platform should be changeable (haven't tested!) to for ex. Linux.
DirectoryTreeIterator.java
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
public class DirectoryTreeIterator implements Iterator<Path> {
private final Deque<Iterator<Path>> deque = new ArrayDeque<>();
public DirectoryTreeIterator(Iterator<Path> it) {
deque.push(it);
}
#Override
public boolean hasNext() {
if (deque.isEmpty()) {
return false;
} else {
Iterator<Path> it = deque.peek();
if (!it.hasNext()) {
deque.pop();
return hasNext();
} else {
return true;
}
}
}
#Override
public Path next() {
if (hasNext()) {
Iterator<Path> it = deque.peek();
Path p = it.next();
try {
// here is the magic recursive on only filtered paths
if (Files.isDirectory(p) && Files.isReadable(p) && !Files.isHidden(p)) {
deque.push(Files.newDirectoryStream(p).iterator());
}
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
return p;
} else {
return null;
}
}
}
Then you are able to use it like a charm:
FileLister.java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Iterator;
public class FileLister {
public static void main(String[] args) throws IOException {
Path p = Paths.get("D:\\");
Iterator<Path> it = Files.newDirectoryStream(p).iterator();
DirectoryTreeIterator dti = new DirectoryTreeIterator(it);
while (dti.hasNext()) {
Path path = dti.next();
if (!Files.isDirectory(path)) {
String mime = Files.probeContentType(path);
System.out.println("Mime of File "
+ path.getFileName() + " is: " + mime);
}
}
}
}

If you add this code right beneath the directory.listFiles() call:
if (fList == null) {
System.out.println("Couldn't read files in directory: " + directoryName);
return resultList;
}
then you will get a message like this:
Couldn't read files in directory: G:\$RECYCLE.BIN\Windows SID
This Windows SIDs is security identifier for a user on your local machine.
So that means your current user has no permission to read this directory (it belongs to a different user) in the "recycle bin" directory, therefore listFiles() returns null instead of a String[].
You could keep the check and the message I've posted, or you can implement a different way to handle "unreadable" directories.
About why "D:\\" failed and "D:\\data" not:
"D:\\" contains the mentioned "$RECYCLE.BIN" directory with restricted access
"D:\\data" has no directory where your current user isn't allowed to access/read it, therefore listFiles() never returned null.

Related

How find files in a directory knowing a part of the name

I have a problem, i have this directory with 1k+ files and some folders. I need find the path of the files(which are in subdirectories) that starts with "BCM", but not only the first i find but every single file which start with that.
I tried looking at other answers about this topic but i couldn't find help,
tried using this code:
File dir = new File("K:\\Jgencs");
FilenameFilter filter = new FilenameFilter()
{
public boolean accept (File dir, String name)
{
return name.startsWith("BCM");
}
};
String[] children = dir.list(filter);
if (children == null)
{
System.out.println("No directory found");
}
else
{
for (int i = 0; i< children.length; i++)
{
String filename = children[i];
System.out.println(filename);
File h = new File(dir,filename);
System.out.println(h.getAbsolutePath()
[UPDATED] This is how you can achieve using plain Java and filter text from a variable passing as parameter:
Here is my directory: /tmp
And here is the code running:
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class GetAllFilesInDirectory {
public static void main(String[] args) throws IOException {
String filter = "BCM";
List<File> files = listFiles("/tmp", new CustomerFileFilter(filter));
for (File file : files) {
System.out.println("file: " + file.getCanonicalPath());
}
}
private static List<File> listFiles(String directoryName, CustomerFileFilter fileFilter) {
File directory = new File(directoryName);
List<File> files = new ArrayList<>();
// Get all files from a directory.
File[] fList = directory.listFiles(fileFilter);
if(fList != null) {
for (File file : fList) {
if (file.isFile()) {
files.add(file);
} else if (file.isDirectory()) {
files.addAll(listFiles(file.getAbsolutePath(), fileFilter));
}
}
}
return files;
}
}
class CustomerFileFilter implements FileFilter {
private final String filterStartingWith;
public CustomerFileFilter(String filterStartingWith) {
this.filterStartingWith = filterStartingWith;
}
#Override
public boolean accept(File file) {
return file.isDirectory() || file.isFile() && file.getName().startsWith(filterStartingWith);
}
}
This is the output:
file: /private/tmp/BCM01.txt
file: /private/tmp/BCM01
file: /private/tmp/subfolder1/BCM02.txt
Doing recursive calls to the method when finding a directory to also list the files form inside, and filtering by name the files before adding.
You want Files.walk:
try (Stream<Path> files = Files.walk(Paths.get("K:\\Jgencs"))) {
files.filter(f -> f.getFileName().toString().startsWith("BCM")).forEach(
file -> System.out.println(file));
}

Include Copyright comment in header on existing and new class via eclipse formatter

I want include copyright comment on the top of every java file. I want to do it via eclipse formatter.
If it is not possible, please suggest any other way to include the copyright in existing java file.
Although it may not perfectly suit the intended approach (that is, using an eclipse plugin for that) : Once I created a small utility class that does exactly this.
It collects a list of all .java files in a given source directory. For each of the resulting files, it looks for the first line starting with the word "package". If the part above this line is not empty, then it will assume that a header is already present, and skip this file. Otherwise, it will insert a header (which is contained in some template file) before the line starting with "package".
This could arbitrarily be improved and generalized, but I only once wrote it down in order to quickly insert copyright headers into the files of an existing code base, and it worked well. Maybe you (or others) find it helpful.
import java.io.File;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
public class HeaderInserter
{
public static void main(String[] args)
{
String headerTemplateFileName = "HeaderTemplate.txt";
String path = "C:/Workspace/HeaderInserter/src";
insertHeaders(path, headerTemplateFileName);
}
private static void insertHeaders(String path, String headerTemplateFileName)
{
FilenameFilter filenameFilter = new FilenameFilter()
{
#Override
public boolean accept(File dir, String name)
{
return name.toLowerCase().endsWith(".java");
}
};
List<String> headerLines = readLines(headerTemplateFileName);
List<File> files = listFiles(new File(path), filenameFilter);
for (File file : files)
{
System.out.println("Inserting header into "+file);
handle(file, headerLines);
}
System.out.println("Done");
}
private static void handle(File inputFile, List<String> headerLines)
{
List<String> lines = readLines(inputFile.getPath());
int index = lineIndexStartingWith(lines, "package");
if (index == -1)
{
System.err.println("No 'package' line found in "+inputFile);
return;
}
if (index > 0)
{
List<String> removedLines = lines.subList(0, index);
String removedPart = createString(removedLines);
String removedContents = removedPart.replaceAll("\n", "");
if (removedContents.trim().length() > 0)
{
System.err.println("Non-empty header found in "+inputFile);
System.err.println(removedPart);
System.err.println("Skipping");
return;
}
}
List<String> keptLines = lines.subList(index, lines.size());
List<String> writtenLines = new ArrayList<String>();
writtenLines.addAll(headerLines);
writtenLines.addAll(keptLines);
String writtenContent = createString(writtenLines);
File outputFile = new File(inputFile.getName()+"_header");
boolean written = writeContent(outputFile, writtenContent);
if (written)
{
boolean deleted = inputFile.delete();
if (!deleted)
{
System.err.println(
"Could not delete old input file: "+inputFile);
return;
}
boolean renamed = outputFile.renameTo(inputFile);
if (!renamed)
{
System.err.println("Could not rename "+outputFile);
System.err.println(" to "+inputFile);
return;
}
System.out.println("Inserted header into "+inputFile);
}
}
private static int lineIndexStartingWith(
List<String> lines, String prefix)
{
for (int i=0; i<lines.size(); i++)
{
String line = lines.get(i);
if (line.trim().startsWith(prefix))
{
return i;
}
}
return -1;
}
private static String createString(List<String> lines)
{
StringBuilder sb = new StringBuilder();
for (String line : lines)
{
sb.append(line).append("\n");
}
return sb.toString();
}
private static boolean writeContent(
File outputFile, String writtenContent)
{
try (FileWriter fw = new FileWriter(outputFile))
{
fw.write(writtenContent);
fw.close();
return true;
}
catch (IOException e)
{
e.printStackTrace();
}
return false;
}
private static List<String> readLines(String fileName)
{
try
{
return Files.readAllLines(
Paths.get(fileName), Charset.defaultCharset());
}
catch (IOException e)
{
e.printStackTrace();
return null;
}
}
private static List<File> listFiles(
File rootDirectory, FilenameFilter filenameFilter)
{
List<File> result = new ArrayList<File>();
listFiles(rootDirectory, filenameFilter, result);
return result;
}
private static void listFiles(
File file, FilenameFilter filenameFilter, List<File> result)
{
if (!file.isDirectory())
{
if (filenameFilter.accept(file.getParentFile(), file.getName()))
{
result.add(file);
}
}
else
{
File files[] = file.listFiles();
for (File f : files)
{
listFiles(f, filenameFilter, result);
}
}
}
}
Try Eclipse Releng Tools here
Write a script to update each file and add first line - use eclipse find and replace regex
http://java.dzone.com/articles/using-regular-expressions

Recursively file search not working

What i wanna do is to recursively search for some files on the external sd-card. The problem is that the code is looking ok, but (assuming .txt files) it only shows me 7 files out of 100+ that are being spread throughout folders.
The code is this:
file = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
void makelist(File file){
if(file.isFile()){
if(SimpleAdapter.getFileType(file)==null)
mis.add(file);
else if(SimpleAdapter.getFileType(file).equalsIgnoreCase("text"))
doc.add(file);
}else if(file.isDirectory()){
for(File f:file.listFiles())
makelist(f);
}
}
Any idea how could i make it run correctly?
Assuming you are building two lists (misc files and doc files), try with below code which all all files other than text files to misc and text files to doc.
if(SimpleAdapter.getFileType(file) == null || !SimpleAdapter.getFileType(file).equalsIgnoreCase("text"))
mis.add(file);
else
doc.add(file);
Not sure why it is not working for you. Tried a test program and it worked perfectly...
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class FileChecker
{
/**
* #param args
*/
public static void main(String[] args) {
SimpleAdapterTest adapter = new SimpleAdapterTest();
adapter.makelist(new File("C:\\MYFolder"));
adapter.showList();
}
}
class SimpleAdapterTest
{
List<File> mis = new ArrayList<File>();
List<File> doc = new ArrayList<File>();
public static String getFileType(File f)
{
String Name = f.getName();
if (f.getName().endsWith(".txt") || Name.endsWith(".TXT")
|| Name.endsWith(".inf") || Name.endsWith(".INF"))
return "text";
return null;
}
public void makelist(File file){
if(file.isFile()){
if(SimpleAdapterTest.getFileType(file)==null)
mis.add(file);
else if(SimpleAdapterTest.getFileType(file).equalsIgnoreCase("text"))
doc.add(file);
}else if(file.isDirectory()){
for(File f:file.listFiles())
makelist(f);
}
}
public void showList()
{
for(File miscFile : mis)
{
System.out.println("Misc files = " + miscFile.getName());
}
for(File docfile : doc)
{
System.out.println("Doc files = " + docfile.getName());
}
}
}

Comparing file names

I want to compare file lying in two different folders.
I wish to compare only files which have same name in those two different folders.
What I wish to do is to compare two different versions of a software and find how many files have been changed.
This will help you get files for two paths:
import java.io.File;
import java.util.*;
public class ListFiles
{
public static void main(String[] args)
{
// First directory path here.
String path1 = ".";
// Second directory path here.
String path2 = ".";
// File class is very important.
// If you did a simple Google search
// Then you would have seen this class mentioned.
File folder1 = new File(path1);
File folder2 = new File(path2);
// It gets the list of files for you.
File[] listOfFiles1 = folder1.listFiles();
File[] listOfFiles2 = folder2.listFiles();
// We'll need these to store the file names as Strings.
ArrayList<String> fileNames1 = new ArrayList<String>();
ArrayList<String> fileNames2 = new ArrayList<String>();
// Get file names from first directory.
for (int i = 0; i < listOfFiles1.length; i++)
{
if (listOfFiles1[i].isFile())
{
fileNames1.add(listOfFiles1[i].getName());
}
}
// Get file names from second directory.
for (int i = 0; i < listOfFiles2.length; i++)
{
if (listOfFiles2[i].isFile())
{
fileNames2.add(listOfFiles2[i].getName());
}
}
// Now compare
// Loop through the two array lists and add your own logic.
}
}
You will need to add your own logic to compare. Source
I have this code which compares all the files in the directory with a particular file to check if that files aleady exists in the directory,may tweak that a little as per your needs.It uses commons-io.jar
import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.io.FileUtils;
public class CompareFile {
String directory;
File file;
public CompareFile(String directory, File file) {
this.directory = directory;
this.file = file;
}
public boolean doesFileExist() {
boolean indicatorFileExist = true;
List<File> files = null;
try {
files = getFiles();
files = files.stream().filter(fileMatch -> {
try {
if(fileMatch.isFile()){
return FileUtils.contentEquals(fileMatch, file);
}else{
return false;
}
} catch (Exception excep) {
excep.printStackTrace();
return false;
}
}).collect(Collectors.toList());
if(files.isEmpty()){
indicatorFileExist = false;
}
} catch (Exception excep) {
excep.printStackTrace();
} finally {
if (files != null) {
files = null;
}
}
return indicatorFileExist;
}
private List<File> getFiles() {
List<File> fileList = null;
try {
if(directory!=null && directory.trim().length()>0 && file!=null){
File dir = new File(directory);
if(dir.isDirectory() && dir.exists() && dir.canRead()){
fileList = Arrays.asList(dir.listFiles());
}
}
} catch (Exception excep) {
excep.printStackTrace();
}
return fileList;
}
}

Retrieveing path of text files in Directory using Java

I have the directory path being passed as an argument in Java program and the directory has various types of files. I want to retrieve path of text files and then further each text file.
I am new to Java, any recommendation how to go about it?
Even though this is not an optimum solution you can use this as a starting point.
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class DirectoryWalker {
/**
* #param args
*/
private String extPtr = "^.+\\.txt$";
private Pattern ptr;
public DirectoryWalker(){
ptr = Pattern.compile(extPtr);
}
public static void main(String[] args) {
String entryPoint = "c:\\temp";
DirectoryWalker dw = new DirectoryWalker();
List<String> textFiles = dw.extractFiles(entryPoint);
for(String txtFile : textFiles){
System.out.println("File: "+txtFile);
}
}
public List<String> extractFiles(String startDir) {
List<String> textFiles = new ArrayList<String>();
if (startDir == null || startDir.length() == 0) {
throw new RuntimeException("Directory entry can't be null or empty");
}
File f = new File(startDir);
if (!f.isDirectory()) {
throw new RuntimeException("Path " + startDir + " is invalid");
}
File[] files = f.listFiles();
for (File tmpFile : files) {
if (tmpFile.isDirectory()) {
textFiles.addAll(extractFiles(tmpFile.getAbsolutePath()));
} else {
String path = tmpFile.getAbsolutePath();
Matcher matcher = ptr.matcher(path);
if(matcher.find()){
textFiles.add(path);
}
}
}
return textFiles;
}
}
Create a File object representing the directory, then use one of the list() or listFiles() methods to obtain the children. You can pass a filter to these to control what is returned.
For example, the listFiles() method below will return an array of files in the directory accepted by a filter.
public File[] listFiles(FileFilter filter)
Start by reading the File API. You can create a File from a String and even determine if it exists() or isDirectory(). As well as listing the children in that directory.

Categories