i am trying to loop an audio file but when i've tried the other various methods available, my music doesn't play.
My basic code is:
import java.io.*;
import sun.audio.*;
public class PlayMusic {
public void playSound() {
try {
AudioPlayer p = AudioPlayer.player;
AudioStream as = new AudioStream(new FileInputStream("02 River Flows In You.wav"));
p.start(as);
} catch (IOException IOE) {
}
}
I've never seen sun.audio.AudioPlayer in use before! I've always used the javax.sound.sampled library.
Maybe you can tell me how you came across it. It looks to me like rather old code (10 years?) and also a bit on the limited side.
I think, if you aren't getting a single playback, you should try the URL form:
AudioStream audiostream = new AudioStream(url.openStream());
AudioPlayer.player.start(audiostream);
Then try putting the code in a loop? A lot depends on whether the .start command blocks or not. If it launches a separate thread (most likely), then you will have to figure out when the file ends, and I don't see any commands provided to do that! The spec also lists the possibility of creating an ContinuousAudioDataStream and managing that.
Unless there is something I don't know about this library that I should, I recommend using either a javax.sound.sampled.Clip, or javax.sound.sampled.SourceDataLine for playback. The Clip has a boolean you can set for looping, but requires the entire file be loaded into memory first. The SourceDataLine plays back from a url or file location, and can implement a listener to tell you when the file is done.
http://docs.oracle.com/javase/tutorial/sound/playing.html
Related
In Linux, everything is a file: keyboards, directories, text files, USB devices, etc.
In java, what would happen if I used a File object to take in something like a keyboard (or anything that isn't your typical "file". Would it work? If not, how come?
If it would work, would I be able to do anything significant with it or are there limitations?
Yes, the Java File class works the same way for all files. It will also work for directories (those will return true for isDirectory) and special files like keyboards and USB devices (those will return false for isFile).
FileReader, FileInputStream, and classes like that will work on regular and special files, but will not work on directories.
As an example, here's a simple program (error handling removed for simplicity) that reads random bytes from the '/dev/random' device and writes them to the audio output at '/dev/dsp'. (It's loud and horrible, mind your ears!)
import java.io.*;
public class Main {
public static void main(String[] args) throws Exception {
File random = new File("/dev/random");
File audio = new File("/dev/dsp");
InputStream in = new FileInputStream(random);
OutputStream out = new FileOutputStream(audio);
while (true) {
out.write(in.read());
}
}
}
Something to keep in mind is that 'special' files like these usually do not allow you to seek, that is, go forwards and backwards in the file. You can't, for example, read what they keyboard will send ten minutes from now.
I'm trying to make an application where when I click a JButton, it plays a song. I've already figured out how to specify JButtons. However, I can't seem to find a way to play sound. I'm not going to use sun.audio, so many of the threads that I looked at didnt work. I found many low quality answers. Eventually, I settled on this code.
public static synchronized void playSound(final String url) {
new Thread(new Runnable() {
public void run() {
try {
Clip clip = AudioSystem.getClip();
AudioInputStream inputStream = AudioSystem.getAudioInputStream(
Main.class.getResourceAsStream("/path/to/sounds/" + url));
clip.open(inputStream);
clip.start();
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}).start();
}
Inside my src folder, I have a folder called "Songs". I changed the file path to this:
/Songs/
Then, I tried calling the function using a wav file:
playSound("song.wav");
And then I get a null error. I believe that this is because it does not recognize the file path. The answer to my problem is most likely very obvious, but somehow I cant find it.
put song.wav in the same folder of your Main class, then the getResourceAsStream will find it.
if you're using eclipse, it can automatically copy the .wav file to the output folder.
You might want to create a class on some different java package so your entry point does not get polluted by assets.
This reading might help you: http://www.thinkplexx.com/learn/howto/java/system/java-resource-loading-explained-absolute-and-relative-names-difference-between-classloader-and-class-resource-loading
I need to write a custom batch File renamer. I've got the bulk of it done except I can't figure out how to check if a file is already open. I'm just using the java.io.File package and there is a canWrite() method but that doesn't seem to test if the file is in use by another program. Any ideas on how I can make this work?
Using the Apache Commons IO library...
boolean isFileUnlocked = false;
try {
org.apache.commons.io.FileUtils.touch(yourFile);
isFileUnlocked = true;
} catch (IOException e) {
isFileUnlocked = false;
}
if(isFileUnlocked){
// Do stuff you need to do with a file that is NOT locked.
} else {
// Do stuff you need to do with a file that IS locked
}
(The Q&A is about how to deal with Windows "open file" locks ... not how implement this kind of locking portably.)
This whole issue is fraught with portability issues and race conditions:
You could try to use FileLock, but it is not necessarily supported for your OS and/or filesystem.
It appears that on Windows you may be unable to use FileLock if another application has opened the file in a particular way.
Even if you did manage to use FileLock or something else, you've still got the problem that something may come in and open the file between you testing the file and doing the rename.
A simpler though non-portable solution is to just try the rename (or whatever it is you are trying to do) and diagnose the return value and / or any Java exceptions that arise due to opened files.
Notes:
If you use the Files API instead of the File API you will get more information in the event of a failure.
On systems (e.g. Linux) where you are allowed to rename a locked or open file, you won't get any failure result or exceptions. The operation will just succeed. However, on such systems you generally don't need to worry if a file is already open, since the OS doesn't lock files on open.
// TO CHECK WHETHER A FILE IS OPENED
// OR NOT (not for .txt files)
// the file we want to check
String fileName = "C:\\Text.xlsx";
File file = new File(fileName);
// try to rename the file with the same name
File sameFileName = new File(fileName);
if(file.renameTo(sameFileName)){
// if the file is renamed
System.out.println("file is closed");
}else{
// if the file didnt accept the renaming operation
System.out.println("file is opened");
}
On Windows I found the answer https://stackoverflow.com/a/13706972/3014879 using
fileIsLocked = !file.renameTo(file)
most useful, as it avoids false positives when processing write protected (or readonly) files.
org.apache.commons.io.FileUtils.touch(yourFile) doesn't check if your file is open or not. Instead, it changes the timestamp of the file to the current time.
I used IOException and it works just fine:
try
{
String filePath = "C:\sheet.xlsx";
FileWriter fw = new FileWriter(filePath );
}
catch (IOException e)
{
System.out.println("File is open");
}
I don't think you'll ever get a definitive solution for this, the operating system isn't necessarily going to tell you if the file is open or not.
You might get some mileage out of java.nio.channels.FileLock, although the javadoc is loaded with caveats.
Hi I really hope this helps.
I tried all the options before and none really work on Windows. The only think that helped me accomplish this was trying to move the file. Event to the same place under an ATOMIC_MOVE. If the file is being written by another program or Java thread, this definitely will produce an Exception.
try{
Files.move(Paths.get(currentFile.getPath()),
Paths.get(currentFile.getPath()), StandardCopyOption.ATOMIC_MOVE);
// DO YOUR STUFF HERE SINCE IT IS NOT BEING WRITTEN BY ANOTHER PROGRAM
} catch (Exception e){
// DO NOT WRITE THEN SINCE THE FILE IS BEING WRITTEN BY ANOTHER PROGRAM
}
If file is in use FileOutputStream fileOutputStream = new FileOutputStream(file); returns java.io.FileNotFoundException with 'The process cannot access the file because it is being used by another process' in the exception message.
This is my code
public static void main(String[] args) {
try{
// open the sound file as a Java input stream
InputStream in = new FileInputStream("Sound.wav");
// create an audiostream from the inputstream
AudioStream audioStream = new AudioStream(in);
// play the audio clip with the audioplayer class
AudioPlayer.player.start(audioStream);
}
catch(Exception e){
System.out.println("Audio not found");
}
}
Sun Audio is Undocumented
You should not be using Sun Audio in your program. See here and here.
The Answer Depends on Your Library
If you are using Java Clip (built-in), try the example here. This is probably the simplest method.
If you switch to use JavaFX, you can see the API here, which has ways to loop. However, JavaFX requires a bit of package restructuring, and there is a learning curve. Unless you need JavaFX for other reasons, I would avoid it.
If you are using any other library, please consult the API for that library, or share with us what you are attempting to use. I have personally used BasicPlayer, but it is quite old.
I've made two apps designed to run concurrently (I do not want to combine them), and one reads from a certain file and the other writes to it. When one or the other are running no errors, however if they are both running a get an access is denied error.
Relevant code of the first:
class MakeImage implements Runnable {
#Override
public void run() {
File file = new File("C:/Users/jeremy/Desktop/New folder (3)/test.png");
while (true) {
try{
//make image
if(image!=null)
{
file.createNewFile();
ImageIO.write(image, "png", file);
hello.repaint();}}
catch(Exception e)
{
e.printStackTrace();
}
}
}
}
Relevant code of the second:
BufferedImage image = null;
try {
// Read from a file
image = ImageIO.read(new File("C:/Users/jeremy/Desktop/New folder (3)/test.png"));
}
catch(Exception e){
e.printStackTrace();
}
if(image!=null)
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write( image, "png", baos );
baos.flush();
byte[] imageInByte = baos.toByteArray();
baos.close();
returns=Base64.encodeBase64String(imageInByte);
}
I looked at this: Java: how to handle two process trying to modify the same file, but that is when both are writting to the file where here only one is. I tried the retry later method as suggested in the former's answer without any luck. Any help would be greatly appreciated.
Unless you use OS level file locking of some sort and check for the locks you're not going to be able to reliably do this very easily. A fairly reliable way to manage this would be to use another file in the directory as a semaphore, "touch" it when you're writing or reading and remove it when you're done. Check for the existence of the semaphore before accessing the file. Otherwise you will need to use a database of some sort to store the file lock (guaranteed consistency) and check for it there.
That said, you really should just combine this into 1 program.
Try RandomAccessFile.
This is a useful but very dangerous feature. It goes like this "if you create different instances of RandomAccessFile for a same file you can concurrently write to the different parts of the file."
You can create multiple threads pointing to different parts of the file using seek method and multiple threads can update the file at the same time. Seek allow you to move to any part of the file even if it doesn't exist (after EOF), hence you can move to any location in the newly created file and write bytes on that location. You can open multiple instances of the same file and seek to different locations and write to multiple locations at the same time.
Use synchronized on the method that modify the file.
Edited:
As per the Defination of a Thread safe class, its this way.. " A class is said to be thread safe, which it works correctly in the presence of the underlying OS interleaving and scheduling with NO means of synchronization mechanism from the client side".
I believe there is a File which is to be accessed on to a different machine, so there must be some client-server mechanism, if its there.. then Let the Server side have the synchronization mechanism, and then it doesnt matters how many client access it...
If not, synchronized is more than enough........