I've attempted to create a custom font using the following method, however it throws an exception :
Stream closed
and nothing happens! How can I import a ttf file from my JAR and use it in Java 2D! I'v managed to get it to work with external files, but it just doesn't work with an InputStream!
public Font gameFont(String filename, float fontSize) {
Font myfont = null;
Font myfontReal = null;
try {
InputStream is = new BufferedInputStream(this.getClass().getResourceAsStream("com/or/dungeon/" + filename));
myfont = Font.createFont(Font.TRUETYPE_FONT, is);
myfontReal = myfont.deriveFont(fontSize);
is.close();
} catch (FontFormatException | IOException e) {
System.out.println(e.getMessage());
}
return myfontReal;
}
You are missing a leading slash. Without it, it is searching relative to the class making the call. Try:
this.getClass().getResourceAsStream("/com/or/dungeon/" + filename));
Alternatively, try:
this.getClass().getClassLoader().getResourceAsStream("com/or/dungeon/" + filename));
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).
The below code works when running from my editor but the image fails to load when compiled into a runnable jar file with eclipse.
public static BufferedImage getRandomImage() {
// returns a random image from the Images folder
Random rand = new Random();
URL res = Card.class.getResource("Images"); // located in /src/.../Images
File f = new File(res.getFile());
if (!f.exists()) {
return new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
}
File[] files = f.listFiles();
int random = rand.nextInt(files.length);
BufferedImage img = null;
try {
img = ImageIO.read(files[random]);
} catch (IOException e) {
e.printStackTrace();
}
return img;
}
Could someone please suggest how I can modify my code or editor to load the files when compiled.
I have read other methods of accessing files but since I need to select randomly from a folder, I need to use the File class.
There is no safe way to list resources at runtime.
(Some people may suggest approaches which work sometimes, but will not work all the time. Class.getResource is not guaranteed to provide a listing; ProtectionDomain.getCodeSource can return null.)
But you don’t need to. It’s your application; you already know what files you put into it.
The best way is to either hard-code the list of files, or include a simple text file that contains a list of the files.
As an example, assume you created (or generated) a file named image-files.txt in which each line contains the base name of an image file, and embedded that file in your application:
List<String> imageNames;
try (BufferedReader linesReader = new BufferedReader(
new InputStreamReader(
Card.class.getResourceAsStream("image-files.txt"),
StandardCharsets.UTF_8));
Stream<String> lines = linesReader.lines()) {
imageNames = lines.collect(Collectors.toList());
} catch (IOException e) {
throw new UncheckedIOException(e);
}
int random = rand.nextInt(imageNames.length());
String imageName = imageNames.get(random)));
BufferedImage img;
try {
img = ImageIO.read(Card.class.getResource(imageName));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
return img;
Note: The getFile() method of URL does not return a valid filename. It only returns the path portion of a URL. There are many characters which would be illegal in URLs, so the path portion percent-escapes them. If you ignore this fact, the value returned by getFile() will eventually fail.
(The reason for the misleading method name is that the URL class was part of Java 1.0, and in the mid-1990s, all URLs actually referred to physical files.)
I need to use the File class
Each .jar entry is just a subsequence of compressed bytes within a single .jar file, so you will never be able to use File to read such an entry. Class.getResource and Class.getResourceAsStream are the only correct ways to read those entries.
The problem is that you are trying to access a URL of a resource as a file.
with this you can get all the images, and then you can do this:
List<String> arr = getResourceFiles("Images");
String imgPath = arr.get(rand.nextInt(arr.size()));
InputStream stream = Card.class.getResourceAsStream("Images/" + imgPath);
try {
img = ImageIO.read(stream);
} catch (IOException e) {
e.printStackTrace();
}
return img;
My goal is to be able to use awesome fonts an a Java GUI. For that matter I searched and found this question.
I chose the second answer to import fontawesome-webfont.ttf with an InputStream. I tailored the code to my needs because I do not need a method for my purpose.
But when it comes to testing it, I get the error: "Problem reading font data" in the line:
Font font = Font.createFont(Font.TRUETYPE_FONT, is);
This is the problematic code:
try (InputStream is = this.getClass().getResourceAsStream("C:/Users/Prak01/Documents/EclipseWorkspace/Zeiterfassung/fontawesome-webfont.ttf")) {
try {
Font font = Font.createFont(Font.TRUETYPE_FONT, is);
font = font.deriveFont(Font.PLAIN, 24f);
TextfieldFont = new JTextField("");
TextfieldFont.setFont(font);
} catch (FontFormatException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
I believe that I did everything according to the rules. The data path is correct. Could it be possible that it is because of the...
this.getClass().getResourcesAsStream();
because I changed it from:
TestFontAwsome.class.getResourceAsStream();
but I believe that it should work with this.getClass() as well.
You have mistakenly assumed that the argument to getResourceAsStream is supposed to be a file name. It is not a file name; it’s a relative URL which is resolved against each entry in the classpath. Generally, this means it should be a path in the same .jar file.
If you want to load a Font directly from a File, don’t use getResourceAsStream. Just open it as a file:
try (InputStream is = new BufferedInputStream(
Files.newInputStream(Paths.get("C:/Users/Prak01/Documents/EclipseWorkspace/Zeiterfassung/fontawesome-webfont.ttf")))) {
Note: You don’t need two try blocks. A try-with-resources statement is allowed to have a catch block:
try (InputStream is = new BufferedInputStream(
Files.newInputStream(Paths.get("C:/Users/Prak01/Documents/EclipseWorkspace/Zeiterfassung/fontawesome-webfont.ttf")))) {
// ...
} catch (FontFormatException e1) {
// ...
}
In a folder called data, I have a font file called font.ttf.
I want to read it in, like this:
try {
Font f = Font.createFont(Font.TRUETYPE_FONT,
new File("data/font.ttf")).deriveFont(12.0);
} catch (IOException | FontFormatException e) {}
That worked fine up until I removed the same font from the system (it's still in the data folder!).
Now, it's just showing Java's generic font.
Is it even possible to read in a font from a file which is not in the System Fonts folder?
You don't seem to be doing anything with that Font f once you've loaded it in, so you might simply be losing it due to block scoping.
Font fallback = load some system default;
Font myfont = null;
...
try {
File ffile = new File("data/font.ttf");
myfont = Font.createFont(Font.TRUETYPE_FONT, ffile).deriveFont(12);
} catch (FontFormatException ffe) {
System.out.println("Tried to load a bad font...");
ffe.printStackTrace();
} catch (IOException ioe) {
System.out.println("I have no idea what went wrong");
ioe.printStackTrace();
} finally {
loadMyApplication(myfont == null ? fallback : myfont);
}
Or if you absolutely need that font for correct UI building or content rendering, call loadMyApplication in the try block, so that any catches prevent your application from loading.
I'm new here and kinda new to java.
I've encountered a problem.
I have a very simple program that tries to create pngs and save them in a user selected folder.
byteimage is a a private byte[]:
byteimage = bcd.createPNG(300, 140, ColorSpace.TYPE_RGB, Color.BLACK, Color.BLACK);
setPath() is called inside the action listener of the browse button
private void setPath() {
JFileChooser pathchooser = new JFileChooser();
pathchooser.setMultiSelectionEnabled(false);
pathchooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
pathchooser.setApproveButtonMnemonic(KeyEvent.VK_ENTER);
pathchooser.showDialog(this, "OK");
File f = pathchooser.getSelectedFile();
if (f != null) {
filepath = f.getAbsolutePath();
pathfield.setText(filepath);
}
}
Byte to png method looks like this:
public void byteToPNG(String filename) {
try {
InputStream in = new ByteArrayInputStream(byteimage);
BufferedImage bufferedimg = ImageIO.read(in);
ImageIO.write(bufferedimg, "png", new File(filename));
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
This method is called like this:
byteToPNG(pathfield.getText() + System.getProperty("file.separator") + textfield.getText() + ".png");
textfield.getText() sets the actual name of the png.
Inside the constructor, default filepath is set:
filepath = System.getProperty("user.dir");
pathfield.setText(filepath);
The code runs fine from Eclipse and it produces a png image at the desired location.
Unfortunately, after exporting as jar, it starts but when the button for generating the png is pressed, nothing happens. I'm thinking there's a problem at InputStream or BufferedImage, but I'm a bit puzzled.
If the String fileName passed to byteToPNG isn't absolute (i.e. written in the form "C:/foo/bar/etc") that could be the cause of the broken jar. You could also try running the jar file in the terminal using the command:
java -jar myJarFile.jar.
This will cause a console window to remain open alongside your running jar application in which all your applications output (including any exceptions) will be printed.