如何使用lambda循环XMLStreamReader

如何使用lambda循环XMLStreamReader,lambda,java-8,Lambda,Java 8,这与其说是一个严肃的需要,不如说是一个学习目的的问题。 我使用下面的代码检查xml文件是否有效。我在这里不担心模式验证。 我知道XMLStreamReader是一个接口,但我试图找到一些实现,使我能够做一些接近: Stream<String> s = reader.getText(); s.forEach(System.out::println); //编辑 import com.iread.CheckXml; public class Check

这与其说是一个严肃的需要,不如说是一个学习目的的问题。 我使用下面的代码检查xml文件是否有效。我在这里不担心模式验证。 我知道XMLStreamReader是一个接口,但我试图找到一些实现,使我能够做一些接近:

        Stream<String> s = reader.getText();
        s.forEach(System.out::println);
//编辑

import com.iread.CheckXml;

public class CheckXmlFiles implements CheckXml {
}

//...
@Test
public void testXmlValidation() throws IOException {
    CheckXml c = new CheckXmlFiles(); 
    assertTrue("For simplicity it is expected 'true'", c.readFile("C:\\_pocs\\temp\\demo.xml"));
}

您可以将
XmlStreamReader
转换为流,然后使用它。例如,您需要创建一个迭代器来调用
hasNext
next
方法

在实现过程中有一些令人头痛的问题:XmlStreamReader会抛出检查过的异常,这将迫使您创建一些额外的异常处理代码,从而使代码膨胀

还要注意,
XmlStreamReader
的底层流必须在迭代器中关闭。如果您在外部关闭它,您将面临一些流关闭异常。在这种情况下,您也不能使用
try with resources

我尝试创建一个简单的流和一个简单的测试,它统计XML文件中可用元素的数量

下面是一些玩具代码,演示您最终如何做到这一点:

public class XMLStreamReaderStream {

    public static Stream<Integer> fromFile(File f) throws IOException, XMLStreamException {
        XMLInputFactory factory = XMLInputFactory.newInstance();
        Reader inputStream;
        inputStream = new InputStreamReader(new FileInputStream(f), "UTF-8");
        XMLStreamReader reader = factory.createXMLStreamReader(inputStream);

        Iterator<Integer> iterator = new Iterator<>() {
            public Integer next() {
                try {
                    return reader.next();
                } catch (XMLStreamException e) {
                    throw new RuntimeException(e);
                }
            }

            public boolean hasNext() {
                try {
                    boolean hasNext = reader.hasNext();
                    if (!hasNext) {
                        reader.close(); // close the stream here
                    }
                    return hasNext;
                } catch (XMLStreamException e) {
                    return false;
                }
            }

            public void forEachRemaining(Consumer<? super Integer> action) {
                while (hasNext()) {
                    action.accept(next());
                }
            }
        };

        return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED), false);
    }

    public static void main(String[] args) throws IOException, XMLStreamException {
        File sampleXml = new File("stackoverflow1.xml");
        LinkedHashMap<Integer, Long> xmlStats = fromFile(sampleXml).collect(Collectors.groupingBy(Function.identity(),
                LinkedHashMap::new, Collectors.counting()));
        Map<String, Long> readableMap = xmlStats.entrySet().stream().collect(Collectors.toMap(e -> {
            Optional<Field> opt = Stream.of(XMLStreamConstants.class.getDeclaredFields()).filter(f -> {
                try {
                    return e.getKey().equals(f.get(null));
                } catch (IllegalAccessException e1) {
                    return false;
                }
            }).findFirst();
            return opt.map(s -> s.toString().replaceAll(".+\\.", "")).orElseGet(() -> Integer.toString(e.getKey()));
        }, Map.Entry::getValue));
        System.out.println(readableMap);
    }
}

你的“没有lambda的完整代码”在我看来并不完整。它至少应该包含获取您希望放入该
流中的
字符串的代码。创建一个
迭代器
,其中
某物
是您在
期间
想要得到的东西,例如
xmlement
Person
。将该
迭代器
包装在
拆分器
中。从
拆分器
@Eran创建一个
,老实说,我不知道这个问题有什么关系,但你在这里;我增加了我的question@BoristheSpider,你能详细阐述一下你的想法吗?据我所知,Spliterator的目标是当我们想要将一个大文件拆分为一些合理的较小虚拟文件时使用,我们需要并行读取(多线程方法)。所谓大文件,我指的是足够大的内存(不是真正的大文件)。最重要的是,在我的例子中,我读取流只是因为我想确保xml格式正确。它可以是任何xml,所以我不能使用类似Pojo的人。我想XMLElement将适合我的情况,但如何使用迭代器/拆分器实现它呢?:不确定从哪里获得这些信息;但这是完全错误的。阅读
API。
public class XMLStreamReaderStream {

    public static Stream<Integer> fromFile(File f) throws IOException, XMLStreamException {
        XMLInputFactory factory = XMLInputFactory.newInstance();
        Reader inputStream;
        inputStream = new InputStreamReader(new FileInputStream(f), "UTF-8");
        XMLStreamReader reader = factory.createXMLStreamReader(inputStream);

        Iterator<Integer> iterator = new Iterator<>() {
            public Integer next() {
                try {
                    return reader.next();
                } catch (XMLStreamException e) {
                    throw new RuntimeException(e);
                }
            }

            public boolean hasNext() {
                try {
                    boolean hasNext = reader.hasNext();
                    if (!hasNext) {
                        reader.close(); // close the stream here
                    }
                    return hasNext;
                } catch (XMLStreamException e) {
                    return false;
                }
            }

            public void forEachRemaining(Consumer<? super Integer> action) {
                while (hasNext()) {
                    action.accept(next());
                }
            }
        };

        return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED), false);
    }

    public static void main(String[] args) throws IOException, XMLStreamException {
        File sampleXml = new File("stackoverflow1.xml");
        LinkedHashMap<Integer, Long> xmlStats = fromFile(sampleXml).collect(Collectors.groupingBy(Function.identity(),
                LinkedHashMap::new, Collectors.counting()));
        Map<String, Long> readableMap = xmlStats.entrySet().stream().collect(Collectors.toMap(e -> {
            Optional<Field> opt = Stream.of(XMLStreamConstants.class.getDeclaredFields()).filter(f -> {
                try {
                    return e.getKey().equals(f.get(null));
                } catch (IllegalAccessException e1) {
                    return false;
                }
            }).findFirst();
            return opt.map(s -> s.toString().replaceAll(".+\\.", "")).orElseGet(() -> Integer.toString(e.getKey()));
        }, Map.Entry::getValue));
        System.out.println(readableMap);
    }
}
{START_ELEMENT=22, END_DOCUMENT=1, END_ELEMENT=22, CHARACTERS=27}