Jar文件无法正常运行,资源无法加载

时间:2018-06-25 15:31:38

标签: java eclipse jar jframe embedded-resource

我的Jar文件无法正常运行时遇到了一些严重的麻烦。我的项目在Eclipse中工作正常,但是在导出时根本无法工作。我有一个与此类似的问题:Runnable JARs missing Images/Files (Resources),几乎与此Runnable exported JAR not running as it should when out of Eclipse

完全一样的问题

我在这里使用了一些方法,但没有一个起作用,唯一的方法是告诉我在命令提示符下运行jar文件以查看是否存在错误。而且我想我可能将其范围缩小到了我的资源文件夹。它不在罐子本身中,而是包含在其中。有没有什么办法解决这一问题?因为这可能是问题所在。另一件事是,该程序是一个游戏,我设计地图的方式必须从“ res / maps / map.txt”中加载。出于某种原因,在学习如何做时没有对我进行解释,“ res /”必须在贴图之前,但是当我加载纹理时,它是一个不同的故事,因此也许我的知识来源并不那么聪明。供参考,这里是加载地图和图像的代码。

图像(根据Cmd Prompt可以正常工作):

package com.mthomps.engine.gfx;

import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;

public class ImageLoader {

public static BufferedImage loadImg(String path){

    try {
        return ImageIO.read(ImageLoader.class.getResource(path));
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        System.exit(1);
    }
    return null;
}

}

实用程序(读取地图的txt文件):

package com.mthomps.engine.utils;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class Utils {

public static String loadFileAsString(String path){
    StringBuilder builder = new StringBuilder();

    try{
        BufferedReader br = new BufferedReader(new FileReader(path));
        String line;
        while((line = br.readLine()) != null)
            builder.append(line + "\n");
        br.close();
    }catch(IOException e){
        e.printStackTrace();
    }

    return builder.toString();

}

public static int parseInt(String number){
    try{
        return Integer.parseInt(number);
    }catch(NumberFormatException e){
        e.printStackTrace();
        return 0;
    }
}

}

地图:

package com.mthomps.engine.main.map;

import java.awt.Graphics;

import com.mthomps.game.tiles.Tile;
import com.mthomps.engine.main.Handler;
import com.mthomps.enigne.utils.Utils;

public class Map {

private Handler handler;
private int width, height;
private int spawnX, spawnY;
private int[][] tiles;

public Map(Handler handler, String path){
    this.handler = handler;
    loadMap(path);
}

public void tick(){

}

public void render(Graphics g){
    int xStart = (int) Math.max(0, handler.getGameCamera().getxOffset() / Tile.TILEWIDTH);
    int xEnd = (int) Math.min(width, (handler.getGameCamera().getxOffset() + handler.getWidth()) / Tile.TILEWIDTH + 1);
    int yStart = (int) Math.max(0, handler.getGameCamera().getyOffset() / Tile.TILEHEIGHT);
    int yEnd = (int) Math.min(height, (handler.getGameCamera().getyOffset() + handler.getHeight()) / Tile.TILEHEIGHT + 1);

    for(int y = yStart; y < yEnd; y++){
        for(int x = xStart; x < xEnd; x++){
            getTile(x, y).render(g, (int) (x * Tile.TILEWIDTH - handler.getGameCamera().getxOffset()), (int) (y * Tile.TILEHEIGHT - handler.getGameCamera().getyOffset()));
        }
    }
}

public Tile getTile(int x, int y){
    if(x < 0 || y < 0 || x >= width || y >= height)
        return Tile.devWhite;

    Tile t = Tile.tiles[tiles[x][y]];
    if(t == null)
        return Tile.devWhite;
    return t;
}

private void loadMap(String path){
    String file = Utils.loadFileAsString(path);
    String[] tokens = file.split("\\s+");
    width = Utils.parseInt(tokens[0]);
    height = Utils.parseInt(tokens[1]);
    spawnX = Utils.parseInt(tokens[2]);
    spawnY = Utils.parseInt(tokens[3]);

    tiles = new int[width][height];
    for(int y = 0; y < height; y++){
        for(int x = 0; x < width; x++){
            tiles[x][y] = Utils.parseInt(tokens[(x + y * width) + 4]);
        }
    }
}

}

GameState(加载地图的位置。出于某些奇怪的原因,需要“ res /”):

package com.mthomps.game.states;

import java.awt.Color;
import java.awt.Graphics;

import com.mthomps.game.entity.mob.Player;
import com.mthomps.engine.main.Handler;
import com.mthomps.engine.main.map.Map;



public class GameState extends State{

private Player player;
private Map maze;

public GameState(Handler handler){
    super(handler);
    player = new Player(handler, 256, 256);
    maze = new Map(handler, "res/maps/maze/maze.txt");
    handler.setMap(maze);

}

@Override
public void tick() {
    maze.tick();
    player.tick();

}

@Override
public void render(Graphics g) {
    maze.render(g);
    player.render(g);

}

    }

就像我说的那样,该代码仅供参考,我觉得我需要jar中的“ res”文件夹,而不仅仅是它的内容。如果有任何方法可以执行此操作,或者代码中有任何错误,请告诉我。命令提示符没有说ImageLoader类有什么问题,但是也许我错过了一个细节。当我运行程序时,什么都没有显示,只有窗口。

3 个答案:

答案 0 :(得分:0)

您需要提供地图资源,以便您的JAR文件可以访问它们。最简单的方法是在Eclipse中构建文件时将它们包括在JAR文件中。 JAR内部的目录结构可以是您想要的任何内容。没有规则说“ res /”必须在“ map /”之前。您定义目录结构是因为您的代码可以访问它。

您链接的第一个问题建议使用Class.getResource("/images/yourImageName.extension");。从文档中可以看到,这将返回一个URI对象。在您的情况下,您可能需要紧密相关的Class.getResourceAsStream("/images/yourImageName.extension");并返回一个InputStream,然后可以将其传递给BufferedReader,其余读取文件的逻辑可以相同。 / p>

答案 1 :(得分:0)

BufferedReader br = new BufferedReader(new FileReader(path));

不能作为File来访问!

通过URL获取一个getResource(..),并改用它。

E.G。

URL url = getClass().getResource("/path/to/resource.res");
InputStream is = url.openStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));

答案 2 :(得分:0)

Eclipse中的Runnable Jar文件导出将把bin/文件夹中的所有内容复制到jar归档文件中。因此,您的目标是在编译后将已编译的源代码和资源保存在bin/文件夹中。

在编译期间,Eclipse首先编译源文件夹中的所有类,然后将它们复制到bin/文件夹中。然后Eclipse只是将所有非类文件从您的源文件夹复制到bin/文件夹中。

如果要将所有资源都放在res/文件夹内的文件夹bin/中,则必须将 res/文件夹放在源文件夹中 。您可以将其放在src/中,也可以创建一个新的源文件夹,例如resources/,其中包含您的res/文件夹。

要在运行时访问资源,建议您像使用图像加载一样使用Class::getResource(String name)。您可以在BufferedReader中的Utils::loadFileAsString(String path)初始化之前添加以下行:

path = Utils.class.getResource(path).getFile();

这会将更新为参数的相对路径更新为正确的绝对路径。 path开头的/非常重要!例如,/res/maps/map.txt有效,而res/...无效。仅将/作为第一个字符,getResource不会查找相对于当前类的包的路径,而是相对于“根”包的路径。 (Rails 3 documentation for first_or_create

如果您还有其他问题(或者仍然无法解决),请随时提问!