从Java应用程序包中读写XML文件

时间:2022-02-08 12:24:16

I've got an XML file that is parsed and written in my application. From within my IDE (Eclipse) I simply address it like this:

我有一个在我的应用程序中解析和编写的XML文件。在我的IDE (Eclipse)中,我只是这样处理它:

Reading:

阅读:

private String xmlFile = "file.xml";

and then I build the document:

然后我建立文件:

doc = sax.build(xmlFile);

Writing is done like this:

写作是这样的:

writer = new FileWriter("file.xml");

Runs great so far, but after bundling my application, the file is no longer accessible. What exactly do I have to do to make it accessible from within an application bundle? I'm absolutely not familiar with the classpath or whatever I need for that, so please go easy on me!

到目前为止运行良好,但是在打包了我的应用程序之后,该文件不再可访问。我需要做什么才能使它从应用程序包中访问?我绝对不熟悉类路径或我需要的任何东西,所以请放心!

Thank you very much!

非常感谢!

7 个解决方案

#1


2  

To read the file you can create a BufferedReader as follows:

要读取文件,可以创建BufferedReader,如下所示:

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
    getClass().getResourceAsStream("file.xml")));

You can write the file as before, but keep track of where it's written to - then you can re-read the file from there if necessary.

您可以像以前一样编写文件,但是要跟踪它被写到的位置——然后如果需要,您可以从那里重新读取文件。

#2


2  

Peter,

彼得,

I've run into a similar issue, and since you're new to this, I'll start with this: When you package a file in a jar, it is compressed, and so accessing it like you have in your original code will not work, as we cannot read the files compressed in the jar. Instead, you need to ask Java to pull out this resource as a stream (as many others have helpfully pointed out) which Java does know how to supply to you.

我遇到类似的问题,因为你是新手,我首先:当你包一个jar文件,压缩,所以访问它喜欢你有在你的原始代码不工作,当我们不能读文件压缩在罐子里。相反,您需要让Java将这个资源作为一个流(正如许多其他人已经指出的那样)提取出来,Java确实知道如何为您提供这些资源。

Now, actually outputting the file from there IS a pain. Here's some code I wrote a while back to do this, which is of course from some other source I found. Fill in the exceptions as needed! =)

