Based on an answer to: List all files from a directory recursively with Java
I have written a little Filemover which will recursively move every file from a directory and place them in the top level of another directory. But for some reason, the code doesn't move all the files. I switched to using Files.move() but while definitely worth while the code is still not walking the directory tree properly. Now I am getting a java.nio.file.NoSuchFileException while trying to move the files.
The stack trace says that its an unknown source, yet when I look to see if the file is there it is. I have isolated the problem to Files.move() but I can't seems to fix it. I have tried both getPath() and getAbsolutePath(). What's even weirder I use a similar method in my sorting routine and it works fine. The only difference is that my source directory has no subdirectories.
I have solved the partial tree walk. It was caused because my ImageFilter only had lower case extensions and the filter needed to be case sensitive. So I fixed it here.
Okay, I switched my little Filemover back to file.renameTo() and it works properly now. It's just a testing tool for randomly moving files into a drop directory for my image sorter so it's not worth figuring out why I was getting no such file exceptions. I was just modifying it to work recursively so it could be used to reverse a sort if someone used the wrong sorting routine on a bunch of images.
Thanks for all your help :)
I have 3 classes
import java.io.File;
import java.util.Collection;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.DirectoryFileFilter;
import ca.fotonow.p3software.ImageFileFilter;
public class PSFileUtils {
public static Collection<File> listfiles(String directory) {
// TODO Auto-generated method stub
File dir= new File (directory);
dir.mkdirs(); //create directory if it doesn't exist.
Collection<File> files= FileUtils.listFiles(dir,new ImageFileFilter(),DirectoryFileFilter.DIRECTORY);
return files;
}
}
Filter Class
import java.io.File;
import java.io.FileFilter;
import org.apache.commons.io.filefilter.IOFileFilter;
public class ImageFileFilter implements IOFileFilter {
private final String filetypes[]= new String[] {"jpeg", "JPEG","jpg","JPG","tif","TIF","tiff","TIFF","raw","RAW"};
#Override
public boolean accept(File file) {
for (String ext: filetypes) {
if (file.getName().toLowerCase().endsWith(ext)) return true;
}
return false;
}
#Override
public boolean accept(File arg0, String arg1) {
// TODO Auto-generated method stub
return false;
}
}
The main class
import java.io.File;
import java.util.Collection;
import java.util.Date;
import java.util.Random;
import java.nio.file.Files;
import static java.nio.file.StandardCopyOption.*;
public class FileMover {
/**
* #param args
*/
public static void main(String[] args) {
//Move random number of files from one directory args[0] to another directory args[1]
//directories can be relative
//Repeats randomly until files are gone
String dir1=args[0];
String dir2=args[1];
Collection<File> files=PSFileUtils.listfiles(dir1);
for (File file: files) {
File newfile=new File(dir2+"/"+file.getName());
try {
Files.move(file.toPath(),newfile.toPath(), REPLACE_EXISTING);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println((new Date()).getTime()+ " "+ newfile.getName());
Random generator =new Random(new Date().getTime());
try {
Thread.sleep(generator.nextInt(5000));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Any idea of what I have wrong?
Renaming the file might not move the file, according to the javadocs:
Many aspects of the behavior of this method are inherently platform-dependent: The rename operation might not be able to move a file from one filesystem to another, it might not be atomic, and it might not succeed if a file with the destination abstract pathname already exists. The return value should always be checked to make sure that the rename operation was successful.
Try java.nio.file.Files.move() instead.
Though #nitegazer is correct I should have used Files.move() instead of File.renameTo(). It turns out that that was not the reason for the partial file tree walk. The file tree walk was failing because the filter is case sensitive and I only provided lower case versions of the file extensions.
I did have a problem with a little script that I use to randomly fill the input hopper for testing the sorter but that just a test script and works fine with File.renameTo().
Related
I am making a stock market simulator app in java, and there is an issue in the deleteHistoryFiles() method. It says that array is null. However, I have no idea what array this error is talking about.
Here's the code (I've deleted some methods to save space):
package stock.market.simulator;
import java.util.Random;
import java.text.DecimalFormat;
import java.util.Timer;
import java.util.TimerTask;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class StockMarketSimulator {
// Path to where the files are stored for rate history
// USE WHEN RUNNING PROJECT IN NETBEANS
//public static final String HISTORYFILEPATH = "src/stock/market/simulator/history/";
// Path to history files to be used when executing program through jar file
public static final String HISTORYFILEPATH = "history/";
public static void main(String[] args) throws IOException {
accountProfile accProfile = accountCreation();
stockProfile[][] stockProfile = createAllStocks();
deleteHistoryFiles(new File(HISTORYFILEPATH));
createHistoryFiles(stockProfile);
mainWindow window = new mainWindow(accProfile, stockProfile);
recalculationLoop(stockProfile, window);
}
// Procedure to create the history files
public static void createHistoryFiles(stockProfile[][] stocks) throws IOException {
String fileName;
FileWriter fileWriter;
for (stockProfile[] stockArray : stocks) {
for (stockProfile stock : stockArray) {
fileName = stock.getProfileName() + ".csv";
fileWriter = new FileWriter(HISTORYFILEPATH + fileName);
}
}
}
// Procedure to delete the history files
public static void deleteHistoryFiles(File directory) {
for (File file : directory.listFiles()) {
if (!file.isDirectory()) {
file.delete();
}
}
}
}
I got the same exception in exactly the same scenario. I tried to create an array of files by calling File.listFiles() and then iterating the array.
Got exception Cannot read the array length because "<local3>" is null.
Problem is that the path to the directory simply does not exist (my code was copied from another machine with a different folder structure).
I don't understand where is <local1> (sometimes it is <local3>) comes from and what does it mean?
It should be just like this: Cannot read the array length because the array is null.
Edit (answering comment) The sole interesting question in this question is what is a <local1>
My answer answers this question: <local1> is just an array created by File.listFiles() method. And an array is null because of the wrong path.
I'm attempting to use some other jar files that have functions I'd like to access. The are public, and I have sample code I built my test app from. It appears to be signing related (ie they are signed, mine was self-signed).
When I attempt to load the applet in a webpage I am asked if I wish to block or unblock. If I tell it to unblock I get the following error:
class "Scanx" does not match the trust level of other classes in the same package.
I've read at least a dozen different articles but they either don't apply or exceed my ability to understand at my current level of Java coding knowledge.
I'd really appreciate any thoughts on how to get past this so I can test & complete my java applet? Code is below:
<html><body>
<applet id=scanx name=scanx code="Scanx.class" height="600" width="600" archive="./Scanx.jar,./ij.jar,./plugin.jar,./twain.jar"></applet>
<script type="text/javascript">
function scanit()
{
document.scanx.getScan();
}
</script>
<input type=button onclick="scanit();">
</body></html>
Here's my java code, which I compile into a jar using "jar cvf Scanx.jar Scanx.java" ...
package uk.co.mmscomputing.device.twain.applet;
import javax.swing.JApplet;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.awt.image.RasterFormatException;
import javax.imageio.ImageIO;
import netscape.javascript.*;
import java.io.File;
import uk.co.mmscomputing.device.scanner.Scanner;
import uk.co.mmscomputing.device.scanner.ScannerListener;
import uk.co.mmscomputing.device.scanner.ScannerDevice;
import uk.co.mmscomputing.device.scanner.ScannerIOException;
import uk.co.mmscomputing.device.scanner.ScannerIOMetadata;
public class xScanx extends JApplet implements ActionListener, ScannerListener{
int index = 0;
String filename;
Scanner scanner;
public Scanx(){
}
public Scanx(String title, String[] argv){
init();
}
public void init(){
scanner=Scanner.getDevice();
scanner.addListener(this);
// scanner.select("TWAIN_32 Sample Source");
}
public void getScan()
{
try{
scanner.acquire();
}catch(ScannerIOException se){
se.printStackTrace();
}
}
public void actionPerformed(ActionEvent evt){
/*
try{
if(evt.getSource()==acquireButton){
scanner.acquire();
}else if(evt.getSource()==selectButton){
scanner.select();
}else if(evt.getSource()==cancelButton){
scanner.setCancel(true);
}
}catch(ScannerIOException se){
se.printStackTrace();
}
*/
}
public void update(ScannerIOMetadata.Type type, ScannerIOMetadata metadata){
if(type.equals(ScannerIOMetadata.ACQUIRED)){
BufferedImage image=metadata.getImage();
System.out.println("Have an image now!");
try{
ImageIO.write(image, "jpg", new File(filename+index+".jpg"));
index++;
// new uk.co.mmscomputing.concurrent.Semaphore(0,true).tryAcquire(2000,null);
}catch(Exception e){
e.printStackTrace();
}
}else if(type.equals(ScannerIOMetadata.NEGOTIATE)){
ScannerDevice device=metadata.getDevice();
}else if(type.equals(ScannerIOMetadata.STATECHANGE)){
System.err.println(metadata.getStateStr());
}else if(type.equals(ScannerIOMetadata.EXCEPTION)){
metadata.getException().printStackTrace();
}
}
public static void main(String[] argv){
try{
new Scanx("Twain Applet Example [2007-11-02]", argv);
}catch(Exception e){
e.printStackTrace();
}
}
}
The reported error message looks similar to the error when having two classes in the same package with different signatures. This has been illegal since back in the nineties. One of the differences is that the fully qualifies class name should be reported (it is about packages). It may be the case that the class is in fact in a default package, never a good idea. That would typically because the package name was added later, but an old class file that has hung around is being used.
The applet tag looks a bit wrong. code="Scanx.class" should have the package name in, which further suggests a stale class file. plugin.jar appears to be part of the PlugIN, so shouldn't be included when run in the plugin (but it will be necessary when compiling the code).
Then you say 'I compile into a jar using "jar cvf Scanx.jar Scanx.java"'. A little bit confusing. You should compile the .java file into a .class with javac. Then use jar to create the jar. The files you want should be .class not .java and should include the package name. If you look at the jar as a zip, it should have classes inside with directory paths matching package names (IIRC, jar tf Scanx.jar should list the files).
I have a Sons class which load and play sounds. And an adhd class which contain the main and uses this Sons class.
All my classes are in the package "adhd" and my sounds in the jar, are like this : 1.wav is in SoundN which is in the jar. (ADHD.jar/SoundN/1.wav).
When I run the code in Eclipse it works, but when I run the jar it doesn't. It is important for me to keep the sounds "loading" because I need my program to read my sounds quickly, as I am using timers. What do you suggest me to do?
Here is the code of my class Sons which load sounds in instances of singletons.
Sons
package adhd;
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
import java.applet.Applet;
import java.applet.AudioClip;
import java.net.URL;
public class Sons {
private static String PATH=null;
private static Sons instance;
private final Map<String, Clip> sons;
private boolean desactive;
Sons(String path) {
PATH = path;
sons = new HashMap<String, Clip>();
}
public void load(String nom) throws UnsupportedAudioFileException, IOException, LineUnavailableException {
Clip clip = AudioSystem.getClip();
clip.open(AudioSystem.getAudioInputStream(getClass().getResourceAsStream(PATH + nom)));
sons.put(nom, clip);
}
public void play(String son) {
if(!desactive) try {
Clip c = getSon(son);
c.setFramePosition(0);
c.start();
} catch(Exception e) {
System.err.println("Impossible to play the sound " + sound);
desactive = true;
}
}
}
Here is the adhd class which contain the main that uses sounds
Main class : adhd
public static void main(String[] args) {
Sons sonN= new Sons("/SoundN/");
try {
sonN.load("1.wav");
} catch (UnsupportedAudioFileException | IOException
| LineUnavailableException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
sonN.play("1.wav");
}
Here is also a picture of the tree
Now, thanks to the exception message, we know what the problem actually is. The problem is not that the sounds can't be loaded or aren't found in the jar. The problem is that, as the javadoc says:
These parsers must be able to mark the stream, read enough data to determine whether they support the stream, and, if not, reset the stream's read pointer to its original position. If the input stream does not support these operation, this method may fail with an IOException.
And the stream returned by Class.getResourceAsStream(), when the resource is loaded from a jar, doesn't support these operations. So what you could do is to read everything from the input stream into a byte array in memory, create a ByteArrayInputStream from this byte array, and pass that stream to AudioSystem.getAudioInputStream().
If loading everything in memory is not an option because the sound is really long (but then I guess you wouldn't put it in the jar), then you could write it to a temporary file, and then pass a FileInputStream to AudioSystem.getAudioInputStream().
I am currently working on a method that will create files and directories. Bellow is the use case & problem explained.
1) When a user specifies a path e.g "/parent/sub folder/file.txt", the system should be able to create the directory along with the file.txt. (This one works)
2) When a user specifies a path e.g "/parent/sub-folder/" or "/parent/sub-folder", the system should be able to create all directories. (Does not work), Instead of it creating the "/sub-folder/" or /sub-folder" as a folder, it will create a file named "sub-folder".
Here is the code I have
Path path = Paths.get(rootDir+"test/hello/");
try {
Files.createDirectories(path.getParent());
if (!Files.isDirectory(path)) {
Files.createFile(path);
} else {
Files.createDirectory(path);
}
} catch (IOException e) {
System.out.println(e.getMessage());
}
You need to use createDirectories(Path) instead of createDirectory(path). As explained in the tutorial:
To create a directory several levels deep when one or more of the
parent directories might not yet exist, you can use the convenience
method, createDirectories(Path, FileAttribute). As with the
createDirectory(Path, FileAttribute) method, you can specify an
optional set of initial file attributes. The following code snippet
uses default attributes:
Files.createDirectories(Paths.get("foo/bar/test"));
The directories
are created, as needed, from the top down. In the foo/bar/test
example, if the foo directory does not exist, it is created. Next, the
bar directory is created, if needed, and, finally, the test directory
is created.
It is possible for this method to fail after creating some, but not
all, of the parent directories.
Not sure of which File API you are using. But find below the simplest code to create file along with folders using java.io package.
import java.io.File;
import java.io.IOException;
public class FileTest {
public static void main(String[] args) {
FileTest fileTest = new FileTest();
fileTest.createFile("C:"+File.separator+"folder"+File.separator+"file.txt");
}
public void createFile(String rootDir) {
String filePath = rootDir;
try {
if(rootDir.contains(File.separator)){
filePath = rootDir.substring(0, rootDir.lastIndexOf(File.separator));
}
File file = new File(filePath);
if(!file.exists()) {
System.out.println(file.mkdirs());
file = new File(rootDir);
System.out.println(file.createNewFile());
}
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
I have created a Mac Java Swing application, and i have set a file extension(*.pkkt) for it in the "Info.plist" file, so when double clicking that file it opens my application.
When i do that the program runs fine. Now i need to load the (*.pkkt) project in the program, but the file path is not passed as an argument to the main(...) method in Mac as happens in Windows Operating System.
After some search i found an Apple handling jar "MRJToolkitStubs" that has the MRJOpenDocumentHandler interface to handle such clicked files. I have tried using it to load that file by implementing that Interface in the main program class, but it is not working. The implemented method is never called at the program start-up.
How does this Interface run ?
------------------------------------------------- Edit: Add a Code Sample
Here is the code i am using :
public static void main( final String[] args ) {
.
.
.
MacOpenHandler macOpenHandler = new MacOpenHandler();
String projectFilePath = macOpenHandler.getProjectFilePath(); // Always Empty !!
}
class MacOpenHandler implements MRJOpenDocumentHandler {
private String projectFilePath = "";
public MacOpenHandler () {
com.apple.mrj.MRJApplicationUtils.registerOpenDocumentHandler(this) ;
}
#Override
public void handleOpenFile( File projectFile ) {
try {
if( projectFile != null ) {
projectFilePath = projectFile.getCanonicalPath();
System.out.println( projectFilePath ); // Prints the path fine.
}
} catch (IOException e) {}
}
public String getProjectFilePath() {
return projectFilePath;
}
}
As mentioned in the comment above "getProjectFilePath()" is always Empty !
On Java 9, use Desktop.setOpenFileHandler()
The proprietary com.apple.eawt packages have been removed from recent versions of Java and has been incorporated into various methods in the Desktop class. For your specific example:
import java.awt.desktop.OpenFilesHandler;
import java.awt.desktop.OpenFilesEvent;
import java.io.File;
import java.util.List;
public class MyOpenFileHandler implements OpenFilesHandler {
#Override
public void openFiles​(OpenFilesEvent e) {
for (File file: e.getFiles​()) {
// Do whatever
}
}
}
Then elsewhere, add this:
Desktop.getDesktop().setOpenFileHandler(new MyOpenFileHandler());
The OpenFilesEvent class also has a getSearchTerm() method. Say that a person used Spotlight on macOS to search for the word "StackOverflow", then decided to open up a document. With this method, can you determine that "StackOverflow" was the word they searched for, and choose to do something with that (perhaps highlight the first occurrence of the word).
You're going to want to use the Apple Java Extensions.
They should be included in any JDK that runs on Mac OS X, but the documentation is kind of hard to get. See this answer for more details.
Specifically, you'll want to make an OpenFilesHandeler.
This code snippet should work:
import com.apple.eawt.event.OpenFilesHandeler;
import com.apple.eawt.event.AppEvent;
import java.io.File;
import java.util.List;
class MacOpenHandler implements OpenFilesHandeler {
#Override
public void openFiles(AppEvent.OpenFilesEvent e) {
List<File> files = e.getFiles();
// do something
}
}
And somewhere:
import com.apple.eawt.Application;
...
MacOpenHandeler myOpenHandeler = new MacOpenHandeler();
Application.getApplication().setOpenFileHandler(myOpenHandeler);