FileOutputStream
просто открывает локальный файл. Он должен быть абсолютным (/home/user/...
или c:\temp\...
) или относительным относительно текущего каталога. В Windows, например, это каталог, содержащий JAR по умолчанию.
Если вы хотели упаковать файл classes
в JAR, вам следует использовать getResourceAsStream
, как упоминал @guleryuz. Путь должен быть либо абсолютным, начиная с корня CLASSPATH (то есть корня файла JAR), например "/assets/classes"
, либо (лучше) относительно пакета вызывающего класса.
Говоря о классах, я бы настоятельно не рекомендовал использовать getClass()
, потому что это полиморфный метод. Есть два способа получить класс: вызвав getClass()
для объекта или обратившись к статическому class
«полю». Если у вас есть экземпляр MyClass
с именем myObject
, то myObject.getClass()
и MyClass.class
по сути одно и то же. Но! Если ваш класс переопределен классом из другого пакета, скажем, TheirClass
, то для экземпляра TheirClass
getClass()
вернет TheirClass.class
, даже если вы вызываете getClass()
из своего кода. Таким образом, если ваш класс не объявлен как final
, использовать getClass().getResource...
всегда плохая идея, потому что вы никогда не знаете, когда кто-то переопределит ваш класс. И вы не должны знать или даже заботиться!
Учитывая все это, скажем, у вас есть класс с именем MyClass
в пакете с именем my.package
. JAR может иметь следующую структуру:
my/
package/
MyClass.class
assets/
classes
Тогда вызов MyClass.class.getResourceAsStream("assets/classes")
должен помочь. В качестве альтернативы это может быть MyClass.class.getResourceAsStream("/my/package/assets/classes")
. Обратите внимание, что абсолютный путь не начинается с каталога проекта, где у вас может быть src
или src/main
или что-то другое, что использует ваша система сборки. Он относится к корню ПУТИ К КЛАССУ (верно, абсолютный путь относительный к корню ПУТИ К КЛАССУ, даже если это звучит странно). То есть он начинается с каталога, где находятся ваши пакеты.
И последнее, но не менее важное: если вы используете систему сборки, подобную Maven (например, Maven или Gradle), то исходные коды Java помещаются в src/main/java
, а файлы ресурсов, такие как ваш файл, — в src/main/resources
. Они оказываются в одном и том же месте в вашем JAR-файле. То есть src/main/java/package/MyClass.java
компилируется в package/MyClass.class
, а src/main/resources/package/assets/classes
переходит в package/assets/classes
. Но для того, чтобы система сборки поняла, что делать с вашими файлами, вы должны поместить их в правильные каталоги: *.java
перейти в java
, ресурсы — в resources
.
Итак, принимая во внимание соглашения, подобные Maven, структура проекта должна быть
src/
main/
java/
my/
package/
MyClass.java
src/
main/
resources/
my/
package/
assets/
classes
Учитывая такую структуру, вы получите JAR-файл со структурой, подобной приведенной выше. Выглядит немного безумно, но очень полезно, когда вы освоитесь.
Если вы не используете систему сборки, подобную Maven, то я понятия не имею, как настроить Eclipse. У разных IDE могут быть свои соглашения, и я всегда использовал Maven с Eclipse. Некоторым IDE нравится, например, помещать исходные коды и ресурсы Java в одно и то же дерево каталогов.
person
Sergei Tachenov
schedule
21.08.2016
java
является частью JRE. Я также не понимаю, какое это имеет отношение кFileInputStream
, который является просто старой программой для чтения файлов, которая работает так же, как и любая другая функция открытия файлов. - person Sergei Tachenov   schedule 21.08.2016ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("assets\\classes".replace("\\", "/")));
должен бытьObjectInputStream inputStream = new ObjectInputStream(getClass().getResourceAsStream("/assets/classes"));
в коде, чтобы работать в jar-файле, как предполагалось. - person guleryuz   schedule 21.08.2016ObjectInputStream inputStream = new ObjectInputStream(getClass().getResourceAsStream("/assets/classes"));
однако выдает NullPointException, когда я развлекаюсь в Eclipse. - person Mark Cramer   schedule 21.08.2016