Куда поместить файл для чтения из класса под пакетом в java?

У меня есть файл свойств, содержащий только имя файла, скажем, file=fileName.dat. Я поместил файл свойств в путь к классу и смог правильно прочитать имя файла (file.dat) из него в mainClass. Прочитав имя файла, я передал имя файла (просто имя, а не путь) другому классу в пакете, скажем, pack.myClass, чтобы прочитать этот файл. Но проблема в том, что pack.myClass не смог правильно получить путь к файлу. Я поместил файл fileName.dat внутри и снаружи пакетаpack, но не смог заставить его работать.

Может ли кто-нибудь предложить мне, куда поместить файл fileName.dat, чтобы я мог правильно его прочитать, и все приложение также было бы переносимым.

Спасибо!

Код, который я использую для чтения файла конфигурации и получения имени файла:

Properties prop = new Properties();
InputStream in = mainClass.class.getResourceAsStream("config.properties");
prop.load(in);
in.close();

myClass mc = new myClass();
mc.readTheFile(prop.getProperty("file"));
/*until this code is working good*/

Затем в myClass, который находится в пакете с именем pack, я делаю:

public void readTheFile(String filename) throws IOException {
    FileReader fileReader = new FileReader(filename); /*this couldn't get the file whether i'm putting the file inside or outside the package folder */
    /*after reading the file I've to do the BufferReader for further operation*/
    BufferedReader bufferedReader = new BufferedReader(fileReader);

person flyleaf    schedule 30.06.2012    source источник
comment
Пожалуйста, предоставьте нам код, а также систему выполнения (Java 2 SE?) и укажите пользователя приложения.   -  person Maarten Bodewes    schedule 30.06.2012
comment
@owlstead: я отредактировал свой вопрос с кодом, над которым работаю   -  person flyleaf    schedule 30.06.2012
comment
@JBNizet: я отредактировал свой вопрос с кодом, над которым работаю   -  person flyleaf    schedule 30.06.2012


Ответы (6)


Я предполагаю, что вы пытаетесь прочитать файл свойств, используя метод класса getResource. Если вы помещаете файл свойств в корень пути к классам, вы должны добавить к имени файла префикс '/', чтобы указать корень пути к классам, например, getResource("/file.dat"). Если файл свойств находится в той же папке, что и класс, для которого вы вызываете метод getResource, вам не следует использовать префикс «/».

person Deniz    schedule 30.06.2012
comment
getResourceAsStream и FileReader используют совершенно разные стратегии для поиска файла. getResourceAsStream ищет файл в пути к классам, FileReader ищет файл в пути файловой системы. Они разные, придерживайтесь только одной стратегии. - person Deniz; 30.06.2012
comment
если я использую getResourceAsStream, могу ли я передать это в BufferReader, который я делаю в следующей строке? - person flyleaf; 30.06.2012
comment
вы должны иметь возможность сделать что-то вроде нового BufferedReader (новый InputStreamReader (xxxClass.getResorceAsStream (укажите путь относительно xxxClass или корень Classpath с префиксом /)) - person Deniz; 30.06.2012

Когда вы используете относительное имя файла, такое как fileName.dat, вы запрашиваете файл с таким именем в текущем каталоге. Текущий каталог не имеет ничего общего с пакетами. Это каталог, из которого запускается JVM.

Поэтому, если вы находитесь в каталоге c:\foo\bar, когда вы запускаете свое приложение (используя java -cp ... pack.MyClass), оно будет искать файл c:\foo\bar\fileName.dat.

person JB Nizet    schedule 30.06.2012

Пытаться..

myClass mc = new myClass();
InputStream in = mc.getClass().getResourceAsStream("/pack/config.properties");

..или просто

InputStream in = mc.getClass().getResourceAsStream("config.properties"); 

.. для последней строки, если main находится в myClass Загрузчик классов, доступный в main(), часто будет загрузчиком классов начальной загрузки, в отличие от загрузчика классов, предназначенного для ресурсов приложения.

person Andrew Thompson    schedule 30.06.2012
comment
Я могу прочитать файл свойств, как я сказал, и могу передать имя файла в mc.readTheFile(). Он может получить имя файла, но мне нужно знать, что будет отличным местом для размещения файла filename.dat, чтобы readTheFle() мог прочитать файл, и весь процесс был переносимым, чтобы я мог выполнять всю работу, используя только файлы классов который автоматически найдет имя файла.dat - person flyleaf; 30.06.2012
comment
Перестаньте думать о нем как о «файле», если он находится внутри Jar приложения, это не обычный File и в него нельзя записать. Однако его может найти и прочитать URL или InputStream. - person Andrew Thompson; 30.06.2012


В большинстве случаев лучше всего искать "fileName.dat" где-нибудь в папке "user.home", которая является ссылкой системное свойство. Сначала создайте путь File из "user.home", а затем попытайтесь найти там файл. Это всего лишь предположение, поскольку вы не указываете точного пользователя приложения, но это наиболее распространенное место.

В настоящее время вы читаете из текущей папки, которая определяется

String currentDir = new File(".").getAbsolutePath();

or

System.getProperty("user.dir")
person Maarten Bodewes    schedule 30.06.2012
comment
пожалуйста, посмотрите на мой вопрос с отредактированной частью кода, над которым я работаю - person flyleaf; 30.06.2012
comment
изменил мой ответ соответственно, это все еще зависит от вашего варианта использования, если это правильно - person Maarten Bodewes; 30.06.2012

Чтобы прочитать файл даже из jar-архива:

readTheFile(String package, String filename) throws MalformedURLException, IOException
{
    String filepath = package+"/"+filename;  
    // like "pack/fileName.dat" or "fileName.dat"

    String s = (new SourceBase()).getSourceBase() + filepath;
    URL url = new URL(s);
    InputStream ins = url.openStream();
    BufferedReader rdr = new BufferedReader(new InputStreamReader(ins, "utf8"));
    do {
        s = rdr.readLine();
        if(s!= null) System.out.println(s);
    }
    while(s!=null);
    rdr.close(); 
 }

с участием

class SourceBase
{
    public String getSourceBase()
    {
    String cn = this.getClass().getName().replace('.', '/') + ".class";
    // like "packagex/SourceBase.class"

    String s = this.getClass().getResource('/' + cn).toExternalForm();
    // like "file:/javadir/Projects/projectX/build/classes/packagex/SourceBase.class"
    // or "jar:file:/opt/java/PROJECTS/testProject/dist/
    //                testProject.jar!/px/SourceBase.class"

    return s.substring(0, s.lastIndexOf(cn));
    // like "file:/javadir/Projects/projectX/build/classes/"
    // or "jar:file:/opt/java/PROJECTS/testProject/dist/testProject.jar!/"
    }
}
person Michael Besteck    schedule 30.06.2012