How to move files one by one using java - java

i know how to send all files from one directory to another in one time.
but how can i want send files (.txt) from one directory to another one by one with a delay of 60s.
import java.io.File;
public class MoveFilesJavaExample {
public static void main(String[] args) {
try {
File oldFile = new File("C:\\source\\File.txt");
if (oldFile.renameTo(new File("C:\\destination"+ oldFile.getName()))) {
System.out.println("The file was moved successfully to the new folder");
} else {
System.out.println("The File was not moved.");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
I can use the following code but it only do the same job every 5s.
import java.util.Timer;
import java.util.TimerTask;
public class UtilTimerDemo {
public static void main(String[] argv) throws Exception {
int delay = 5000; // delay for 5 sec.
int period = 1000; // repeat every sec.
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
System.out.println("doing");
}
}, delay, period);
}
}
Thank you

Inside your TimerTask, use File#listFiles() (possibly with the FilenameFilter parameter, if that suits your needs) to get a list of files in the source directory.
Iterate through the returned Files looking for the first item that is not a directory (assuming that you want to move only normal files).
Move that file.
Optionally (depending on your requirements) if you got to the end of the array of returned Files and didn't find any non-directories, then stop the TimerTask.

Start a Timer that fires every 60 seconds.
In the constructor of the Timer, use DirectoryStream<Path> to get all the files in a directory. This is done using the static method of Files class in the nio package.
Then, use Files.move() in the Timer to move the files one by one.
Stop the Timer when you have iterated over all the files in the stream.
DirectoryStream can be globbed, thus allowing you to filter the files that you want. You can either write simple extensions or complex RegEx to decide what files are returned in your DirectoryStream.

Related

How To Allow Only One .Jar Instance, And To Let It Use Args From Other Attempted Instances?

I've got a tough question, for which I will first sketch a background to make things more understandable.
Background
I have made an audioplayer in Java which can be launched with command line args, and also without. The application's .jar (made with Netbeans) is wrapped in a .exe file (made with Launch4j) so that you can open for example a mp3 file with the .exe, and then the .jar inside adopts the filepath in it's String[] args.
The problem with this approach (for now) is that if you select multiple mp3 files at once and you open them at the same time, they all get opened in seperate windows of the audioplayer. What I want however, is that all the files get opened in one single instance of the application.
What I then attempted is to let Launch4j allow only one instance of the .jar/.exe in the hopes that all the selected files would be opened in one application, this did unfortinately not work.
What I see as a solution
So I want to be able to select multiple .mp3 files in windows, and that all their filepaths get passed on as a command line arg to one single instance of the application. Or a different approach that has the same result. Does anyone know how to realize this in the actual application?
Many thanks in advance. I will try to keep looking for potential solutions/ideas as well.
--Edits--
The main method is ready to receive multiple files. I have implemented a piece of code that saves all the command line args of the application to a .txt file, and when I allow only one single instance with the Launch4j .exe file, there only appears to be one single argument in the .txt file when I try to open multiple mp3 files.
If I allow the .exe to have multiple instances, then I simply have the .jar application being launched multiple times (one time for each file I try to open).
I used java RMI (Remote Method Invokation) to make a single-instance application.
An RMI attempts to listen on a socket with a user-defined port number.
When starting the jar.
If noone serves that port, then this instance is the RMI server. Establish a GUI Window. Call an open with the main's args.
If there is already a serving application, send by RMI an open with the main's args. Then exit normally, return from main.
Code: Untested as you probably want to arrange things differently.
public interface OpenRMI extends Remote {
void open(String[] args) throws RemoteException;
}
public class SingleInstanceApp implements OpenRMI {
private static final String RMI_ENTRY = "ImJustACowLolAudioPlayer";
public static void main(String[] args) throws RemoteException,
AccessException, NotBoundException {
System.out.println("main " + Arrays.toString(args));
if (System.getSecurityManager() == null) {
System.setSecurityManager(new SecurityManager());
}
Registry registry = LocateRegistry.getRegistry();
OpenRMI openRMI;
try {
System.out.println("bind with new OpenRMI");
SingleInstanceApp app = new SingleInstanceApp();
openRMI = (OpenRMI) UnicastRemoteObject.exportObject(app, 0);
registry.bind(RMI_ENTRY, openRMI);
System.out.println("Player bound");
app.create(); // Server.
} catch (AlreadyBoundException e2) {
System.out.println("lookup as someone else bound before us");
openRMI = (OpenRMI) registry.lookup(RMI_ENTRY); // Client.
}
openRMI.open(args);
}
private void create() {
new Thread(true) { // Daemon thread, or start GUI
#Override
public void run() {
System.out.println("create " + this);
for (int i = 0; i < 10; ++i) {
Thread.sleep(1000L);
}
shutdown();
}
}
}
private void shutdown() throws RemoteException,
NotBoundException, AccessException {
System.out.println("close " + this);
Registry registry = LocateRegistry.getRegistry();
registry.unbind(RMI_ENTRY);
}
#Override
public void open(String[] args) throws RemoteException {
System.out.println("open " + this + ": " + Arrays.toString(args));
}
}
I would expect some more decent classes.
I fixed it, after some hours of programming and taking breaks inbetween
package argsbuilder;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
public class ArgsBuilder
{
public static void main(String[] args)
{
checkIfRunning(args);
}
private static void checkIfRunning(String[] args)
{
buildFile(args);
ProcessBuilder pb = new ProcessBuilder("core.exe"); //core.exe is a .exe wrapper with the .jar audioplayer in it
try
{
Process p = pb.start();
}catch (IOException f){System.out.println(f);}
}
private static void buildFile(String[] args)
{
try
{
boolean notdone = true;
int i=0;
File f;
while(notdone)
{
f = new File("arg" + i + ".txt");
if(f.exists())
{
i++;
}
else
{
PrintStream out = new PrintStream(new FileOutputStream(new File("Folder Location" + "arg" + i + ".txt")));
System.setOut(out);
System.out.println(args[0]);
notdone = false;
}
}
}catch(Exception g){System.out.println(g);}
}}
What the above does
The above application checks if there are other argument files, and if there are it will keep generating a new name untill the name is free. It then prints the argument to that file. After it has printed the argument, it launches the audioplayer. In the audioplayer the following happens:
import javafx.embed.swing.JFXPanel;
import java.net.InetAddress;
import java.net.ServerSocket;
public class YourApp {
public static void main(String[] args)
{
try
{
socket = new ServerSocket(PORT,0,InetAddress.getByAddress(new byte[] {127,0,0,1}));
//Everything you need to launch the application in the try
}catch(Exception g){//Nothing in the catch}
}}
What the above does
It tries to claim a serversocket for itself. If there already is one then it does not proceed to launch the application. That way only one instance will be running at a time. (at PORT you just fill in a random integer).
Combining those 2, you can read the textfiles created by the first application and interpret them as arguments in the second application.
So how does it interpret them as arguments?
Well, I already had a timer fixed into the program, and I tell the audioplayer to look for the very first arg file (arg0.txt) in a specified folder. If it finds it it adds it to an arraylist, along with all arg+i.txt files.
It might not be the fastest way, but it surely works well.

SwingWorker with FileVisitor not publishing processed info quickly; GUI hangs

Using SwingWorker with FileVisitor not publishing processed info quickly; GUI hangs. I'd prefer it didn't and would like help with that problem.
Here's a brief outline of how I use SwingWorker with FileVisitor interface to search a Windows directory node for files matching user-specified criteria. :
public class Main
{
public static void main(String args[])
{
EventQueue.invokeLater( new Runnable() {
#Override public void run() {
gui = new GUI();
}});
}
}
//==============================================================
public class GUI extends JFrame
{
public GUI()
{
init();
createAndShowGUI();
}
private void init()
{
dftTableModel = new DefaultTableModel(0 , 4);
tblOutput = new JTable(dftTableModel);
tblOutput.setAutoResizeMode(AUTO_RESIZE_OFF);
scrTblOutput = new JScrollPane(tblOutput);
dftTableModel.setColumnIdentifiers(new Object[]{"Date", "Size", "Filename", "Path"});
EDIT HAD I ONLY INCLUDED THESE TWO LINES, PROBLEM MAY HAVE BEEN SOLVED IMMEDIATELY
tca = new tablecolumnadjuster.TableColumnAdjuster(tblOutput);
tca.setDynamicAdjustment(true);
}
private static void btnSearchActionPerformed(ActionEvent evt)
{
TASK task = new TASK();
task.execute();
}
}
}
//==============================================================
public class TASK extends SwingWorker<Void,String>
{
private class rowRec{
String date;
int size;
String filename;
String pathname;
private rowRec(String d, int s, String f, String p)
{
date = d;
size = s;
filename = f;
pathname = p;
}
}
FV fv;
TASK() { fv = new FV(); }
//-------------- inner class
class FV implements FileVisitor<Path>
{
// When walk begins, internal FileVisitor code makes this routine
// loop until no more files are found OR disposition = TERMINATE.
public FileVisitResult visitFile(Path f, BasicFileAttributes a) throws IOException
{
if(f.getFileName().toString().toLowerCase().matches(fPatt.toLowerCase().trim()))
{
publish(s);
if(++k > parseInt(GUI.txtMaxMatches.getText()))
disposition = TERMINATE;
publish("Stopped at max. records specified");
}
return disposition;
}
}
//----------------
private void report(String s)
{
rowData = new rowRec(date, isize, filename, path);
dftTableModel.addRow(new Object[]{rowData.date, rowData.size, rowData.filename, rowData.pathname});
}
#Override
protected void process(List<String> chunks)
{
chunks.stream().
forEach
(
(chunk) ->
{
report(chunk);
}
);
kc += chunks.size();
System.out.println(kc); // *********************************
}
#Override
public Void doInBackground() throws Exception
{
disposition = FileVisitResult.CONTINUE;
Files.walkFileTree(GUI.p ,fv);
}
}
GUI starts a new instance of SwingWorker, whose job is to display (in a JTable) file info found by the instance of TASK that it starts. TASK instantiates FileVisitor, and walkFileTree begins. Every matching file found in the visitFile method is published for SwingWorker to process.
It works great most of the time, but if there is a ton of matching files, the GUI becomes unresponsive for several seconds; meanwhile, plenty of reading and displaying has occurred, and the UI is updated every few thousand file reads.
Despite using SwingWorker to fill the JTable in the background, apparently (I'm guessing) too much matching files info comes too fast to keep up.
Here's why I say that:
Even though visitFile has a counter which signals to TERMINATE, process apparently is far behind in adding records to the JTable. The println inside it shows that, as time passes, the number of chunks passed varies considerably, depending on rate of FileVisitor finding matches:
41
81
138
250
604
1146
...
1417
1497
1590
1670
1672
1676
1680
1682
1692
1730
1788
1794
1797
1801
1807
1820
1826
1829
1847
1933
2168
10001
After visitFile terminated, process had to send (10001-2168), or 7833 records to the JTable, and it took a long time, and the GUI was unresponsive much of the time. In fact, if the max. matches is (the ridiculous) 10,000, the program hangs for many MINUTES, but 10,000 records are in the JTable.
I don't know what to do about the unresponsiveness. I'd like to be able to hit the STOP button and have the program stop. Or be able to X (close) the window. No way.
Am I not using SwingWorker correctly? I can't make the tree walk be based on SwingWorker since there's no loop that I have available to me (it's internal).
P.S. While apparently hung, javaw is taking a solid 25% of CPU time and incrementing its memory allocation by about 16K per second, as process plods along, until it finally publishes the last chunk.
EDIT
I may have found help here.
But, gee, close??
I've highlighted my questions.
I don't know the solution to your problem, but I do know that this should not be done within the SwingWorker or its inner classes:
GUI.txtMaxMatches.getText())
You should get this information on the EDT and pass it into your SwingWorker via its constructor.
The responsiveness problem is solved in ONE LINE OF CODE.
// tca.setDynamicAdjustment(true);
Refer to edit in original question.

Single program instance

I need to make a program, which can be executed in single instance. I tried to create a temporary file and delete it before exit program.
public static boolean isLocked() {
File f = new File("lock.txt");
return f.exists();
}
public static void lock() {
String fname = "lock.txt";
File f = new File(fname);
try {
f.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void unlock() {
File f = new File("lock.txt");
f.delete();
}
In frame
private void initialize() {
lock();
}
private void setFrameHandler() {
frame.addWindowListener(new java.awt.event.WindowAdapter() {
#Override
public void windowClosing(java.awt.event.WindowEvent windowEvent) {
unlock();
}
});
}
Problem occurs if program is finished with emergency (e.g. electricity cuts). File does not remove, and running a new instance is impossible.
How to make a reliable single-instance verification?
You could check for another instance of the program at startup using the GetProcesses method as described here
But that only works depending on the scenario you have (might not see all processes of other users)
Another thing you could do is simply checking, if a specific file is locked via File.Open
File.Open ("path.lock", FileMode.OpenOrCreate, FileAccess.ReadWrite);
As long as you keep the resulting FileStream open in your program no other program can open the file in that mode either. This is basically how Unix lock files work too. Of course you have to catch an IOException (hinting you to a locked file).
Disclaimer: I did not try that code out so please check if I gave you the right parameters.
Edit: You could also check out this Code-Project article on how to do it with the win32 API
Another attempt using windows messaging has been done here
A simple approach to this on a single machine is to write a 'PID file', which is literally a file containing the operating system's ID of the process currently running. You create this when you start your "critical" work, and remove it on successful completion.
Since it is unlikely that the process would be started again with the same PID, you can simply check to see if the PID file already exists, and if so, if that process is still running.

Implementing a timeout while listing files in java

I am trying to implement a timeout while listing files in java considering that listing files should be IO bound with some CPU need as well. Following is the code:
FileLister:
package com.timeout;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class FileLister implements Runnable{
private String fileLocation;
private List<String> fileList = new ArrayList<String>();
public FileLister(String fileLocation){
this.fileLocation = fileLocation;
}
public void run(){
this.listFiles(this.fileLocation);
}
public void listFiles(String fileLocation){
File file = new File(fileLocation);
File testFile = null;
String[] fileList = file.list();
if(null!=fileList){
for(String fileName:fileList){
testFile = new File(fileLocation+"/"+fileName);
if(testFile.isDirectory()){
listFiles(fileLocation+"/"+fileName);
}else{
synchronized(this){
this.fileList.add(fileLocation+"/"+fileName);
}
}
}
}
}
public List<String> getFileList() {
return fileList;
}
}
Timer:
package com.timeout;
public class Timer implements Runnable{
private long timeout;
public Timer(long timeout){
this.timeout = timeout;
}
public void run(){
long expectedEndTime = System.currentTimeMillis() + this.timeout;
System.out.println("expectedEndTime---"+expectedEndTime);
while(System.currentTimeMillis()<expectedEndTime){
}
System.out.println("endTime---"+System.currentTimeMillis());
System.exit(0);
}
}
Calling class:
package com.timeout;
import java.io.IOException;
public class Timeout {
public static void main(String[] args)throws IOException{
FileLister fl = new FileLister("C:/");
Timer tm = new Timer(10000);
Thread flt = new Thread(fl);
Thread tmt = new Thread(tm);
flt.start();
try{
Thread.sleep(1000);
}catch(InterruptedException ie){
System.exit(0);
}
tmt.start();
System.out.println("Files after 11 second--");
for(String fileName:fl.getFileList()){
System.out.println(fileName);
}
}
}
I am putting the timeout as 11 seconds(10+1).
This code is giving me a concurrent modification exception. Why should that occur considering only one thread accessing the fileList variable.
Considering that listing file is IO Bound will timer work concurrently.
I am not considering TimerTask/Executor as of now.
This does not really make sense if you stick to the old File API, since when you .listFiles(), the whole directory entries are swallowed into the array that is returned. That you iterate over it afterwards doesn't make the directory entry loading "lazy".
Where is does make sense is if you use the new java.nio.file API (Java 7+) -- and you should use that and drop File --, since Files.newDirectoryStream() does lazy load directory entries. (*)
This returns a DirectoryStream which is basically a lazy Iterable over the directory entries, except that it also implements Closeable. And therefore you can interrupt this, like in:
try (
final DirectoryStream<Path> entries = Files.newDirectoryStream(...);
) {
for (final Path entry: entries) {
if (Thread.currentThread().isInterrupted())
break;
// proceed with "entry"
}
}
One more reason to use that instead of .listFiles(): if the operation to get a DirectoryStream fails, you don't get null (!!) but an appropriate exception instead: AccessDeniedException, NotDirectoryException, NoSuchFileException, FileSystemLoopException (for filesystems with symlink support), etc etc.
Again: ditch File.
(*): at least for operating systems which support it (Linux has getdents() for instance) or, more generally, for all FileSystem implementations which support it
There are 3 threads in your code, file list thread, time out thread and main thread. The while loop executing in time out thread can not block code executing after tmt.start() line. So the fileList ArrayList(not thread safe) is accessed by main thread and file list thread simultaneously, this is why concurrent modification exception caused.

Program displays filenames in a JTextArea as it walks the directory tree but I don't know how to stop it via a keypress

There are two windows: a GUI for user input and Output window for list of filenames found. Execution must be user-stoppable via a keypress and must leave both windows open because the program processes subdirectories, so it can run a long time, possibly stepping thru 100_000 files, either producing tons of output or none at all, depending on how user's filename pattern matches files encountered in the selected starting node.
Here's my question:
How do I look for a keypress (e.g., ESC or CTRL-C) to allow user to terminate? (Clicking red X isn't an option since that closes windows; user needs to see what's been found before termination. Doing so does not close either window anyway since all buttons are disabled once tree walk begins.)
I've tried putting keyListeners in several places, but once the "Start" button is clicked, all the swing components are disabled.
This seems like such a common situation that I'm surprised I can't find any textbook, thread, or Google info that directly answers the question. So I'm afraid it's not gonna be at all easy. That would be no surprise. I may have found a clue here but I can't get it to compile and the link contained there doesn't lead to that code snippet.
The search begins when the Search button is clicked:
private void jbSearchActionPerformed(ActionEvent evt) {
SearchyGUI.doIt();
}
The doIt() method walks the directory tree by an extension of SimplefileVisitor:
public class OverriddenFileVisitor extends SimpleFileVisitor<Path> {
...
}
public static void doIt(){
try {
visitor = new OverriddenFileVisitor();
info.setVisible(true);
Files.walkFileTree(SearchyGUI.p , visitor);
}
catch (Exception e) { }
}
}
Output is written to jTextArea1 via the report() method:
public static void report(String s){
Output.jTextArea1.append(s + "\n");
}
This is done primarily in the visitFile() method of SimpleFileVisitor:
public FileVisitResult visitFile(Path f, BasicFileAttributes a) throws IOException {
report(foundkt + "--" + f.getFileName().toString());
return FileVisitResult.CONTINUE;
}
Here's the main class:
public class SearchyGUI {
static Output info;
static Path p ;
static FileVisitor visitor ;
static GUI gui
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
gui = new GUI();
gui.setVisible(true);
}
});
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
info = new Output();
}
});
}
The problem is you are hogging the GUI thread, so the GUI thread can't process any events originating from the user.
You need to create a new Thread and do the work in there. Then, to display output from that thread, you can use SwingUtilities.invokeLater or something like that.
The Key Bindings API is probably the best choice for monitoring key strokes.
I would also add a [Cancel] button to the UI, which shared the same action...
public class CancelAction extends AbstractAction {
public CancelAction() {
putValue(NAME, "Cancel");
}
public void actionPerformed(ActionEvent evt) {
// Perform the cancel operation...
}
}
Then some where else in your code...
CancelAction cancelAction = new CancelAction();
JButton cancelButton = new JButton(cancelAction);
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "Cancel");
am.put("Cancel", am);
Now the other problem you're going to have is the fact that you look like you are running a long running task within the context of the Event Dispatching Thread. This is going to prevent your program from being able to update the UI or allow the user to interact with the UI.
If you need to make changes to the UI (ie, show the output of the file processing), you should try a SwingWorker.
The main reason being is that it allows you to execute the long running task in another thread, but provides the mechanism for re-syncing updates back to the EDT, where it is safe to make changes to the UI.
Take a look at Concurrency in Swing for more details.
Regardless of which direction you take, you're going to need to supply a reference to the object that is carrying out the task and provide some kind of "cancel" flag, which the "task" object will need to monitor
The way I had left this program last night was unsatisfactory since Exit resulted in user not being able to see the output so far displayed (it could be useful). So I established window listeners and used the close event to set a boolean aborted to true to prevent further output to the window, but the thread kept running, which led to intermittent problems if another search was started before the thread ended.
Here's how I fixed it.
The FileVisitor interface has 4 methods to implement to walk the tree--two for each file visited, two for each directory. Each returns a FileVisitResult which is normally FileVisitResult.CONTINUE. By changing the return value to FileVisitResult.TERMINATE in the file visitor thread, it terminates appropriately! That is, I set a flag that the thread could check and take appropriate action, which is exactly what #MadProgrammer suggested.
public static FileVisitResult disposition = FileVisitResult.CONTINUE;
...
private static void report(String s){
if (! aborted)
try{
Output.jTextArea1.append(s + "\n");
}
catch (Exception e){
aborted = true ;
disposition = FileVisitResult.TERMINATE;
}
}
...
#Override
public FileVisitResult visitFile(Path f, BasicFileAttributes a) throws IOException {
f1 = new File(f.getParent().toString() + "\\" + f.getFileName().toString());
long filesize = f1.length();
report(f.getFileName().toString() + "\t found in " + f.getParent().toString());
return disposition;
}
I am one happy camper! Thank you BOTH for your ideas and input.
Well, I made it stop. I guess if you wander the woods long enough you'll find a gnome. I read Robin's hint last week and sort of gave up. Then I read some more and more. And then more. But Robin assured me that gnomes DO exist in these here woods!
The code I used was a modification of some I found for a MatLab/Java app. (Why'd I even look at it?? Best apparent Google hint.)
I made the "file visitor" (directory tree walker component) startable as a thread as Robin advised:
public class OverriddenFileVisitor extends SimpleFileVisitor<Path> implements Runnable{
// ................................................................^^^^^^^^^^^^^^^^^^^
In doIt() I made a couple of changes, moving the lines that process the directory to the now-runnable class and started the file visitor as its own thread in doIt():
public static void doIt(){
try {
new OverriddenFileVisitor().startTh();
//^^^^^^^^^^
//(moved) Files.walkFileTree(SearchyGUI.p , visitor);
...
I added the new method in the previous line to OverriddenFileVisitor class: (This is the main part of the MatLab/Java code that made sense to me so I used and modified it.)
public void startTh() {
Thread t = new Thread(this);
t.start();
}
And I inserted the overridden run() method for the class:
public void run() {
try {
Files.walkFileTree(SearchyGUI.p , this); // Used to be in doIt().
}
catch (IOException ex) { }
}
It ran and gave correct results and stopped when I hit Exit button, which "became" enabled after revising the file visitor to run in its own thread, which is what #Robin Green was saying. I almost feel like I know what I've done.
P.S. Note that I already was able to get my output via invokeLater()--last several lines of original question.
It's not finished but it's much more satisfactory.

Categories