2011-12-23 11 views
6

Bir uygulama yazıyorum (özellikle Bukkit Minecraft sunucusu için bir eklenti). Bunu yapmak, uygulamanın JAR'ından bir .properties dosyasına erişmem gerektirir. Garip bir sorunla karşılaştığım yer burası. Programımı, geliştirme bilgisayarımda test ettiğimde, iyi çalışıyor. .properties dosyası yüklenir ve her şey yolunda. Ancak, test ettiğim diğer bilgisayarda uygulamayı başlatmaya çalışıyorum ve özellikleri yüklenemedi ve InputStreamnull. İşte dosyasını yüklemek ettiği yöntemdir: Bazı alakasız kod ihmal ettikTüm bilgisayarlarda JAR'daki kaynağa erişilemiyor

public class Points { 
    private HashMap<String, MessageFormat> messages; 

    public Points() { 
     buildMessages(); 
    } 

public static void buildMessages() { 
     Properties messageProps = new Properties(); 
     InputStream in = Points.class.getResourceAsStream("resources/messages.properties"); 
     messages = new HashMap<String, MessageFormat>(); 
     Enumeration en; 
     try { 
      messageProps.load(in); 
     } catch(IOException ex) { 
      System.err.println("Couldn't read message properties file!"); 
      return; 
     } catch(NullPointerException ex) { 
      System.err.println("Couldn't read message properties file!"); 
      if(in == null) 
       System.out.println("IOStream null"); 
      return; 
     } 
     en = messageProps.propertyNames(); 
     while(en.hasMoreElements()) { 
      String key = (String)en.nextElement(); 
      String prop = messageProps.getProperty(key); 
      MessageFormat form = new MessageFormat(prop.replaceAll("&", 
       "\u00a7").replaceAll("`", "")); 
      messages.put(key, form); 
     } 
    } 
} 

ama hepsi bu özü buydu. aşağıdaki gibi JAR yapısı şöyledir: Dosya resources/messages.properties yüklenen benim PC'de

com/ 
     pvminecraft/ 
      points/ 
       Points.java <-- The class where the file is loaded 
       resources/ 
        messages.properties <-- The file being loaded 

, ancak diğer dosya üzerinde, InputStream null ve NullPointerException benim catch blok çalıştırılır. Soruna ne neden olabilir ve nasıl düzeltebilirim? Teşekkürler.

Güncelleme: Tüm yolu (/com/pvminecraft/points/resources/messages.properties) kullanarak bile, aynı sorun hala devam ediyor.

Güncelleme 2: sunucusudur org.bukkit ve org.craftbukkit şeyler

java.lang.NullPointerException 
    at java.util.Properties$LineReader.readLine(Properties.java:435) 
    at java.util.Properties.load0(Properties.java:354) 
    at java.util.Properties.load(Properties.java:342) 
    at com.pvminecraft.points.Points.buildMessages(Unknown Source) 
    at com.pvminecraft.points.Points.onEnable(Unknown Source) 
    at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:188) 
    at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:968) 
    at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:280) 
    at org.bukkit.craftbukkit.CraftServer.loadPlugin(CraftServer.java:186) 
    at org.bukkit.craftbukkit.CraftServer.enablePlugins(CraftServer.java:169) 
    at org.bukkit.craftbukkit.CraftServer.reload(CraftServer.java:436) 
    at org.bukkit.Bukkit.reload(Bukkit.java:187) 
    at org.bukkit.command.defaults.ReloadCommand.execute(ReloadCommand.java:22) 
    at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:165) 
    at org.bukkit.craftbukkit.CraftServer.dispatchCommand(CraftServer.java:378) 
    at org.bukkit.craftbukkit.CraftServer.dispatchCommand(CraftServer.java:374) 
    at net.minecraft.server.MinecraftServer.b(MinecraftServer.java:564) 
    at net.minecraft.server.MinecraftServer.w(MinecraftServer.java:541) 
    at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:425) 
    at net.minecraft.server.ThreadServerApplication.run(SourceFile:457) 

Tümü: Burada tam yığın-izidir. .properties dosyası, Points'un onEnable yöntemiyle çağrılan buildMessages yönteminde yüklenir.

Güncelleştirme 3: Arch Linux'un yeni yüklemesinde, ileti özellikleri dosyası doğru şekilde yüklendi ve her şey yolunda. Uzak sunucu Ubuntu Linux ve benim dev PC'm Arch.

Güncelleştirme 4: Tamam, bu bir çözüm türüdür. Yerelleştirilmiş bir sorun gibi görünüyor. Bunu söylüyorum çünkü iki bilgisayara daha erişmeyi başardım ve program her ikisinde de doğru çalışıyor. Bu rahatsız edici olsa da, bu benim kodumda yanlış bir şey gibi görünmüyor ya da betikler oluşturmuyor. Hala neyin yanlış olduğunu bilmek istiyorum, ama artık basmıyor. Buna bakmaya devam edeceğim. Herkese teşekkürler.

+0

"Kaynaklar" dizini sınıf yolunda değil - bkz. Tom'un yanıtı. Ancak "com/pvminecraft/points/resources" dizini. Geliştirme ortamınızı kontrol edin - sınıf yolunda bulunan bir yere oturmuş özellik dosyalarının bir kopyasını ya da komik bir şekilde ayarladığınıza inanıyorum. – Paul

+0

Lütfen yığın yığınının tamamını gönderin. – Paul

+0

Burada satır numarası nedir: 'com.pvminecraft.points.Points.buildMessages (Bilinmeyen Kaynak)'. JDK sürümünüz nedir? – Kowser

cevap

2

