我正在编写一个程序,使用文件I / O遍历用户给出的目录,然后将这些目录添加到通用链接列表中。 我写的程序在Ubuntu上完美工作,但在Windows上使用时却不起作用。 这是一个相当长的程序,但这是我认为有问题的部分:
private Node<Item> currentNode = new Node<Item>(); public void traverse(File fileObject) { File allFiles[] = fileObject.listFiles(); for(File aFile: allFiles){ System.out.println(aFile.getName()); /* debugging */ recursiveTraversal(aFile); /* Line 34 */ } } public void recursiveTraversal(File fileObject){ Node<Item> newNode = new Node<Item>(); currentNode.addChild(newNode); currentNode = newNode; if (fileObject.isDirectory()){ newNode.setData(new Item()); File allFiles[] = fileObject.listFiles(); for(File aFile : allFiles){ /* This is line 48 */ recursiveTraversal(aFile); } }else if (fileObject.isFile()){ newNode.setData(new Item()); } currentNode = newNode.getParent(); }
当我在Linux上使用它时,我可以给它类似/home/matt/Documents
和它的工作原理,但是当我在使用G:\\Users\\Matt\\Documents
Windows上进行尝试时,它将出错。 我input的打印语句实际上打印出文件夹中的文件,但程序的其余部分却弄乱了一些东西:
java.lang.NullPointerException at FileTraverse.recursiveTraversal(FileTraverse.java:48) at FileTraverse.traverse(FileTraverse.java:34) at DirectoryMain$ClickAction.actionPerformed(DirectoryMain.java:103) ...
之后的很多错误都与Swing GUI有关,这个程序正在运行,但我不认为这与任何事情有关。
编辑:添加在跟踪对应的行号。
我的猜测是,你正在打一个目录,由于某些原因,Windows不允许你查看。 在这种情况下,listFiles()很可能返回null。
从File.listFile()的Javadoc(加入强调):
返回:一个抽象路径名数组,表示由此抽象路径名表示的目录中的文件和目录。 如果目录是空的,数组将是空的。 如果此抽象路径名不表示目录或发生I / O错误,则返回null。
您将需要应对来自listFiles()
空返回值,不幸的是使用java.io.File
API无法找到发生了什么错误。
如果您正在使用Java 7,则可以使用DirectoryStream类:
private void recursiveTraversal(Path path) throws IOException { try (DirectoryStream<Path> stream = Files.newDirectoryStream(path)) { for (Path entry : stream) { //Do something with entry doSomething(entry); if (Files.isDirectory(entry)) recursiveTraversal(entry); } } }
不同的是, newDirectoryStream()
可以抛出一个IOException
(或一个像AccessDeniedException
这样的子类,它提供了关于调用失败原因的信息。
如果你在第48行得到一个NullPointerException
,它必须意味着你获得的allFiles
数组是null
。 根据该方法的JavaDoc ,只有在您调用它的文件不是目录或发生某些IO错误时才会发生这种情况。 这有点奇怪,因为你检查if是否是一个目录。 也许在操作系统级别有一些访问问题,关于权限。
您可能需要考虑使用FileFilter
或java.nio.file
包中的东西。 我相信后者使遍历目录更容易。
traverse()
和recursiveTraversal()
traverse()
之间的区别对我来说有点奇怪, 你什么时候使用traverse()
? 它发挥了什么作用recursiveTraversal()
还没有做? 当然, traverse()
假定它正在处理一个目录,但是recursiveTraversal()
已经很好的处理了目录。
在recursiveTraversal()
有Item
的所有操作,但由于在这里什么都不做 ,所以很难发现这个工具。 🙂
public void traverse(File fileObject) { File allFiles[] = fileObject.listFiles(); for(File aFile: allFiles){ System.out.println(aFile.getName()); /* debugging */ recursiveTraversal(aFile); } } public void recursiveTraversal(File fileObject){ Node<Item> newNode = new Node<Item>(); currentNode.addChild(newNode); currentNode = newNode; if (fileObject.isDirectory()){ newNode.setData(new Item()); File allFiles[] = fileObject.listFiles(); for(File aFile : allFiles){ recursiveTraversal(aFile); } }else if (fileObject.isFile()){ newNode.setData(new Item()); } currentNode = newNode.getParent(); }
我可能会移动newNode.setData(new Item());
在isDirectory()
检查之上 ,使得清除newNode
有一个新的Item
添加到它,不管当前的fileObject
是文件还是目录:
public void recursiveTraversal(File fileObject){ Node<Item> newNode = new Node<Item>(); currentNode.addChild(newNode); currentNode = newNode; newNode.setData(new Item()); if (fileObject.isDirectory()){ File allFiles[] = fileObject.listFiles(); for(File aFile : allFiles){ recursiveTraversal(aFile); } }else if (fileObject.isFile()){ /* must do _something_ with files */ } currentNode = newNode.getParent(); }
我在Windows上尝试类似的东西,程序尝试遍历安全权限限制访问的目录时,程序将崩溃并返回nullPointerException。
除非你需要程序添加安全/隐藏/系统文件夹,只需使用try catch子句来处理错误。
public static void dive(File file, int level){ try{ for(File x : file.listFiles()) if(x.isDirectory() && !x.isHidden()) dive(x); }catch(NullPointerException e){ // Do nothing.. } }
这应该遍历所有的用户目录