在Java中将XML文件复制到新的XML文件中写入

4
我想知道是否有可能使用Java中的XML解析器逐行读取XML文档中的每一行,然后在另一个XML文件中重新生成相同的文档?(在我的情况下,只需要复制从点X到点Y的行)。我考虑过在小试验中使用缓冲读取器和缓冲写入器,但它没有正确输出文件。以下是我在试验中所做的事情,但这不是我想要的。那么,有没有人有这方面的经验或者有任何想法或建议可以提供?谢谢您提前。

JAVA CODE

public class IPDriver 
{
    public static void main(String[] args) throws IOException
    {
        BufferedReader reader = new BufferedReader(new FileReader("C:/Documents and Settings/user/workspace/Intern Project/Proposals/Converted Proposals/Extracted Items/ProposalOne/word/document.xml"));
        BufferedWriter writer = new BufferedWriter(new FileWriter("C:/Documents and Settings/user/workspace/Intern Project/Proposals/Converted Proposals/Extracted Items/ProposalOne/word/tempdocument.xml"));

        String line = null;

        while ((line = reader.readLine()) != null)
        {
            writer.write(line);
        }

        // Close to unlock.
        reader.close();
        // Close to unlock and flush to disk.
        writer.close();
    }
}

感谢Ted Hopp提供的可工作的JAVA代码

public class IPDriver 
    {
        public static void main(String[] args) throws IOException
        {
            BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("C:/Documents and Settings/user/workspace/Intern Project/Proposals/Converted Proposals/Extracted Items/ProposalOne/word/document.xml"), "UTF-8"));
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("C:/Documents and Settings/user/workspace/Intern Project/Proposals/Converted Proposals/Extracted Items/ProposalOne/word/tempdocument.xml"), "UTF-8"));

            String line = null;

            while ((line = reader.readLine()) != null)
            {
                writer.write(line);
            }

            // Close to unlock.
            reader.close();
            // Close to unlock and flush to disk.
            writer.close();
        }
    }

1
为什么这个不起作用?它是不是报错了或者有其他问题? - Pangolin
1
输出有什么问题吗?我猜想你想使用XML解析器来获得更好的控制和输出?我这样评论是因为你上面的示例代码根本没有使用解析器。 - Perception
基本上,在Ted的解决方案之前,我只能获取原始XML文档的1/20,然后在新文档中报告了一些样式表错误。 - This 0ne Pr0grammer
3个回答

6

如果你的代码没有正确地复制文件,我的猜测是你有一个字符编码问题。由于XML的默认编码是UTF-8,而FileReader的默认编码是你的平台的默认编码,我建议改为这样做:

BufferedReader reader = new BufferedReader(
    new InputStreamReader(
        new FileInputStream("...input file path..."),
        "UTF-8"
    )
);
BufferedWriter writer = new BufferedWriter(
    new OutputStreamWriter(
        new FileOutputStream("...output file path..."),
        "UTF-8"
    )
);

XML解析器会给你元素(或元素事件),而不是行。例如,它们无法区分空格变化的差异:
<tag attr1="val1" attr2="val2" />

对比:

<tag attr1="val1"
     attr2="val2"
     />

如果您的要求包括区分这两种情况,那么使用XML解析器方法将无法实现。


@Ted Hopp,太好了!非常感谢。但是,对于我想要做的事情,我不确定应该在我的代码中添加什么来仅抓取我想要的部分。例如,我想能够识别存储在您上面示例中的“val”实例...抓取该“行”下面的所有内容,直到找到另一个“val”实例。这可能吗? - This 0ne Pr0grammer
这取决于你对文件内容的控制程度、XML结构的复杂程度以及你所需的内容。我倾向于使用DOM解析器,对不需要的内容进行一些操作,从修改后的DOM生成XML,并接受格式丢失的结果。然而,如果文档结构足够简单,你可以使用正则表达式搜索实现自己的粗略解析。关键是要考虑所有可能会破坏代码的文档内容,然后防范它们。这并不是一项容易的任务。 - Ted Hopp
如果您需要从 XML 中获取数据,您应该使用 XML 解析器 - 这是使用 XML 的一个基本规则。唯一不需要解析的情况是进行盲拷贝。 - StaxMan
1
@Ted Hopp,@StaxMan 我的经验(到目前为止)是使用SAX解析器从给定的xml文档中提取出我所需要的必要属性。之前我犹豫不决是否要在此情况下使用解析器的原因是因为(继续之前所说的),除了在heading1和heading2之间爬取信息外,我还想确定是否存在“image”的实例在这两个标题之间。如果是这样,那么我想将该部分保留在一个单独的文档中,并仅解析该文档以查找目标属性(最有可能使用SAX)。 - This 0ne Pr0grammer
@Ted Hopp,@StaxMan,然而,我相信解析器只能向下读取,无法向上读取。因此,如果我要使用解析器识别图像实例,我将无法刮掉其上面的部分。所以现在我真的不确定最好的方法是什么。 :/ - This 0ne Pr0grammer
@This 0ne- 我认为你会发现使用DOM解析器比SAX更容易。(它占用内存较高,但确实有其用途。)你可以轻松地在子树中搜索标记、剪切掉你不想要的部分,并且很容易使用转换器从剩余的内容生成XML。 - Ted Hopp

3
如果您只需要一份副本,请不要犯使用Reader而是使用InputStream/OutputStream的初学者错误。即使使用Reader,为什么还要逐行读取呢?只需读取缓冲区中的字符即可。
那么为什么要避免使用Reader呢?因为它增加了将字节解码为字符(并要求Writer从字符编码为字节)的开销,这对您没有任何价值。如果您另外犯一个常见错误,即未指定要用于Reader或Writer的编码,则可能会出现问题 - 这将使用任何平台默认编码,这可能与您正在读取的文件使用的编码相同,也可能不同。

1

我会使用StAX,但我刚开始熟悉SAX并将其纳入了我的项目阶段。您认为StAX与SAX有多大不同? - This 0ne Pr0grammer
使用SAX通常就像尝试倒立爬树一样困难,或者像以逆波兰式表达式编写代码一样。或者用计算机科学的术语来说:它是基于事件循环(监听器)的,因此您最终需要编写处理程序并跟踪状态,所有这些都非常复杂。Stax更加直观;您可以使用游标(XMLStreamReader)按照XML文档中的顺序读取内容,然后类似地编写它们。 - StaxMan
就像他所说的那样,StAX是基于拉取光标的,而不是SAX的推模型。这使得它非常适合你正在尝试做的事情。你将使用更少的代码来完成工作,并且编写和阅读代码可能更直观。话虽如此,你当然也可以使用SAX来完成工作。你可以利用实习项目的机会学习两者。这将是值得花费时间的。 - ewan.chalmers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接