简体   繁体   English

java.lang.IllegalStateException:已经获得迭代器

[英]java.lang.IllegalStateException: Iterator already obtained

I modified this code to do several tasks in one directory: 我修改了此代码,以在一个目录中执行多个任务:

public class HDDSerialNumber
{

    public void getHDDSerialNumber() throws IOException
    {
        try (DirectoryStream<Path> ds = Files.newDirectoryStream(Paths.get("/sys/block"), "sd*"))
        {
            // Get HDD Model
            StreamSupport.stream(ds.spliterator(), false)
                .map(p -> p.resolve("device/model")).flatMap(wrap(Files::lines))
                .forEach(System.out::println);

            // Get HDD Vendor
            StreamSupport.stream(ds.spliterator(), false)
                .map(p -> p.resolve("device/vendor")).flatMap(wrap(Files::lines))
                .forEach(System.out::println);

            // Get HDD Vendor
            StreamSupport.stream(ds.spliterator(), false)
                .map(p -> p.resolve("device/state")).flatMap(wrap(Files::lines))
                .forEach(System.out::println);
        }
    }

    static <T, R> Function<T, R> wrap(IOFunction<T, R> f)
    {
        return t ->
        {
            try
            {
                return f.apply(t);
            }
            catch (IOException ex)
            {
                throw new UncheckedIOException(ex);
            }
        };
    }

    interface IOFunction<T, R>
    {
        R apply(T in) throws IOException;
    }
}

But when I run the code I get this error stack: 但是当我运行代码时,我得到了这个错误堆栈:

run:
ST320LT012-9WS14
Exception in thread "main" java.lang.IllegalStateException: Iterator already obtained
    at sun.nio.fs.UnixDirectoryStream.iterator(UnixDirectoryStream.java:118)
    at sun.nio.fs.UnixSecureDirectoryStream.iterator(UnixSecureDirectoryStream.java:73)
    at java.lang.Iterable.spliterator(Iterable.java:101)
    at hardware.HDDSerialNumber.getHDDSerialNumber(HDDSerialNumber.java:25)
    at hardware.Hardware.main(Hardware.java:12)
Java Result: 1

Can you help me to fix the code, please? 您能帮我修改代码吗? I suppose that Iterator already obtained must be used only once in this example but I don't have idea how to fix this. 我想在这个例子中已经获得的Iterator只能使用一次,但是我不知道如何解决这个问题。

While DirectoryStream extends Iterable, it is not a general-purpose Iterable as it supports only a single Iterator; 虽然DirectoryStream扩展了Iterable,但它不是通用的Iterable,因为它仅支持单个Iterator。 invoking the iterator method to obtain a second or subsequent iterator throws IllegalStateException. 调用迭代器方法以获得第二个或后续迭代器,则抛出IllegalStateException。

( Source ) 来源

The iterator of the Iterable returned by Files.newDirectoryStream ( DirectoryStream implements Iterable ) can only be used once. Files.newDirectoryStreamDirectoryStream实现Iterable )返回的Iterable的迭代器只能使用一次。 You can solve it by calling Files.newDirectoryStream separately for each of the 3 streams you are creating. 您可以通过分别针对要创建的3个流分别调用Files.newDirectoryStream来解决此问题。

Instead of creating one DirectoryStream<Path> ds = Files.newDirectoryStream(Paths.get("/sys/block"), "sd*"); 而不是创建一个DirectoryStream<Path> ds = Files.newDirectoryStream(Paths.get("/sys/block"), "sd*"); and using it in all 3 StreamSupport.stream calls, create 3 DirectoryStream<Path> . 并在所有3个StreamSupport.stream调用中使用它,创建3 DirectoryStream<Path>

Example : 范例:

public void getHDDSerialNumber() throws IOException
{
    try (DirectoryStream<Path> ds = Files.newDirectoryStream(Paths.get("/sys/block"), "sd*"))
    {
        // Get HDD Model
        StreamSupport.stream(ds.spliterator(), false)
            .map(p -> p.resolve("device/model")).flatMap(wrap(Files::lines))
            .forEach(System.out::println);
    }
    try (DirectoryStream<Path> ds = Files.newDirectoryStream(Paths.get("/sys/block"), "sd*"))
    {
        // Get HDD Vendor
        StreamSupport.stream(ds.spliterator(), false)
            .map(p -> p.resolve("device/vendor")).flatMap(wrap(Files::lines))
            .forEach(System.out::println);
    }
    try (DirectoryStream<Path> ds = Files.newDirectoryStream(Paths.get("/sys/block"), "sd*"))
    {
        // Get HDD State
        StreamSupport.stream(ds.spliterator(), false)
            .map(p -> p.resolve("device/state")).flatMap(wrap(Files::lines))
            .forEach(System.out::println);
    }
}

EDIT : 编辑:

If you want to handle the case of a file that doesn't exist without interrupting the program execution, catch the exception thrown in that case. 如果要处理不存在的文件而不中断程序执行的情况,请捕获在这种情况下引发的异常。

For example : 例如 :

    try (DirectoryStream<Path> ds = Files.newDirectoryStream(Paths.get("/sys/block"), "sd*"))
    {
        // Get HDD State
        StreamSupport.stream(ds.spliterator(), false)
            .map(p -> p.resolve("device/state"))
            .flatMap(wrap(path - > try {
                                     return Files.lines(path);
                                   } catch (IOException ioEx) {
                                     return Stream.empty();
                                   }))
            .forEach(System.out::println);
    }

This would catch the exception and return an empty Stream. 这将捕获异常并返回空Stream。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM