I found many similar questions on this topic in this forum, but none of the solutions of those questions working for me and this problem is really making me frustrated.
I have the following method which should play a wav file when I call it.
Directory of the wav file is: ProjectFolder/src/resources/Sounds/click.wav
public static void Click()
{
String clickSound = "/resources/Sounds/click.wav";
Media hit = new Media(new File(clickSound).toPath().toString());
MediaPlayer mediaPlayer = new MediaPlayer(hit);
mediaPlayer.play();
}
But it results in the following exception:
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: java.net.URISyntaxException: Illegal character in path at index 0: \resources\Sounds\click.wav
at javafx.scene.media.Media.<init>(Media.java:385)
When I set the value of the string clickSound "resources/Sounds/click.wav" instead of "/resources/Sounds/click.wav", the exception says illegal character in path at index 9.
So I am guessing that it is considering '/' character as an illegal character. I tried using '\' instead of '/', but the result was same.
I do not want to change the location of the wav file for certain reason. How can access I access that wav file from ProjectFolder/src/resources/Sounds/click.wav and play it without any exception?
Any kind of help is appreciated.
Thanks in advance.
As stated in the documentation:
The source must represent a valid URI and is immutable. Only HTTP, HTTPS, FILE, and JAR URLs are supported. If the provided URL is invalid then an exception will be thrown.
You are passing in the path to a file, instead of a URI.
You almost certainly don't want a file here anyway; for example, when you deploy your application it will typically be deployed as a jar file, and the media will be an entry in that jar file (so it won't be a file in its own right at all). On top of that, the resources folder is typically part of the source code structure, and for obvious reasons the source code is not usually available at runtime.
Assuming your resources are being deployed to the root of the classpath, which is the usual setup, you need something like
String clickSound = "/Sounds/click.wav";
Media hit = new Media(getClass().getResource(clickSound).toExternalForm());
You listed the file as in directory "ProjectFolder/src/resource/Sounds/click.wav" but when trying to access you have "resources" instead of "resource"
Related
Having researched this issue extensively here & elsewhere, without finding a working solution, I thought I'd ask...
I have a jar file (deployed on a RaspberryPi), with an internal structure like this:
myApp
MyClass
....
textFiles
foo.txt
....
I need 'MyClass' to read 'foo.txt'.
the general advice here & elsewhere is to use something like the following:
InputStream in = getClass().getResourceAsStream("../textFiles/foo.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
I have also read that the path to use (as the param for getResourceAsStream()) is the path to the target file, relative to the location of the class reading the file.(..?)
However, regardless of the path I use, I cannot get the above 2 lines to work. I always get an NPE thrown by the 2nd line.
I'm assuming that the NPE indicates that 'in' is null because 'foo.txt' has not been found.
any advice leading to a successful resolution, gratefully received.
cheers
Paul
Try removing the .. from the path, as per documentation:
If the name begins with a '/' ('\u002f'), then the absolute name of the resource is the portion of the name following the '/'.
Otherwise, the absolute name is of the following form:
modified_package_name/name
Where the modified_package_name is the package name of this object with '/' substituted for '.' ('\u002e').
So my immediate problem has been solved, but not to my satisfaction.
I relocated the contents of 'textFiles' (in the Jar), so all the text files were in the Jar's root. I then successfully managed to find & load the file using:
InputStream in = getClass().getResourceAsStream("/foo.txt");
However, I still don't undserstand why this worked. I don't see why "/textFiles/foo.txt" didn't work, when the files were in that subdir, off the Jar's root...?
Anyway...I have a new problem now, which I think is hardware related....it takes about 40 seconds to read the files!! I think I blame the old SD card in my Raspberry Pi.
But that's a problem for another day!
Thanks for your input.
I want to get the URIs to the entries of a zip file in order to keep references to it's contents without having to keep the zip file open.
Therefore I open the zip file using the zip filesystem and export the Path of the entries as URI.
Path zipfile = ...
URI uriOfFileInZip;
try(FileSystem fs = FileSystems.newFileSystem(zipfile, null)){
Path fileInZip = fs.getPath("fileInZip.txt");
uriOfFileInZip = fileInZip.toUri();
}
Now I want to read the file again, so I try to open a stream to the file.
InputStream is = uriOfFileInZip.toURL().openStream();
This works as long as the path of the zip file does not contain any spaces. As soon as it contains spaces, I get an error like this
java.io.FileNotFoundException: D:\example\name%20of%20zipfile.zip (The system cannot find the file specified)
the URI to the file in the zip is
jar:file:///D:/example/name%2520of%2520zipfile.zip!/fileInZip.txt
the name of the zip is
D:\example\name of zipfile.zip
I wonder about the %2520 this seems like an issue with the URL encoding, but shouldn't this be handled transparently? Or is it a bug?
Any ideas to solve this problem?
Looks like a bug.
Seems as if com.sun.nio.zipfs.ZipPath.toUri() is either messed up, or I didn't read the corresponding RFC yet ;-). Played around with some other file names. There seems to be a double encoding going on for the zip file path, but not for the file entry in the zip.
Besides not using the URI-approach you could also build the URI yourself from scratch, but then you are not that flexible anymore. Or you just undo the unnecessary encoding:
String uriParts[] = uriOfFileInZip.toString().split("!");
uriParts[0] = URLDecoder.decode(uriParts[0], "UTF-8");
uriOfFileInZip = URI.create(String.join("!", uriParts));
But to be honest, I would rather try to omit the URI for zip files or if you really have to, rename the files beforehand ;-) Better yet: open a bug if it does not behave as stated in the corresponding RFCs.
You may also want to get some additional information from the following question regarding bug, etc.:
Java 7 zip file system provider doesn't seem to accept spaces in URI
EDIT (added proposal without URI):
You can also try to completely work with your Path instance (fileInZip) instead of the URI, as the path instance "knows" its filesystem.
As soon as you need access to the file inside the zip, you create a new FileSystem based on the information of the Path instance (fileInZip.getFileSystem()). I did not elaborate that completely, but at least the file store should contain all the necessary information to access the zip file again. With that information you could call something like FileSystems.newFileSystem(Paths.get(fileStoreName), null).
Then you can also use Files.newInputStream(fileInZip) to create your InputStream. No need to use URI here.
This is only reproducible with JDK 8. The later versions do not have this issue.
For the following code:
Map<String, String> env = new HashMap<>();
env.put("create", "true");
final FileSystem fs = FileSystems.newFileSystem(new URI("jar:file:/D:/path%20with%20spaces/junit-4.5.jar"), env);
System.out.println(fs.getPath("LICENSE.TXT").toUri()); `
I got the following output with JDK 1.8.0_212 :
jar:file:///D:/path%2520with%2520spaces/junit-4.5.jar!/LICENSE.TXT
whereas with JDK 11.0.3:
jar:file:///D:/path%20with%20spaces/junit-4.5.jar!/LICENSE.TXT
A search through the Java bug system shows that it had been fixed in JDK 9 with JDK-8131067 .
I have a text file in my resource folder and I need to be able to read/remove/add text. I believe I have to use append so I tried this.
Files.write(Paths.get(Testing.class.getResource("/testresources/SearchList.txt").getPath())
, "the text".getBytes(), StandardOpenOption.APPEND);
This gives me back
Exception in thread "main" java.nio.file.InvalidPathException: Illegal char <:> at index 2: /C:/Users/Ben/workspace/Eve/bin/org/me/Testing/resources/SearchList.txt
If anyone could should me some clarity on this subject that would be great. Thankyou!
This worked for me fine:
You should add the text file to a raw folder. If the raw folder does not exist in your resource directory, create one. And then in order to access it and write or edit it, use this:
OutputStream outputStream=getResources().openRawResource(R.raw.YourTextFile);
then in order to Read from the file, you should do this
InputStream inputStream=getResources().openRawResource(R.raw.YourTextFile);
A leading slash is being automatically added to your path - /C:/Users/Ben/workspace/Eve/bin/org/me/Testing/resources/SearchList.txt
Lots of solutions have been suggested here in answers, Java NIO file path issue
Use any of those mentioned answers as your solution.
Also, for files intended to be in jar, You need to use Paths method public static Path get(URI uri) instead of public static Path get(String first,String... more) See How to get a path to a resource in a Java JAR file
I'm trying to play an mp3 file in BlueJ following this Stack question answer:
Playing .mp3 and .wav in Java?
I have the exact same code except the file name. Here is my code:
String bip = "Johnny.mp3";
Media hit = new Media(bip);
MediaPlayer mediaPlayer = new MediaPlayer(hit);
mediaPlayer.play();
I CAN compile this, but when the program tries to run it I get an exception. Here is the entire error:
java.lang.IllegalArgumentException: uri.getScheme() == null! uri == 'Johnny.mp3'
at com.sun.media.jfxmedia.locator.Locator.<init>(Locator.java:211)
at javafx.scene.media.Media.<init>(Media.java:391)
at Game.goRoom(Game.java:282)
at Game.processCommand(Game.java:167)
at Game.play(Game.java:130)
Personally, I think this is related with the file path I have given. I know that the file exists in my project map but I'm very uncertain on the pathway they want, do they want a full pathway all the way from file:// or just the sound-files name which is what I have done? Note that this project doesn't have any resource folder like Eclipse projects have since this is how the IDE handles it files. The sound-file just lies in the same folder as all the classes so it's not sorted in any manner.
I have checked around, and it seems that if this is not my problem it would be that my JavaFX is not initialized. If this is the case, how would I go about it and how would the syntax look like?
Media takes your String value and tries to make a URI. Why the method doesn't just require you to pass it a URI (or URL) directly, I don't know.
The documentation outlines this rather well...
Constructs a Media instance. This is the only way to specify the media
source. The source must represent a valid URI and is immutable. Only
HTTP, FILE, and JAR URLs are supported. If the provided URL is invalid
then an exception will be thrown. If an asynchronous error occurs, the
error property will be set. Listen to this property to be notified of
any such errors.
...
Constraints:
The supplied URI must conform to RFC-2396 as required by java.net.URI.
Only HTTP, FILE, and JAR URIs are supported.
See java.net.URI for more information about URI formatting in
general. JAR URL syntax is specified in
java.net.JarURLConnection.
Parameters: source - The URI of the source media. Throws:
- java.lang.NullPointerException - if the URI string is null.
- java.lang.IllegalArgumentException - if the URI string does not
conform to RFC-2396 or, if appropriate, the Jar URL specification, or
is in a non-compliant form which cannot be modified to a compliant
form. - java.lang.IllegalArgumentException - if the URI string has a
null scheme. - java.lang.UnsupportedOperationException - if the
protocol specified for the source is not supported....
And if we have a look at the source, you can see it trying to wrap the String in a URI class...
public Media(#NamedArg("source") String source) {
this.source = source;
URI uri = null;
try {
// URI will throw NPE if source == null: do not catch it!
uri = new URI(source);
} catch(URISyntaxException use) {
throw new IllegalArgumentException(use);
}
So, depending on where the file is actually stored, you could use something like
Media hit = new Media(new File(bip).toURI().toURL().toString());
MediaPlayer mediaPlayer = new MediaPlayer(hit);
mediaPlayer.play();
This also assumes that "Johnny.mp3" is in the current working directory of your program.
I say "depending" as you would use a different approach for media files which were located internally (bundled) with your application to those which are external.
In which case you might use something like...
Media hit = new Media(getClass().getResource(bip).toExternalForm());
MediaPlayer mediaPlayer = new MediaPlayer(hit);
mediaPlayer.play();
Here ya go:
MediaPlayer yourPlayer = new MediaPlayer(new Media(Paths.get("yourAudioFile").toUri().toString()));
Make sure to add the file extension onto the audio file! Also, import the following:
import java.nio.file.Paths;
I'm assuming you have the Media and MediaPlayer classes imported.
The code I am using to load the image is:
ImageIO.read(SpriteSheet.class.getResource(path));
The path being the path to the resource. But it would error with IllegalArgumentException. I wondered what might be causing and came to the conclusion that the resource should be added into the same path as the class.
Is it possible to load the image from another folder, like a res folder outside of the bin folder? (folder holding compiled classes)
EDIT:
So i messed around with a few things, and came to a solution. But now I have another problem. Here is my code
File sheet = new File(SpriteSheet.class.getProtectionDomain().getCodeSource().getLocation().getPath());
URI uri = sheet.toURI();
BufferedImage image = ImageIO.read(uri.toURL());
When I try to run it, it gives me an IIOException: Can't read Input File
This means that I can never actually get it work. I tried debugging by prining the URL to the console and this is the URL.
C:\Users\Amma\Abhijeet\Eclipse%20Workspace1\Test%20Game\bin
The %20 comes in the middle. Meaning that the file is and never can be acceesed. Is there anyway I can fix this?
Thanks.
Class.getResource will return null if the resource could not be found or the invoker doesn't have adequate privileges to get the resource.
All variants of ImageIO.read will throw an IllegalArgumentException if they receive a null input.
Take a look at the documentation of the getResource to understand how an absolute resource name is constructed from the given resource named and what are the rules for searching resources.
You can read images from any location as long as you have permissions to do so, the ImageIO.read method accepts a File, URL or InputStream so you have many option to do it.