gpt4 book ai didi

java - Spring Jaxb2 : How to append batch data to XML file with no reading it to memory?

转载 作者:行者123 更新时间:2023-12-01 09:30:01 27 4
gpt4 key购买 nike

我需要批量写入数据到xml。

有以下域对象:

@XmlRootElement(name = "country")
public class Country {
@XmlElements({@XmlElement(name = "town", type = Town.class)})
private Collection<Town> towns = new ArrayList<>();
....
}

还有:

@XmlRootElement(name = "town")
public class Town {
@XmlElement
private String townName;
// etc
}

我正在使用 Jaxb2 整理对象。配置如下:

marshaller = new Jaxb2Marshaller();
marshaller.setClassesToBeBound(Country.class, Town.class);

因为简单的编码在这里不起作用,如 marhaller.marshall(fileName, Country) - 它会导致 xml 格式错误。

是否有一种方法可以调整 marhaller,以便在所有编码数据不存在该文件时创建文件,或者如果存在则将其附加到 xml 文件末尾?

此外,由于此文件可能很大,我不想读取内存中的整个文件,追加数据,然后写入磁盘。

最佳答案

我使用 StAX 进行 xml 处理,因为它基于流,比 DOM 消耗更少的内存,并且与只能解析 xml 数据但无法写入的 SAX 相比,具有读写能力。

这是我想出的方法:

public enum StAXBatchWriter {
INSTANCE;
private static final Logger LOGGER = LoggerFactory.getLogger(StAXBatchWriter.class);

public void writeUrls(File original, Collection<Town> towns) {
XMLEventReader eventReader = null;
XMLEventWriter eventWriter = null;
try {
String originalPath = original.getPath();
File from = new File(original.getParent() + "/old-" + original.getName());
boolean isRenamed = original.renameTo(from);
if (!isRenamed)
throw new IllegalStateException("Failed to rename file: " + original.getPath() + " to " + from.getPath());
File to = new File(originalPath);

XMLInputFactory inFactory = XMLInputFactory.newInstance();
eventReader = inFactory.createXMLEventReader(new FileInputStream(from));

XMLOutputFactory outFactory = XMLOutputFactory.newInstance();
eventWriter = outFactory.createXMLEventWriter(new FileWriter(to));

XMLEventFactory eventFactory = XMLEventFactory.newInstance();

while (eventReader.hasNext()) {
XMLEvent event = eventReader.nextEvent();
eventWriter.add(event);
if (event.getEventType() == XMLEvent.START_ELEMENT && event.asStartElement().getName().toString().contains("country")) {
for (Town town : towns) {
writeTown(eventWriter, eventFactory, town);
}
}
}
boolean isDeleted = from.delete();
if (!isDeleted)
throw new IllegalStateException("Failed to delete old file: " + from.getPath());
} catch (IOException | XMLStreamException e) {
LOGGER.error(e.getMessage(), e);
throw new RuntimeException(e);
} finally {
try {
if (eventReader != null)
eventReader.close();
} catch (XMLStreamException e) {
LOGGER.error(e.getMessage(), e);
}
try {
if (eventWriter != null)
eventWriter.close();
} catch (XMLStreamException e) {
LOGGER.error(e.getMessage(), e);
}
}
}

private void writeTown(XMLEventWriter eventWriter, XMLEventFactory eventFactory, Town town) throws XMLStreamException {
eventWriter.add(eventFactory.createStartElement("", null, "town"));

// write town id
eventWriter.add(eventFactory.createStartElement("", null, "id"));
eventWriter.add(eventFactory.createCharacters(town.getId()));
eventWriter.add(eventFactory.createEndElement("", null, "id"));

//write town name
if (StringUtils.isNotEmpty(town.getName())) {
eventWriter.add(eventFactory.createStartElement("", null, "name"));
eventWriter.add(eventFactory.createCharacters(town.getName()));
eventWriter.add(eventFactory.createEndElement("", null, "name"));
}

// write other fields

eventWriter.add(eventFactory.createEndElement("", null, "town"));
}
}

这不是最好的方法,尽管它是基于流的并且正在工作,但它有一些开销。当添加一批时 - 必须重新读取旧文件。

如果有一个选项可以在文件中的某个点附加数据(例如“在 4 行后将数据附加到该文件”),那就太好了,但似乎无法做到这一点。

关于java - Spring Jaxb2 : How to append batch data to XML file with no reading it to memory?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39513121/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com