Java Thread stopping when hiding to SystemTray - java

For my parents I am writing a simple program to copy files from their digital photocamera to their 'My Documents' folder. They always need my help (they are not so technically advanced) to get their pictures off their camera so I decided to help them out. I called it The Copying Machine. Since I couldn't find a suitable USB-Listener in Java, I wrote one myself:
private void sync()
{
// All devices in an ArrayList
File[] roots = File.listRoots();
ArrayList<File> newList = new ArrayList<File>();
for(File f : roots)
{
newList.add(f);
}
// Delete unavailable devices
ArrayList<File> removeThese = new ArrayList<File>();
for(File f : devices)
{
if(!newList.contains(f))
{
removeThese.add(f);
}
}
devices.removeAll(removeThese);
// Add unknown devices
for(File f : newList)
{
if(!devices.contains(f) && f.canRead() && f.canWrite())
{
alarm(f); // Called when new device inserted
devices.add(f);
}
}
}
This method is called every 1000ms in a seperate Thread and I guess that will do. Admitted, this is a dirty method but it works. I tested this function often and I always had the result I wanted. When I continued building my programm, I found that the thread would stop detecting new devices when I hide my programm to the SystemTray. When I open it again, the detection thread still won't work. Could anyone tell me what causes this and how this is to be solved?

Upon saving the data inserted by the user, I stopped detection of new devices. This was foolish of me so I thank you for making me aware of this.
public boolean saveSettings()
{
File f = new File(fsv.getHomeDirectory() + File.separator + "settings.cms");
ObjectOutputStream objOut;
try
{
// Here was my problem.
detector.stopDetection();
if(gui.saveSettings())
{
// Settings-file wegschrijven
objOut = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(f)));
objOut.writeObject(settings);
objOut.flush();
objOut.close();
return true;
}
else
{
return false;
}
}
catch (IOException e)
{
handleExceptions(e);
return false;
}
}

Related

I can't delete a file because it seems 'open'

