Eclipse Java File FileInputStream与加载字体文件时的输入流 [英] Eclipse Java File FileInputStream vs Input Stream when loading font file

查看:192
本文介绍了Eclipse Java File FileInputStream与加载字体文件时的输入流的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在浏览一些教程,并且将字体文件加载到Eclipse Java Project中有问题。我在SO上尝试了许多解决方案,最终找到一个(使用FileInputStream),这对我来说是有效的,但是当项目导出为可运行的JAR时,并不是这样。另一方面,在加载图标的另一个项目中使用相同的目录结构,所以我猜问题不在路径本身。

I am going through some tutorials and I have a problem with loading font file into Eclipse Java Project. I tried many solutions suggested here on SO, and eventually find one (using FileInputStream) which does work for me, but not when the project is exported as runnable JAR. On the other hand using same directory structure in the other project where I load icons works, so I guess the problem is not in the path itself.

这里是目录结构:

这是代码:

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();
    }
}

所以,令我困扰的是:

- 为什么这不工作(似乎找不到字体文件),因为它抛出
NullPointerException

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

也没有这个工作

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

- 为什么这在Eclipse项目中有效,但是当导出到
runnable时JAR

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

更新
原来,这将工作: / p>

UPDATE As it turned out this will work:

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

问题出在第一个斜杠 - 路径应该是examples / resources / verdana.ttf而不是/examples/resources/verdana.ttf。它在Eclipse和可运行的JAR中都有效。

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

现在,令人兴趣的是,为什么在这种情况下需要首先删除

Now, what intrigues me is why is then that first slash necessary in this case

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

更新2
沮丧为什么这种方法不't work

UPDATE 2: After being frustrated why this method doesn't work

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

我从Eclipse中删除了整个类,现在BOTH方法在Eclipse和runanble JAR中工作 - 就像它应该be。

I deleted whole class from Eclipse and now BOTH methods work within Eclipse and runanble JAR - just as it should be.

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

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


推荐答案

回答你最近关于斜杠的问题:当你使用 getClass()搜索将从调用类开始。如果您不使用第一个类,则将在 examples / examples / resource 中查找该文件(因为调用类在示例)不存在。正确的斜线是将搜索带到类路径根目录。

To answer your last concern about the slash: when you use getClass() the search will begin from the calling class. If you don't use the first class the file will be looked for in examples/examples/resource (since the calling class is in examples) which doesn't exist. What the forward slash does is bring the search to the class path root.


这在Eclipse项目中工作,但在导出为可运行JAR时不起作用,
此外,许多人建议 InputStream 应该优于 FileInputStream

如果您的应用程序需要资源并打包在jar中,则应从从URL中读取,方法是通过 getClass()。getResource()其返回一个资源的实际URL,或者 getClass()。getResourceAsStream()返回资源作为从URL获取的 InputStream 的形式的流。您也可以 getClassLoader(),但这是主要的区别

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


  • getClass() - 如上所述,搜索将从调用类的位置开始。所以无论这个课程是什么包,那就是搜索开始的地方。这样的结构

  • getClass() - As stated above, the search will begin from the location of the calling class. So whatever package the class is in, that's where the search begins. A structure like this

ProjectRoot
          src
             com
                example
                     MyClass.class
             resources
                    resource.ttf

将导致搜索从在示例包中的目录中。因此,如果您尝试使用此路径 resources / resource.ttf 如果将失败,因为资源 dir在示例目录中。使用 / 将搜索到类路径的根目录,这是 src (至少从IDE透视图 - 这将被打包成一个)。所以 /resources/resource.ttf 将工作,因为 src / resources / resource.ttf 存在。

will cause the the search to begin from inside example dir of the package. So if you try and use this path resources/resource.ttf if will fail, because there is no resources dir in the examples dir. Using the / will bring the search to the root of the class path, which is the src (at least from IDE perspective - which will get jar'ed into a classes). So /resources/resource.ttf would work, as src/resources/resource.ttf exists.

getClassLoader() - 从类路径root开始搜索,所以 src 。您不需要额外的 / ,因为 resources / resource.ttf 就像说它存在为 src / resources / resource.ttf

getClassLoader() - begins it's search from the class path root, so the src. You don't need the extra / because resources/resource.ttf is like saying it exists as src/resources/resource.ttf.

另一方面,当您使用任何形式的文件搜索时,搜索将以本地文件系统为依据。所以关于你的问题,为什么使用 File 可以在你的IDE上工作,是因为IDE启动了程序,而不是从jar中,而是从IDE本身使用当前的工作目录作为根路径。

On another note, when you use any form of a File search, the search will be in terms of the local file system. So as to your question why using File would work on your IDE, is because the IDE launches the program not from the jar, but from the IDE itself and uses the current working directory as the root path.

所以要记住的主要事情是当你的文件是应用程序资源时,从类路径读取它。

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

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






有关IDE功能的进一步说明。你是日食如果你在yout文件系统中去你的项目,你会看到一个 bin 文件,就你的IDE来说是类路径。当您编译代码时,资源将被复制到该路径中。当您尝试阅读文件时,IDE将搜索的位置,因为项目是工作目录,并使用非绝对路径,即搜索发生的地方


Further explanation about the functionality of your IDE. Yours is eclipse. If you go to you project in yout file system, you will see a bin file, in terms of your IDE is the class path. When you compile your code, the resources get copied into that path. That's where the IDE will search when you try and read as a file, as the project is the working directory, and using a non absolute path, that's where the searching happens

这篇关于Eclipse Java File FileInputStream与加载字体文件时的输入流的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