java - Jar 文件未正确运行且资源未加载
问题描述
我的 Jar 文件运行不正确时遇到了一些严重问题。我的项目在 Eclipse 中运行良好,但在导出时它根本不起作用。我遇到了与此类似的问题:Runnable JARs missing Images/Files (Resources)和这个Runnable 导出的 JAR 在退出 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 类有什么问题,但也许我错过了一个细节。运行程序时什么都没有显示,只有窗口。
解决方案
您需要提供 JAR 文件可以访问的地图资源。最简单的方法是在 Eclipse 中构建 JAR 文件时将它们包含在 JAR 文件中。JAR 中的目录结构可以是任何你想要的。没有规定说“res/”必须在“map/”之前。您定义目录结构,因为您的代码是访问它的对象。
您链接的第一个问题建议使用Class.getResource("/images/yourImageName.extension");
. 正如您从文档中看到的,这将返回一个URI
对象。在您的情况下,您可能需要密切相关Class.getResourceAsStream("/images/yourImageName.extension");
的返回 aInputStream
然后您可以将其传递给BufferedReader
并且读取文件的其余逻辑可以相同。
推荐阅读
- swift - 仅针对 Objective-C 导出 Swift var
- javascript - Angular:对象不是 ApiService.saveData() 中的函数
- java - CalendarView 突出显示颜色的问题
- python - 我可以使用哪种算法来确定导致当前状态的一系列动作?
- arrays - 在 MATLAB 中实现两个数组的减法和除法方程
- c# - 如何有效地将 bool 转换为 int?
- google-cloud-platform - 我们可以使用 Cloud Data Fusion 执行 python 脚本吗
- javascript - JavaScript中的两个数组内连接
- ruby-on-rails - 使用 RSpec double 进行 Rails 测试:ActiveRecord::AssociationTypeMismatch:
- maven - 如何将依赖项从本地 gradle 缓存复制到 Windows 计算机上的本地 maven 存储库?