I'm coding something with an audio part with WAV Files and after 2 days of searching for a bug, I really don't know where the problem is. I guess my thread doesn't stop and that prevents me from deleting a file, but when I'm debugging everything goes well and I've no exceptions or errors.
Here is my interface:
Picture of my interface
So when I want to delete a file by clicking on delete button that launches 'DeleteTrack' method and it works, but when I listen to it first thanks to listen button that launches 'PlaySound' method, I can't delete it, it's like if nothing happen.
Also, when I use 'PlaySound' and then I try to delete my file from windows I have this:
Windows error
Thank you for reading and I'll be very grateful if you could help me and sorry if my English isn't perfect.
GatherFiles method just return my list of waves I've verified it's not null
MajListAudio method refresh my list if I add or delete a song
public void DeleteTrack() {
String song_name = audioList.getSelectedValue();
File[] listeOfFiles = GatherFiles(null);
// Loop to find the file to delete and then delete it.
for(int i=0;i<listeOfFiles.length;i++){
if(song_name.equals(listeOfFiles[i].getName())){
listeOfFiles[i].delete();
}
}
// Refresh the list
MajListAudio();
}
}
So here is the function when I guess there is a problem.
public void PlaySound(File sound){
thread = new Thread(){
#Override public void run(){
try {
// Initialize a clip with our sound file
AudioInputStream audioStream = AudioSystem.getAudioInputStream(sound);
Clip clip = AudioSystem.getClip();
clip.open(audioStream);
// Variable that will updated to fix the percentage of the progressBar
int progressContains =0;
// Size in Seconds of our music
int sizeAudio = (int) (clip.getMicrosecondLength()/1000000);
clip.start();
do{
// indice allow us to know how much the progress bar has to grow every second. We divide with 100 because it's the maximum
//of the bar
int indice = 100/sizeAudio;
// Refresh the value of the bar and prepare her next value
progressBar.setValue(progressContains);
progressContains+= indice;
// The main thread is sleeping for 1s
Thread.sleep(1000);
}while(clip.isActive());
//Reset the bar after a play
clip.stop();
clip.close();
audioStream.close();
progressBar.setValue(0);
} catch (UnsupportedAudioFileException ex) {
ex.printStackTrace();
} catch (LineUnavailableException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
};
thread.start();
}
Others functions
public File[] GatherFiles(DefaultListModel myModel){
// If you want to get the list without implementing the model
if(myModel == null){
File[] both = Concatenate(getListOfFiles("\\cryptedAudio"), getListOfFiles("\\audio"));
return both;
// Same with a model
}else{
audioList.setModel(myModel);
File[] both = Concatenate(getListOfFiles("\\cryptedAudio"), getListOfFiles("\\audio"));
return both;
}
}
public File[] getListOfFiles(String endPath){
String folderPath = new File(".").getAbsolutePath();
folderPath= folderPath.substring(0, folderPath.length()-1);
File folder = new File(folderPath+endPath);
File[] listeOfFiles = folder.listFiles();
return listeOfFiles;
}
/*
*Return a new Array that contains borh arrays in parameters
*/
public <T> T[] Concatenate (T[] a, T[] b) {
int aLen = a.length;
int bLen = b.length;
#SuppressWarnings("unchecked")
T[] c = (T[]) Array.newInstance(a.getClass().getComponentType(), aLen+bLen);
System.arraycopy(a, 0, c, 0, aLen);
System.arraycopy(b, 0, c, aLen, bLen);
return c;
}
I really suspect your threading is an issue. You wait one second after the sound finishes, at the very least. So maybe your delete happens too soon. One way around this, is to read everything from the file, and then make the sound. That way the file should always be closed.
byte[] bytes = Files.readAllBytes(sound.toPath());
AudioInputStream audioStream = AudioSystem.getAudioInputStream(
new ByteArrayInputStream(bytes)
);
Clip clip = AudioSystem.getClip();
clip.open(audioStream);
Since your problem appears to be your file not getting released to the system, we use File.readAllbytes which reads the whole file, and release it back to the OS before you even play a sound.
The concept behind your original setup should work, but it appears that your loop does not finish before you try and delete the file. It could also be that you start more than one thread to access the file.
Have you tried something like
AudioInputStream audioStream = AudioSystem.getAudioInputStream(sound);
Clip clip = AudioSystem.getClip();
clip.open(audioStream);
// play the audio...
clip.close();
audioStream.close();
This is just making sure that the AudioInputStream is getting closed properly since I'm not sure that clip.close() is closing it (though one would think it should...)
This method API AudioSystem.getAudioInputStream(sound) returns an AudioInputStream that you should close.
So better if you first assign the returned value to a local variable:
AudioInputStream inputAudioStream = AudioSystem.getAudioInputStream(sound);
And then you can open it using the clip instance:
Clip clip = AudioSystem.getClip();
clip.open(inputAudioStream);
Finally don't forget to close the inputAudioStream variable:
clip.close();
inputAudioStream.close();
I strongly suggest to use the try-with-resources Statement
try(AudioInputStream inputAudioStream = AudioSystem.getAudioInputStream(sound)) {
// Initialize a clip with our sound file
Clip clip = AudioSystem.getClip();
clip.open(inputAudioStream);
[.... ] your code
clip.close();
progressBar.setValue(0);
}
[.... ] your catch code

Java I/O Opening Files in External Program

I have a Java program that I am using to scan a directory to look for certain files. It finds the files but now I am trying to get the code to open the files once it finds them, but I am not sure how to do that.
Here a part of my code
File file = new File("/Users/******/Desktop/******");
String[] A = file.list();
File[] C = file.listFiles();
for (String string : A) {
if (string.endsWith(".txt")) {
System.out.println(string);
}
if (string.contains("******")) {
System.out.println("It contains X file");
}
}
I am trying to get it so once it finds the files ending in .txt, it opens all of them
I have tried using Google on how to solve his, I came across .getRuntime() and so I tried
try{
Runtime.getRuntime().exec("******.txt");
} catch(IOException e){
}
But I am not fully understanding how how this works. I am trying to get to so that once it finds the files it opens them. I am not trying to have the IDE open the text on the screen. I want the actual Notepad/TextEdit program to open.
File[] files = new File("/Users/******/Desktop/******").listFiles();
for (File f : files) {
String fileName = f.getName();
if (fileName.endsWith(".txt")) {
System.out.println(fileName);
}
if (fileName.contains("******")) {
System.out.println("It contains X file");
}
}

Reading a directory returns null when deployed on the apache tomcat 7.0 server

I'm trying to read a folder on a network and retrieve a list of txt files.
When testing it locally in Eclipse, it works fine, however whenever I deploy it on the Apache Tomcat 7 server it returns null.
It doesn't seem to be an access right problem since the server has access to the folder I'm trying to browse.
I'm not sure what is going wrong there, is it a setting on the server I need to change or something else?
private List<File> readDirectory() {
File test = new File(envMap.get(database));
List<File> files = new ArrayList<File>();
try {
files = FileListing.getFileListing(test);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
List<File> txtFiles = new ArrayList<File>();
if (files != null) {
for (File file : files) {
if (file.isFile() && file.getName().endsWith(".txt")) {
txtFiles.add(file);
}
}
}
return txtFiles;
}
I used this http://www.javapractices.com/topic/TopicAction.do?Id=68 for FileListing.getFileListing
After double checking it turns out that I'm getting a FileNotFoundException: Directory does not exist. The directory does exists and the server has access rights on it, so I'm not really sure of what to do.
files cannot be null. Your code uses
static private List<File> getFileListingNoSort(File aStartingDir) throws FileNotFoundException {
List<File> result = new ArrayList<File>();
File[] filesAndDirs = aStartingDir.listFiles(); // may return null
List<File> filesDirs = Arrays.asList(filesAndDirs); // would throw NPE
for(File file : filesDirs) {
result.add(file);
if (!file.isFile()) {
//must be a directory
List<File> deeperList = getFileListingNoSort(file);
result.addAll(deeperList);
}
}
return result;
}
Are you sure you are showing us the right code?
Found out what the problem was, turns out that by default Apache is running under a Local System Account that has no network access. Changing that to another account with network access solved the problem.
Source: http://blog.mattwoodward.com/2010/08/accessing-network-drive-from-apache-and.html

Iterating through a directory in java

Hi right now I have the following method I am using to read one file at a time in a the same directory as the class that has this method:
private byte[][] getDoubleByteArrayOfFile(String fileName, Region region)
throws IOException
{
BufferedImage image = ImageIO.read(getClass().getResource(fileName));
byte[][] alphaInputData =
new byte[region.getInputXAxisLength()][region.getInputYAxisLength()];
for (int x = 0; x < alphaInputData.length; x++)
{
for (int y = 0; y < alphaInputData[x].length; y++)
{
int color = image.getRGB(x, y);
alphaInputData[x][y] = (byte)(color >> 23);
}
}
return alphaInputData;
}
I was wondering how I can make it so that instead of having "fileName" as a argument I can but a directory name as a argument and then iterate through all of the files within that directory and perform the same operation on it. Thanks!
If you are using Java 7, then you need to take a look at NIO.2.
Specifically, take a look at the Listing a Directory's Contents section.
Path dir = Paths.get("/directory/path");
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
for (Path file: stream) {
getDoubleByteArrayOfFile(file.getFileName(), someRegion);
}
} catch (IOException | DirectoryIteratorException x) {
// IOException can never be thrown by the iteration.
// In this snippet, it can only be thrown by newDirectoryStream.
System.err.println(x);
}
Here is a quick example that may help:
private ArrayList<byte[][]> getDoubleByteArrayOfDirectory(String dirName,
Region region) throws IOException {
ArrayList<byte[][]> results = new ArrayList<byte[][]>();
File directory = new File(dirName);
if (!directory.isDirectory()) return null //or handle however you wish
for (File file : directory.listFiles()) {
results.add(getDoubleByteArrayOfFile(file.getName()), region);
}
return results;
}
Not exactly what you asked for since it's wrapping your old method rather than re-writing it, but I find it a bit cleaner this way, and leaves you with the option of still processing a single file. Be sure to tweak the return type and how to handle the region based on your actual requirements (hard to tell from the question).
It is rather simple, using the File#listFiles() which returns a list of files in the specified File, which must be a directory. To make sure that the File is a directory, simply use File#isDirectory(). The problem occurs where you decide how to return the byte buffer. Since the method returns a 2d buffer, it is necessary to use a 3d byte buffer array, or in this case a List seems to me like the best choice since an unknown number of files will exist in the directory in question.
private List getDoubleByteArrayOfDirectory(String directory, Region region) throws IOException {
File directoryFile = new File(directory);
if(!directoryFile.isDirectory()) {
throw new IllegalArgumentException("path must be a directory");
}
List results = new ArrayList();
for(File temp : directoryFile.listFiles()) {
if(temp.isDirectory()) {
results.addAll(getDoubleByteArrayOfDirectory(temp.getPath(), region));
}else {
results.add(getDoubleByteArrayOfFile(temp.getPath(), region));
}
}
return results;
}
You can, see the list and listFiles documentation for how to do this.
We can use recursion to process a directory with subdirectories also. Here I am deleting file one by one, you can call any other function to process it.
public static void recursiveProcess(File file) {
//to end the recursive loop
if (!file.exists())
return;
//if directory, go inside and call recursively
if (file.isDirectory()) {
for (File f : file.listFiles()) {
//call recursively
recursiveProcess(f);
}
}
//call processing function, for example here I am deleting
file.delete();
System.out.println("Deleted (Processed) file/folder: "+file.getAbsolutePath());
}

Sending only 1mb of files from folder through web service

My question is that I want to send pdf files through web service with condition that only 1mb of files are taken from that folder containing many files.
Please help me to resolve this question.I am new to web service.
Ask me again if it not clear.
Thanks In Advance.
The following method will return a list of all the files whose total size is <= 1Mb
public List<File> getFilesList(){
File dirLoc = new File("C:\\Temp");
List<File> validFilesList = new ArrayList<File>();
File[] fileList;
final int fileSizeLimit = 1024000; // Bytes
try {
// select all the files whose size <= 1Mb
fileList = dirLoc.listFiles(new FilenameFilter() {
public boolean accept(final File dirLoc, final String fileName) {
return (new File(dirLoc + "\\" + fileName).length() <= fileSizeLimit);
}
});
long sizeCtr = fileSizeLimit;
for(File file : fileList){
if(file.length() <= sizeCtr){
validFilesList.add(file);
sizeCtr = sizeCtr - file.length();
if(sizeCtr <= 0){
break;
}
}
}
} catch (Exception e) {
e.printStackTrace();
validFilesList = new ArrayList<File>();
} finally {
fileList = null;
}
return validFilesList;
}
Well, I dont know if I have understood your requirements correctly and if this would help your problem but you can try this java solution for filtering the files from a directory.
You will get a list of files and then you can use the web-service specific code to send these files
File dirLoc = new File("C:\\California");
File[] fileList;
final int fileSize = 1024000;
try {
fileList = dirLoc.listFiles(new FilenameFilter() {
public boolean accept(final File dirLoc, final String fileName) {
return (new File(dirLoc+"\\"+fileName).length() > fileSize);
}
});
} catch (Exception e) {
e.printStackTrace();
} finally {
fileList = null;
}
This should work.
If you just require filenames, replace the File[] with String[] and .listFiles() with list()
I cannot say much about the performance though. For a small list of files it should work pretty fast.
I am not sure if this is what you want but you can pick the files and check their size by :
java.io.File file = new java.io.File("myfile.txt");
file.length();
File.length()Javadoc
Send files whose size is 1 Mb.

Categories