Yves Amsellem отвечает довольно хорошо, но работает, только если все элементы имеют одинаковый тип. В противном случае ваш unmarshall выдаст исключение, но читатель уже использует байты, поэтому вы не сможете восстановить. Вместо этого мы должны следовать совету Скаффмана и посмотреть на образец из банки JAXB.
Чтобы объяснить, как это работает:
- Создание демаршаллера JAXB.
- Добавьте слушателя к маршаллеру для перехвата соответствующих элементов. Это делается путем «взлома» ArrayList, чтобы гарантировать, что элементы не будут сохранены в памяти после разархивирования.
- Создать SAX-парсер. Здесь происходит потоковая передача.
- Используйте unmarshaller для генерации обработчика для парсера SAX.
- поток!
Я изменил решение, чтобы оно было общим *. Однако это потребовало некоторых размышлений. Если это не так, пожалуйста, посмотрите примеры кода в банках JAXB.
ArrayListAddInterceptor.java
import java.lang.reflect.Field;
import java.util.ArrayList;
public class ArrayListAddInterceptor<T> extends ArrayList<T> {
private static final long serialVersionUID = 1L;
private AddInterceptor<T> interceptor;
public ArrayListAddInterceptor(AddInterceptor<T> interceptor) {
this.interceptor = interceptor;
}
@Override
public boolean add(T t) {
interceptor.intercept(t);
return false;
}
public static interface AddInterceptor<T> {
public void intercept(T t);
}
public static void apply(AddInterceptor<?> interceptor, Object o, String property) {
try {
Field field = o.getClass().getDeclaredField(property);
field.setAccessible(true);
field.set(o, new ArrayListAddInterceptor(interceptor));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Main.java
public class Main {
public void parsePurchaseOrders(AddInterceptor<PurchaseOrder> interceptor, List<File> files) {
try {
// create JAXBContext for the primer.xsd
JAXBContext context = JAXBContext.newInstance("primer");
Unmarshaller unmarshaller = context.createUnmarshaller();
// install the callback on all PurchaseOrders instances
unmarshaller.setListener(new Unmarshaller.Listener() {
public void beforeUnmarshal(Object target, Object parent) {
if (target instanceof PurchaseOrders) {
ArrayListAddInterceptor.apply(interceptor, target, "purchaseOrder");
}
}
});
// create a new XML parser
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
XMLReader reader = factory.newSAXParser().getXMLReader();
reader.setContentHandler(unmarshaller.getUnmarshallerHandler());
for (File file : files) {
reader.parse(new InputSource(new FileInputStream(file)));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
* Этот код не был проверен и предназначен только для иллюстративных целей.