有没有办法使用Java 8中的Files.lines读取序列化文件

时间:2015-11-02 22:36:59

标签: serialization file-io lambda java-8 java-stream

我正在尝试读取对象的序列化文件,但我想尝试Java 8的功能编程功能;但是,我一直收到MalformedInputException。显然,Files.lines读入Stream< String>而不是对象。 (Files class in Oracle Documentation.)因此格式错误的输入 - 它无法使用它所使用的字符集来处理字符串的序列化字符。

我通常会使用ObjectInputStream,但我有心情尝试新的东西。 Java 8中是否有一些我不能使用lambdas上下文中的流来读取序列化文件的内容?

如果您有兴趣,请在尝试之前尝试创建一个Stream< String> (WordDefinitions.dat是一个序列化文件,其中包含一个名为Definition的类中的自定义数据类对象 - 基本上只是实验的字符串):

List<Definition> defsList =
    Files.lines(Paths.get("WordDefinitions.dat")) 
        .collect(Collectors.toList());

我甚至尝试了一个明确的演员:

List<String> defsList =
    Files.lines(Paths.get("WordDefinitions.dat"))
        .map(item -> {
            Definition temp = (Definition)item;
            return temp.toString();
         })
         .collect(Collectors.toList());

2 个答案:

答案 0 :(得分:2)

没有将ObjectInputStream转换为Stream<Object>的功能,通常,这些功能无法很好地协同工作。最值得注意的是,ObjectInputStream没有提供任何方法来识别是否有更多对象可用,即是否已到达流的末尾。

仍然可以使用以下方法创建流:

public static Stream<Object> fromFile(File f) throws IOException {
    FileInputStream is=new FileInputStream(f);
    try {
        ObjectInputStream ois=new ObjectInputStream(is);
        return StreamSupport.stream(
        new Spliterators.AbstractSpliterator<Object>(Long.MAX_VALUE, Spliterator.ORDERED) {
            public boolean tryAdvance(Consumer<? super Object> action) {
                try {
                    action.accept(ois.readObject());
                    return true;
                } catch (IOException ex) {
                    throw new UncheckedIOException(ex);
                } catch (ClassNotFoundException ex) {
                    throw new NoClassDefFoundError(ex.getMessage());
                }
            }
            @Override public Spliterator<Object> trySplit() { return null; }
        }, false).onClose(() -> { try { ois.close(); }
            catch (IOException ex) { throw new UncheckedIOException(ex); } });
    } catch(Throwable t) {
        try(FileInputStream toClose=is) { throw t; }
    }
}

如上所述,此流不知道其对象的数量,因此需要明确使用limit以确保不会尝试读取结束:

File f=File.createTempFile("ser", null);
try(FileOutputStream os=new FileOutputStream(f);
    ObjectOutputStream oos=new ObjectOutputStream(os)) {
    oos.writeObject("hello");
    oos.writeObject(42);
    oos.writeObject(Arrays.asList("X", "Y", "Z"));
    oos.flush();
}
System.out.println(f+": "+f.length()+" bytes");
try(Stream<Object> s=fromFile(f)) {
    s.limit(3).forEach(System.out::println);
}

答案 1 :(得分:0)

没有。序列化对象不是行。