Eclipse Java File FileInputStream vs Input Stream when loading a font file

I am learning some lessons and I am having trouble loading a font file in the Eclipse Java Project. I tried many of the solutions offered here on SO and ended up finding one (using FileInputStream) that works for me, but not when the project is exported as a runnable JAR. On the other hand, using the same directory structure in another project where I upload the icons works, so I think the problem is not in the path itself.

Here is the directory structure enter image description here :

Here is the code:

package examples; import java.awt.Font; import java.awt.FontFormatException; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.net.URISyntaxException; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JPanel; public class Test01 extends JPanel { String text = "Free the bound periodicals"; Font fon; FileInputStream fis; // InputStream fis; @Override public void paintComponent(Graphics comp) { Graphics2D comp2D = (Graphics2D) comp; // This (for another project) works both in Eclipse and in runnable JAR // ImageIcon loadIcon = new ImageIcon(getClass().getResource("/examples/resources/load.gif")); // This (quite contrary to many SO suggestions) doesn't work in Eclipse for this project, why? // fis = this.getClass().getResourceAsStream("/examples/resources/vedrana.ttf"); // This (quite contrary to many SO suggestions) doesn't work in Eclipse for this project, why? // fis = this.getClass().getClassLoader().getResourceAsStream("/examples/resources/verdana.ttf"); // This works within Eclipse project but not when exported to runnable JAR, // Moreover many suggest that InputStream should be favored over FileInputStream try { fis = new FileInputStream(new File(getClass().getResource("/examples/resources/verdana.ttf").toURI())); } catch (FileNotFoundException e1) { JOptionPane.showMessageDialog(this, "FileNotFoundException!"); } catch (URISyntaxException e1) { JOptionPane.showMessageDialog(this, "URISyntaxException!"); } catch (Exception e1) { JOptionPane.showMessageDialog(this, "NullPointerException!"); } try { fon = Font.createFont(Font.TRUETYPE_FONT, fis); } catch (FontFormatException e) { // TODO Auto-generated catch block System.out.println("Error - FontFormatException " + e.getMessage()); } catch (IOException e) { // TODO Auto-generated catch block System.out.println("Error - IOException " + e.getMessage()); } fon = fon.deriveFont(Font.PLAIN, 72); FontMetrics metrics = getFontMetrics(fon); comp2D.setFont(fon); comp2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); int x = (getSize().width - metrics.stringWidth(text)) / 2; int y = getSize().height / 2; comp2D.drawString(text, x, y); } public static void main(String[] args) { JFrame mainFrame = new JFrame("Main Menu"); mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mainFrame.setSize(1000, 250); mainFrame.setVisible(true); mainFrame.add(new Test01()); // mainFrame.pack(); } } 

So what bothers me:

- Why this does not work (it seems he cannot find the font file), since it throws a NullPointerException

 fis = this.getClass().getResourceAsStream("/examples/resources/vedrana.ttf"); 

and does not work

 fis = this.getClass().getClassLoader().getResourceAsStream("/examples/resources/verdana.ttf"); 

- Why does this work in an Eclipse project, but not when exporting to a runnable JAR

 fis = new FileInputStream(new File(getClass().getResource("/examples/resources/verdana.ttf").toURI())); 

UPDATE As it turned out, this will work:

 fis = this.getClass().getClassLoader().getResourceAsStream("examples/resources/verdana.ttf"); 

The problem was in the first braid - the path should be "examples / resources / verdana.ttf" instead of "/examples/resources/verdana.ttf". It works in both Eclipse and the runnable JAR.

Now what intrigues me is that in this case the first slash is needed

 ImageIcon loadIcon = new ImageIcon(getClass().getResource("/examples/resources/load.gif")); 

UPDATE 2 : After disappointment, why this method does not work.

 InputStream fis = this.getClass().getResourceAsStream("/examples/resources/verdana.ttf"); 

I removed the entire class from Eclipse and now the BOTH methods work in the Eclipse and runanble JAR - as it should be.

 InputStream fis = this.getClass().getResourceAsStream("/examples/resources/verdana.ttf"); 

or

 InputStream fis = this.getClass().getClassLoader().getResourceAsStream("examples/resources/verdana.ttf"); 
0
java eclipse inputstream jar fileinputstream
May 25 '14 at 10:03
source share
2 answers

To answer your last concern about the slash: when using getClass() search will start from the calling class. If you are not using the first class, the file will search in examples/examples/resource (since the calling class is in examples ), which does not exist. What the forward slash does is bring the search to the root of the class path.

This works in an Eclipse project, but not when exporting to a runnable JAR. Moreover, many people think that InputStream should be preferred to FileInputStream

If you need a resource for the application and it is packed in a jar, it must be read from the URL, either through getClass().getResource() , which returns the actual URL to the resource, or getClass().getResourceAsStream() , which return a resource as a stream in the form of an InputStream obtained from a URL. You can also getClassLoader() , but here are the main differences

  • getClass() - As indicated above, the search will begin at the location of the calling class. So any package in which the class is located begins where the search begins. Similar structure

     ProjectRoot src com example MyClass.class resources resource.ttf 

    will cause the search to start from within the example dir package. Therefore, if you try to use this path resources/resource.ttf if a failure occurs because the resources dir is not in the examples directory. Using / will lead the search to the root of the class path, which is src (at least in terms of the IDE), which will be broken down into classes ). This way /resources/resource.ttf will work since src/resources/resource.ttf exists.

  • getClassLoader() - starts a search from the root of the class path, therefore src . You don't need an extra / , because resources/resource.ttf is like it exists as src/resources/resource.ttf .




In another note, when you use any form of File search, the search will be in terms of the local file system. As for your question, why using File will work in your IDE, this is because the IDE starts the program not from the jar, but from the IDE itself and uses the current working directory as the root path.

Therefore, the main thing to keep in mind is that when your file is an application resource, read it as such from the class path.

 InputStream is = getClass().getResourcAsStream("/path/to/file"); 



Further explanation of the functionality of your IDE. Your eclipse. If you go to the project in the yout file system, you will see the bin file, from the point of view of your IDE, the class path. When you compile your code, resources are copied to this path. What is where the IDE will search when you try to read and as a file, since the project is the working directory and does not use the absolute path where the search takes place

+3
May 25 '14 at 12:16
source share

Although @peeskillet provided a very succinct answer, if anyone wants to do extra reading, you can also find a very good explanation here:

Download Java Files

I mention this because there seem to be a lot of questions and confusion (including my own) about the correct way to upload a file in Java using different methods.

So, in the end, both methods work:

 // This works both within Eclipse project and in runnable JAR InputStream fis = this.getClass().getResourceAsStream("/examples/resources/verdana.ttf"); 

or

 // This works both within Eclipse project and in runnable JAR InputStream fis = this.getClass().getClassLoader().getResourceAsStream("examples/resources/verdana.ttf"); 
+1
May 25 '14 at 14:01
source share



All Articles