Farklı Java sınıf yükleyicileri ve bunların arama yolları arasında küçük incelikler gibi görünüyor. Bu ayrıntılara girmeden önce; Neden bu kavanoz dosyasındaki tam yolu denemiyorsunuz? (böyle yani şey:

Points.class.getResourceAsStream("com/pvminecraft/points/resources/messages.properties"); 

)

+3

Tam yollar "/" ile başlar –

+0

Bu değişiklikle aynı hikaye. Bilgisayarım üzerinde çalışıyor, ama diğeri değil. –

+0

@MichaelSmith - Bilgisayarınızda nasıl çalışıyorsunuz? – Paul

2

Point.class.getClassLoader().getResourceAsStream("com/pvminecraft/points/resources/messages.properties");

ilk '/' bulunmadan deneyin ve bir JVM yerde çalışmalıdır.

Bu işe yaramadıysa, lütfen dosyayı JAR dosyasının KÖKÜ'ne getirip tekrar deneyin.

public static byte[] getFile(File zip, String fileName) throws FileNotFoundException, ZipException, IOException { 
     String filename = fileName; 

     if (!zip.exists()) { 
      throw new FileNotFoundException(zip.getName()); 
     } 
     while (filename.charAt(0) == '/' || filename.charAt(0) == '\\') { 
      filename = filename.substring(1); 
     } 

     if (filename.contains("\\")) { 
      filename = filename.replace("\\", "/"); 
     } 

     ZipFile zipFile = new ZipFile(zip); 
     Enumeration entries = zipFile.entries(); 

     ByteArrayOutputStream output; 
     byte[] result = null; 

     while (entries.hasMoreElements()) { 
      ZipEntry entry = (ZipEntry) entries.nextElement(); 

      if (entry.getName().equalsIgnoreCase(filename)) { 
       FileUtils.copyInputStream(zipFile.getInputStream(entry), output = new ByteArrayOutputStream()); 
       result = output.toByteArray(); 
       zipFile.close(); 
       output.close(); 
       return result; 
      } 
     } 

     zipFile.close(); 
     throw new FileNotFoundException(filename); 
    } 

Bu

public static void copyInputStream(InputStream in, OutputStream out) throws IOException { 
    byte[] buffer = new byte[1024]; 
    int len; 
    while (((len = in.read(buffer)) >= 0)) { 
     out.write(buffer, 0, len); 
    } 
    out.flush(); 
} 

çalışan kavanoz

String currentJar = ""; 
             // Get current jar path. Since user may rename this file, we need to do this way 
       try { 
        currentJar = (Points.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()); 
        if (currentJar.startsWith("/")) currentJar = currentJar.substring(1); 
        } catch (URISyntaxException ex) { 
        } 

birinci yolunu alın gerekir: hala çalışmıyorsa

, bu yöntemi kullanmayı deneyin '/' Gerçekten neden göründüğünü hatırlamıyorum, ama öyle, yani onu kaldırmalısınız:

Sen çalışmak için bayt dizisi olacak:

Nihayet yöntemini çağırın. Sadece bir ByteArrayInputStream olarak koyun ve sorunlarınız çözülmelidir.


Bu kod oluşturduğum bir util sınıfının parçasıdır) (yöntem gereksiz bir bayt dizisi okumak neden olduğunu, ama ofc, sen Properties.load doğrudan o InputStream kullanacak şekilde değiştirebilir . Posta util sınıfına sınıfına util fileutils için

http://all-inhonmodman.svn.sourceforge.net/viewvc/all-inhonmodman/ModManager/src/modmanager/utility/ZIP.java?revision=292&content-type=text%2Fplain

Bağlantı için

Bağlantı

Ayrıca emin olmak isteyebilirsiniz http://all-inhonmodman.svn.sourceforge.net/viewvc/all-inhonmodman/ModManager/src/modmanager/utility/FileUtils.java?revision=294&content-type=text%2Fplain

0

eğer yapı komut dosyası (Ant, Maven) veya IDE'niz, o iletilerden (bu kodun .class değil) çıkan JAR dosyasından kaldırılmasını/yerini kaldırmadı. JAR içeriğinizi 7zip veya WinZip gibi araçlarla kontrol edebilirsiniz.

0

Sınıfınızın aynı paketinde bulunan bir kaynağı yüklediğinizden (Point), yüklemek için mutlak yolu kullanmanız gerekmez.

Sunucu, eklentileri yüklemek için herhangi bir önbellek kullanıyor mu? Bunun nedeni, sınıf yolunda bulunan eklenti kavanozun eski bir versiyonundan kaynaklanabilir. Sunucunun gerçekten jar dosyasının doğru sürümünü yüklediğini doğrulamak için, eklentinin bir sürümünü konsola kaydeden bir dosyayı dağıtmayı ve bir şey olup olmadığını (mesajın günlüğe kaydedilip kaydedilmediğini) deneyebilirsiniz.

Ayrıca, sınıf yükleyici hiyerarşisinin sunucuda nasıl düzenlendiğini bilmiyorum, ancak kaynağı geçerli iş parçacığı sınıf yükleyicisinden yüklemeyi deneyebilirsiniz (genellikle içeriğe bakacak olan ana üst sınıf yükleyiciyi). diğer her çocuk sınıfı yükleyici). Bunun için mutlak yolu kullanmalısın.

ClassLoader rootCL = Thread.currentThread().getContextClassLoader(); 
InputStream resource = rootCL.getResourceAsStream(
     "/com/pvminecraft/points/resources/messages.properties"); 

Kontrol bu question farklı sınıf yükleyiciler hakkında daha fazla bilgi için.