Sorry if I sound unexperienced or make no sense, I'm currently in my second computer science year and I'm currently making a light 2D game engine in java for a school project ( We can choose what we want to do for this one ).
So I'm currently working on the asset manager. For now it contains a hashmap with assets and a InputStreamProvider.
The InputStreamProvider is an interface between the assetManager and different kind of providers. For now, I only have a FileProvider which provides a stream from a file.
For now everything is ok, but when it comes to actually retrive the file from an id, I got a small problem with the extension. I thought that one of the advantages of using an asset manager was that you could just use IDs for your assets, which is fine once they are loaded, but when you need to load them how do you know the file extention?
Here is my workaround which is obviously not a good solution using a config file which lists the extentions being used for the assets and then trying to load the file with every extention.
public class FileProvider extends AssetInputStreamProvider {
private final static String assetLocation = "assets/";
protected final static List<String> assetExtentions = new ArrayList<>();
static {
try {
InputStreamReader isr = new InputStreamReader(new FileInputStream(new File("conf/assets.cfg")));
while (isr.ready()) {
String ext = new String();
Character c = (char) isr.read();
while (!c.equals(',')) {
ext += c;
c = (char) isr.read();
}
assetExtentions.add(ext);
}
} catch (FileNotFoundException ex) {
Logger.getLogger(AssetInputStreamProvider.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(AssetInputStreamProvider.class.getName()).log(Level.SEVERE, null, ex);
}
}
#Override
public InputStream getInputStream(String type, String name) {
File file;
for (String assetExtention : assetExtentions) {
try {
System.out.println(assetLocation + type + "/" + name + "." + assetExtention);
file = new File(assetLocation + type + "/" + name + "." + assetExtention);
return new FileInputStream(file);
} catch (FileNotFoundException ex) {
Logger.getLogger(FileProvider.class.getName()).log(Level.SEVERE, null, ex);
}
}
return null;
}
}
So I'd like to know if there is a way to load a file without knowing its extention, or if I'm completely mistaken about the way to load assets and then if anyone could tell me the way to do it properly it would be really helpful.
And out of curiosity, it's out of the scope of my question but I've seen some people using integer for IDs but no matter how much I think about it, I can't figure how to do it without hardcoding resources and giving them an int value so I'd like to get some hints to know how to implement such a system too.
Thanks a lot for reading and have a good day.
Related
Launching the jar, the console says that the file is not found and the font is not loaded.
How could I solve this problem?
I got this code:
public class FontLoader {
public static Font load(){
String fontFilePath = Paths.get(System.getProperty("user.dir"), "prova.jar", "Retro Gaming.ttf").toString();
int fontStyle = Font.BOLD;
int fontSize = CenterOnDefaultScreen.center().height*2/100;
Font font = null;
int fontTypeResource = Font.TRUETYPE_FONT;
if((fontFilePath == null || fontFilePath.isEmpty()) || fontSize < 1) {
throw new IllegalArgumentException("load() Method Error! Arguments " +
"passed to this method must contain a file path or a numerical " +
"value other than 0!" + System.lineSeparator());
}
try {
font = Font.createFont(fontTypeResource, new FileInputStream(
new File(fontFilePath))).deriveFont(fontStyle, fontSize);
}
catch (FileNotFoundException ex) {
System.out.println("FileNotFoundException: " + fontFilePath);
}
catch (FontFormatException | IOException ex) {
System.out.println("Exception thrown");
}
return font;
}
}
String fontFilePath = Paths.get(System.getProperty("user.dir"), "prova.jar", "Retro Gaming.ttf").toString();
That.. rather obviously won't work.
You need to use the gRAS (getResourceAsStream) system. File in java (as in, what new FileInputStream needs, the java.io.File object) are actual files. entries inside jar files don't count. It is not possible to refer to that ttf file with a File object, nor to open it with FileInputStream.
Fortunately, the createFont method doesn't demand that you pass a FileInputStream; any old InputStream will do.
The ttf file needs to be in the same classpath root as the this very class you are writing (for example, the same jar). Once you've ensured that is the case, you can use gRAS:
try (var fontIn = FontLoader.class.getResourceAsStream("/Retro Gaming.ttf")) {
Font.createFont(Font.TRUETYPE_FONT, fontIn).deriveFont(.., ...);
}
gRAS looks in the same place as where FontLoader.class lives. From your snippet it sounds like you put the ttf in the 'root' of the jar and not next to FontLoader. The leading slash in the string argument to getResourceAsStream means: Look relative to the root of the place FontLoader is in (so, your jar, presumably).
I am attempting to copy a file from inside my JAR to disk, outside the JAR file. The files that I will need to copy are default configuration files for a large-scale accounting system and are needed on the computer file system.
I have searched StackOverflow, as well as other sites (found with Google) and have read around fifty answers, which I've tried all of them. The code below is the first that has not simply blown up (with NullPointerException or FileNotFoundException), but has actually attempted to get the resource located in the JAR file.
I have my JAR file set up as follows:
com.is2300.isis
MainClass.java (actual name is crazy long and I don't want to type it out right now)
com.is2300.isis.resources
Location of the resource file I would like to copy out to disk
com.is2300.isis.utils
Location of my class ResourceExporter (below - bottom) that has the file exporting methods.
My MainClass.main() entry-point function:
public static void main(String[] args) {
// Test our 'utils.ResourceExporter.exportResource(String resourceName)
//+ function.
// Set the start point of our substring to either 5 or 9, depending upon
//+ if we are debugging (in NetBeans) or not (executing the JAR).
if ( isDebugging ) {
startPoint = 5;
} else {
startPoint = 9;
}
// First, we'll try just the name of the resource file to export.
String rsName = "nwind.conf";
try {
System.out.println(ResourceExporter.exportResource(rsName,
MainClass.class, "/home/user/tmp", startPoint));
} catch (Exception ex) {
System.err.println(ex.getCause());
System.err.println(ex.getMessage());
ex.printStackTrace(System.err);
}
// Then, we'll try it with the absolute path.
rsName = "/com/is2300/isis/resources/nwind.conf";
try {
System.out.println(ResourceExporter.exportResource(rsName,
MainClass.class, "/home/user/tmp", startPoint));
} catch (Exception ex) {
System.err.println(ex.getCause());
System.err.println(ex.getMessage());
ex.printStackTrace(System.err);
}
// Then, we'll try it with the relative path.
rsName = "../resources/nwind.conf";
try {
System.out.println(ResourceExporter.exportResource(rsName,
MainClass.class, "/home/user/tmp", startPoint));
} catch (Exception ex) {
System.err.println(ex.getCause());
System.err.println(ex.getMessage());
ex.printStackTrace(System.err);
}
// Last, we'll try it using dots instead of slashes.
rsName = "com.is2300.isis.resources.nwind.conf";
try {
System.out.println(ResourceExporter.exportResource(rsName,
MainClass.class, "/home/user/tmp", startPoint));
} catch (Exception ex) {
System.err.println(ex.getCause());
System.err.println(ex.getMessage());
ex.printStackTrace(System.err);
}
}
My ResourceExporter.exportResource() method:
public static String exportResource(String resourceName, Class cls,
String outPath, int startPoint) throws Exception {
File files = new File(cls.getResource(
cls.getResource(cls.getSimpleName() +
".class").toString().substring(
startPoint, cls.getResource(
cls.getSimpleName() + ".class").toString().lastIndexOf("/")
+ 1)) + "files");
InputStream in = new FileInputStream(files);
FileOutputStream out = new FileOutputStream(outPath +
resourceName.substring(resourceName.lastIndexOf("/")));
int readBytes;
byte[] buffer = new byte[4096];
while ( (readBytes = in.read(buffer)) > 0 )
out.write(buffer, 0, readBytes);
in.close();
out.close();
return files.getAbsolutePath();
}
With what I'm doing in public static void main(String[] args), I would expect one of the calls to the ResourceExporter.exportResource() method to actually cause the file to be copied.
However, when I step through the exportResource() method, on each call after the line:
File files = new File(cls.getResource(
cls.getResource(cls.getSimpleName() +
".class").toString().substring(
startPoint, cls.getResource(
cls.getSimpleName() + ".class").toString().lastIndexOf("/")
+ 1)) + "files");
The variable files.getCanonicalPath() call shows /home/user/Projects/ProjectName/nullfiles and I do not understand why this is, nor what this is.
#JBNizet and #AndrewThompson:
Thank you both for your comments. Especially #JBNizet! You gave me a swift kick in the head that made me look closer at what I had written and immediately saw the issue. Thank you very much for that.
The fix was this: Instead of the convoluted thing I was doing:
File files = new File(cls.getResource(
cls.getResource(cls.getSimpleName() +
".class").toString().substring(
startPoint, cls.getResource(
cls.getSimpleName() + ".class").toString().lastIndexOf("/")
+ 1)) + "files");
InputStream in = new FileInputStream(files);
FileOutputStream out = new FileOutputStream(outPath +
resourceName.substring(resourceName.lastIndexOf("/")));
Which I had written about 10 years ago and don't remember what I was thinking, I was able to simplify it to this:
InputStream in = ClassLoader.getSystemClassLoader().getSystemResourceAsStream(resourceName);
FileOutputStream out = new FileOutputStream(outPath +
resourceName.substring(resourceName.lastIndexOf("/")));
Now, the "file" (as a nod to the semantic correction by #AndrewThompson) is being located within the JAR file.
However, that was not the only change that had to be made. Where I set up the variable that is passed into the parameter resourceName was also not correct. I had it set up like so:
String rsName = "/com/is2300/isis/resources/nwind.conf";
However, the leading slash (/) was not supposed to be there. As soon as I changed the above line to:
String rsName = "com/is2300/isis/resources/nwind.conf";
everything just worked the way I expected.
Again, thanks to those two who commented. I appreciate your thoughts and assistance in getting my brain engaged.
I don't understand how to use TextIO's readFile(String Filename)
Can someone please explain how can I read an external file?
public static void readFile(String fileName) {
if (fileName == null) // Go back to reading standard input
readStandardInput();
else {
BufferedReader newin;
try {
newin = new BufferedReader( new FileReader(fileName) );
}
catch (Exception e) {
throw new IllegalArgumentException("Can't open file \"" + fileName + "\" for input.\n"
+ "(Error :" + e + ")");
}
if (! readingStandardInput) { // close current input stream
try {
in.close();
}
catch (Exception e) {
}
}
emptyBuffer(); // Added November 2007
in = newin;
readingStandardInput = false;
inputErrorCount = 0;
inputFileName = fileName;
}
}
I had to use TextIO for a school assignment and I got stuck on it too. The problem I had was that using the Scanner class I could just pass the name of the file as long as the file was in the same folder as my class.
Scanner fileScanner = new Scanner("data.txt");
That works fine. But with TextIO, this won't work;
TextIO.readfile("data.txt"); // can't find file
You have to include the path to the file like this;
TextIo.readfile("src/package/data.txt");
Not sure if there is a way to get it to work like the Scanner class or not, but this is what I've been doing in my course at school.
The above answer (about using the correct file name) is correct, however, as a clarification, make sure that you actually use the proper file path. The file path suggested above, i.e. src/package/ will not work in all circumstances. While this will be obvious to some, for those of you who need clarification, keep reading.
For example (and I use NetBeans), if you have already moved the file into NetBeans, and the file is already in the folder you want it to be in, then right click on the folder itself, and click 'properties'. Then expand the 'file path' section by clicking on the three dots next to the hidden file path. You will see the actual file path in its entirety.
For example, if the entire file path is:
C:\Users..\NetBeansProjects\IceCream\src\icecream\icecream.dat
Then, in the java code file itself, you can write:
TextIo.readfile("src/icecream/icecream.dat");
In other words, make sure you include the words 'src' but also everything that follows the src as well. If it's in the same folder as the rest of the files, you won't need anything prior to the 'src'.
I have a text file which I downloaded from the internet. File is large, somewhat around 77MB and I need to map it into the memory so I can read it fast. Here is my code
public class MapRead {
public MapRead()
{
try {
File file = new File("E:/Amazon HashFile/Hash.txt");
FileChannel c = new RandomAccessFile(file,"r").getChannel();
MappedByteBuffer buffer = c.map(FileChannel.MapMode.READ_ONLY, 0,c.size()).load();
System.out.println(buffer.isLoaded());
System.out.println(buffer.capacity());
} catch (IOException ex) {
Logger.getLogger(MapRead.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
No good, this generated the below output.
false
81022554
This is my first time trying this. I have no idea what went wrong, or what to do next, to read the file.
I have an application that merges two audio files into a single one.
My problem is, that when I run the application, sometimes (haven't been able to find out exactly when) I get the same file duplicated with two different names. When the output should be just 1 file
Here's the code I'm using to name the files:
AudioInputStream audioInputStream = null;
audioInputStream = new MixingFloatAudioInputStream(audioFormat, audioInputStreamList);
String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(Calendar.getInstance().getTime());
String strOutputFilename = timeStamp + "-" + tel +".wav";
System.out.println("Llamadas/" + strOutputFilename);
File outputFile = new File("Llamadas/" + strOutputFilename);
try
{
AudioSystem.write(audioInputStream, AudioFileFormat.Type.WAVE, outputFile);
}
catch (IOException e)
{
e.printStackTrace();
}
It doesn't throws any kind of error, I just get the duplicates with a difference on their names of 1 second on their tampstamp part.
ie:
20130910134003-097496427.wav
20130910134004-097496427.wav
Any idea of the reason or another method to get always the right timestamp?