现在,实际上从那里输出文件是很痛苦的。这是我之前写的一些代码,当然是我从其他来源找到的。根据需要填写异常!=)

        InputStream in = null;
        in = this.getClass().getResourceAsStream("/main.cc");

        File outputFile = createMainOutputFile();
        OutputStream out = null;
        try {
            out = new FileOutputStream(outputFile);
        } catch (FileNotFoundException e) {
            System.out.println(outputFile + " was not found!");
            e.printStackTrace();
        }

        // Transfer bytes from in to out 
        byte[] buf = new byte[1024]; 
        int len; 
        try {
            while ((len = in.read(buf)) > 0) { 
                out.write(buf, 0, len); 
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
        try {
            in.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
        try {
            out.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 

We actually have to output the file piece by piece, sad I know, I really wish what you were hoping to do worked! It'd make life a lot easier. The only thing that may be confusing there is the createMainOutputFile() call, so here's the code for that too...

我们实际上要把文件一块一块一块地输出,可惜我知道,我真希望你希望做的事情能成功!这会让生活更轻松。惟一可能让人感到困惑的是createMainOutputFile()调用,因此这里也有相应的代码……

private File createMainOutputFile() {
    File directoryPath = new File(mainOutputFolder);
    directoryPath.mkdirs();
    File newFile = new File (mainOutputFolder + "main.cc");
    try {
        newFile.createNewFile();
    } catch (IOException e) {
        System.out.println("failed To create new file.");
        e.printStackTrace();
    }
    return newFile;
}

Best of Luck!

最好的运气!

Edit: Now that I notice you're actually parsing it with an XML parser, I'll point out to you that if you're using a SAX parser (at least apache's) you'll find that it will actually accept an inputStream just like it would a file:

编辑:现在我注意到您实际上正在使用XML解析器解析它,我将向您指出,如果您使用SAX解析器(至少是apache的),您将发现它实际上将接受inputStream,就像它接受一个文件一样:

DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = null;
        try {
            docBuilder = docFactory.newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            //Here we supply the inputStream instead of the file...
            doc = docBuilder.parse(inputStream);
        } catch (SAXException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        Node xmlRoot = doc.getFirstChild();

#3


1  

Imagine that you have a package named myXmlDir put your file.xml file under this package (a directory actually)

假设有一个名为myXmlDir的包放置文件。这个包下的xml文件(实际上是一个目录)

Notice that this package is packaged with you class inside the jar and can be accessed by the classLoader.

注意,这个包与jar中的类打包在一起,可以被classLoader访问。

See this code that return an input stream:

请参阅返回输入流的代码:

return SomeClass.class.getClassLoader().getResource("myXmlDir/file.xml").openStream();

you can also, instead of openStream(), activate the getFile() function

您还可以激活getFile()函数,而不是openStream()函数

#4


1  

I can't comment, so my answer is referring to LES2's answer. The trick is that your file.xml must be on the classpath if you want to use a classloader.

我不能评论,所以我的答案是指LES2的回答。关键是你的文件。如果希望使用类加载程序,则必须将xml放在类路径中。

Usually, it will be included in the classpath if it is in your JAR file. to check if it's there, open the jar with 7zip or any other zip program. If the file is not inside the jar, you must ship it along with the jar and add it to the classpath manually when starting the app.

通常,如果它在JAR文件中,它将包含在类路径中。要检查它是否在那里,用7zip或任何其他zip程序打开jar。如果文件不在jar中,则必须将其与jar一起发送,并在启动应用程序时手动将其添加到类路径。

lets say file.xml and the jar are in the same directory. then

假设文件。xml和jar在同一个目录中。然后

java -cp .:myjar.jar com.example.Main

should help.

应该帮助。

#5


1  

Use the file as a property. You can than do with it whatever you want. To access it use

将文件用作属性。你可以做任何你想做的事。访问它的使用

Class.getResourceAsStream()

or an equivalent method. Check out this link for a few hints: http://www.javaworld.com/javaworld/javaqa/2003-08/01-qa-0808-property.html?page=2

或一个等价的方法。查看这个链接可以得到一些提示:http://www.javaworld.com/javaworld/javaqa/2003-08/01-qa-0808-property.html?page=2

Edit:
I'm sorry to say that my suggestion isn't as good as I thought it was. I felt that I had done something as you want to once but I looked at the app and all I did was read the files. I also did a bit of googleing and found this forum entry which is a bit old but considering the lacking progress on Sun's part I reckon it's essence is still valid: http://lists.apple.com/archives/Java-dev/2003/Feb/msg00876.html

编辑:很抱歉,我的建议不如我想象的那么好。我觉得我做了一件你想做的事情,但是我看了一下应用,我所做的就是阅读文件。我也做了一点google搜索,发现这个论坛入口有点旧,但是考虑到Sun在这方面的不足,我认为它的本质仍然是有效的:http://lists.apple.com/archives/Java-dev/2003/Feb/msg00876.html

Basically, if you want to write something, either require the user to extract the jar before launching or (my suggestion) create a directory in the same directory as the jar is in and write your file to that directory. If you really needed to, you could even build another jar with that file and all the files of the original jar, which would of course leave you with two archives.

基本上,如果您想要编写一些东西,要么需要用户在启动之前提取jar,或者(我的建议)在jar所在的目录中创建一个目录,然后将文件写入该目录。如果您确实需要,您甚至可以用该文件和原始jar的所有文件构建另一个jar,当然,这将留给您两个存档。

Sorry for bringing your hopes up.

对不起,把你的希望说出来了。

#6


1  

Best option to this common problem: Absolute path for the location outside the jar/war.

这个常见问题的最佳选择:jar/war之外的位置的绝对路径。

The the app itself can be deployed anywhere, but the host should have a common file area such as "/common/files/someApplication"

应用程序本身可以部署在任何地方,但是主机应该有一个公共文件区域,比如“/common/files/someApplication”

Better yet is to have a configuration to specify (during build or at runtime) which path to use. E.g. dev build would use "/dev/myprojects/someApplication"

更好的是有一个配置来指定(在构建期间或运行时)使用哪个路径。例如,mydev build将使用“/dev/ projects/someApplication”

Not as good solution: Deploy as exploded war file. Read and write is not a problem, but now you've cause a deployment dependency.

不是很好的解决方案:部署为爆炸的war文件。读写不是问题,但是现在您已经导致了部署依赖。

#7


0  

your input should be the absolute or relative path of the file....

您的输入应该是文件的绝对或相对路径....

#1


2  

To read the file you can create a BufferedReader as follows:

要读取文件,可以创建BufferedReader,如下所示:

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
    getClass().getResourceAsStream("file.xml")));

You can write the file as before, but keep track of where it's written to - then you can re-read the file from there if necessary.

您可以像以前一样编写文件,但是要跟踪它被写到的位置——然后如果需要,您可以从那里重新读取文件。

#2


2  

Peter,

彼得,

I've run into a similar issue, and since you're new to this, I'll start with this: When you package a file in a jar, it is compressed, and so accessing it like you have in your original code will not work, as we cannot read the files compressed in the jar. Instead, you need to ask Java to pull out this resource as a stream (as many others have helpfully pointed out) which Java does know how to supply to you.

我遇到类似的问题,因为你是新手,我首先:当你包一个jar文件,压缩,所以访问它喜欢你有在你的原始代码不工作,当我们不能读文件压缩在罐子里。相反,您需要让Java将这个资源作为一个流(正如许多其他人已经指出的那样)提取出来,Java确实知道如何为您提供这些资源。

Now, actually outputting the file from there IS a pain. Here's some code I wrote a while back to do this, which is of course from some other source I found. Fill in the exceptions as needed! =)

现在,实际上从那里输出文件是很痛苦的。这是我之前写的一些代码,当然是我从其他来源找到的。根据需要填写异常!=)

        InputStream in = null;
        in = this.getClass().getResourceAsStream("/main.cc");

        File outputFile = createMainOutputFile();
        OutputStream out = null;
        try {
            out = new FileOutputStream(outputFile);
        } catch (FileNotFoundException e) {
            System.out.println(outputFile + " was not found!");
            e.printStackTrace();
        }

        // Transfer bytes from in to out 
        byte[] buf = new byte[1024]; 
        int len; 
        try {
            while ((len = in.read(buf)) > 0) { 
                out.write(buf, 0, len); 
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
        try {
            in.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
        try {
            out.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 

We actually have to output the file piece by piece, sad I know, I really wish what you were hoping to do worked! It'd make life a lot easier. The only thing that may be confusing there is the createMainOutputFile() call, so here's the code for that too...

我们实际上要把文件一块一块一块地输出,可惜我知道,我真希望你希望做的事情能成功!这会让生活更轻松。惟一可能让人感到困惑的是createMainOutputFile()调用,因此这里也有相应的代码……

private File createMainOutputFile() {
    File directoryPath = new File(mainOutputFolder);
    directoryPath.mkdirs();
    File newFile = new File (mainOutputFolder + "main.cc");
    try {
        newFile.createNewFile();
    } catch (IOException e) {
        System.out.println("failed To create new file.");
        e.printStackTrace();
    }
    return newFile;
}

Best of Luck!

最好的运气!

Edit: Now that I notice you're actually parsing it with an XML parser, I'll point out to you that if you're using a SAX parser (at least apache's) you'll find that it will actually accept an inputStream just like it would a file:

编辑:现在我注意到您实际上正在使用XML解析器解析它,我将向您指出,如果您使用SAX解析器(至少是apache的),您将发现它实际上将接受inputStream,就像它接受一个文件一样:

DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = null;
        try {
            docBuilder = docFactory.newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            //Here we supply the inputStream instead of the file...
            doc = docBuilder.parse(inputStream);
        } catch (SAXException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        Node xmlRoot = doc.getFirstChild();

#3


1  

Imagine that you have a package named myXmlDir put your file.xml file under this package (a directory actually)

假设有一个名为myXmlDir的包放置文件。这个包下的xml文件(实际上是一个目录)

Notice that this package is packaged with you class inside the jar and can be accessed by the classLoader.

注意,这个包与jar中的类打包在一起,可以被classLoader访问。

See this code that return an input stream:

请参阅返回输入流的代码:

return SomeClass.class.getClassLoader().getResource("myXmlDir/file.xml").openStream();

you can also, instead of openStream(), activate the getFile() function

您还可以激活getFile()函数,而不是openStream()函数

#4


1  

I can't comment, so my answer is referring to LES2's answer. The trick is that your file.xml must be on the classpath if you want to use a classloader.

我不能评论,所以我的答案是指LES2的回答。关键是你的文件。如果希望使用类加载程序,则必须将xml放在类路径中。

Usually, it will be included in the classpath if it is in your JAR file. to check if it's there, open the jar with 7zip or any other zip program. If the file is not inside the jar, you must ship it along with the jar and add it to the classpath manually when starting the app.

通常,如果它在JAR文件中,它将包含在类路径中。要检查它是否在那里,用7zip或任何其他zip程序打开jar。如果文件不在jar中,则必须将其与jar一起发送,并在启动应用程序时手动将其添加到类路径。

lets say file.xml and the jar are in the same directory. then

假设文件。xml和jar在同一个目录中。然后

java -cp .:myjar.jar com.example.Main

should help.

应该帮助。

#5


1  

Use the file as a property. You can than do with it whatever you want. To access it use

将文件用作属性。你可以做任何你想做的事。访问它的使用

Class.getResourceAsStream()

or an equivalent method. Check out this link for a few hints: http://www.javaworld.com/javaworld/javaqa/2003-08/01-qa-0808-property.html?page=2

或一个等价的方法。查看这个链接可以得到一些提示:http://www.javaworld.com/javaworld/javaqa/2003-08/01-qa-0808-property.html?page=2

Edit:
I'm sorry to say that my suggestion isn't as good as I thought it was. I felt that I had done something as you want to once but I looked at the app and all I did was read the files. I also did a bit of googleing and found this forum entry which is a bit old but considering the lacking progress on Sun's part I reckon it's essence is still valid: http://lists.apple.com/archives/Java-dev/2003/Feb/msg00876.html

编辑:很抱歉,我的建议不如我想象的那么好。我觉得我做了一件你想做的事情,但是我看了一下应用,我所做的就是阅读文件。我也做了一点google搜索,发现这个论坛入口有点旧,但是考虑到Sun在这方面的不足,我认为它的本质仍然是有效的:http://lists.apple.com/archives/Java-dev/2003/Feb/msg00876.html

Basically, if you want to write something, either require the user to extract the jar before launching or (my suggestion) create a directory in the same directory as the jar is in and write your file to that directory. If you really needed to, you could even build another jar with that file and all the files of the original jar, which would of course leave you with two archives.

基本上,如果您想要编写一些东西,要么需要用户在启动之前提取jar,或者(我的建议)在jar所在的目录中创建一个目录,然后将文件写入该目录。如果您确实需要,您甚至可以用该文件和原始jar的所有文件构建另一个jar,当然,这将留给您两个存档。

Sorry for bringing your hopes up.

对不起,把你的希望说出来了。

#6


1  

Best option to this common problem: Absolute path for the location outside the jar/war.

这个常见问题的最佳选择:jar/war之外的位置的绝对路径。

The the app itself can be deployed anywhere, but the host should have a common file area such as "/common/files/someApplication"

应用程序本身可以部署在任何地方,但是主机应该有一个公共文件区域,比如“/common/files/someApplication”

Better yet is to have a configuration to specify (during build or at runtime) which path to use. E.g. dev build would use "/dev/myprojects/someApplication"

更好的是有一个配置来指定(在构建期间或运行时)使用哪个路径。例如,mydev build将使用“/dev/ projects/someApplication”

Not as good solution: Deploy as exploded war file. Read and write is not a problem, but now you've cause a deployment dependency.

不是很好的解决方案:部署为爆炸的war文件。读写不是问题,但是现在您已经导致了部署依赖。

#7


0  

your input should be the absolute or relative path of the file....

您的输入应该是文件的绝对或相对路径....