我的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类有什么问题,但是也许我错过了一个细节。当我运行程序时,什么都没有显示,只有窗口。
答案 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));
embedded-resource不能作为File
来访问!
通过URL
获取一个getResource(..)
,并改用它。
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
)
如果您还有其他问题(或者仍然无法解决),请随时提问!