简体   繁体   中英

File IO, Reading from file array using a for-each loop ( : ) in java

So normally, I know one would use a standard for loop to iterate though the array, like such:

public static void readCodesFromFile(String filename, String[] codes) throws FileNotFoundException {
    try ( Scanner fin = new Scanner(new File(filename) ); ) {
        for (int i = 0; i <= codes.length - 1; i++) {
            codes[i] = fin.nextLine();
        }
    }
}

But, I desperately want to discover how to do this with a for each loop instead. At this point I just need to know if it can be done, but also would love the efficiency and cleanliness of using this loop for this task. I have tried something like this, and moved things around many times, but cannot seem to get anything to read properly.

Below is the for each ( : ) I have been working with:

 public static void readCodesFromFile(String filename, String [] codes) throws FileNotFoundException {
     try (Scanner fin = new Scanner(new File(filename) ); ) {
         for (String code : codes) {
            codes = fin.nextLine();
         }
     }
 }

At this point I just need to know if it can be done...

No, not as it's written. For one, the spec doesn't allow for it but you're also dealing with immutable String s. Say, from your second example, code is a reference to an element in your array. Once I do code = "foo"; , code now references the (presumably) new String and the array element retains its original value.

But, I desperately want to discover how to do this with a for each loop instead.

If that's the case, why not invert the problem? Instead of iterating over the array, provide a way to iterate over the file.

In this answer I'm going to assume two things:

  1. You'll provide an Iterable FileReader
  2. You'll use an ArrayList instead of a normal array ( this is to get past the indexing issue with the additional benefit that you'll no longer need to know or care about the number of lines in the file )

Here's the FileReader (with a lot not implemented):

class FileReader implements Iterable<String> {

    @Override
    public Iterator<String> iterator() {
        return new FileReaderIterator();
    }

    @Override
    public void forEach(Consumer<? super String> action) { }

    @Override
    public Spliterator<String> spliterator() { return null; }

    class FileReaderIterator implements Iterator<String> {

        @Override
        public boolean hasNext() {
            return false;
        }

        @Override
        public String next() {
            return null;
        }

        @Override
        public void remove() { }

        @Override
        public void forEachRemaining(Consumer<? super String> action) { }
    }
}

Assuming you had this implemented you could have used it like so:

List<String> lines = new ArrayList<>();
FileReader reader = new FileReader(...);
for (String line : reader) {
    lines.add(line);
}

I'm not suggesting you change your design rather to consider what a different design choice could have provided.

Another way you could achieve this with a basic array very easily would be to encapsulate the line in a class. For example:

class FileLine {
    private String line;

    public FileLine() {...}

    public FileLine(String line) {
        this.line = line;
    }

    public setLine(String line) {
        this.line = line;
    }
}

Make an array of those, iterate over it with the enhanced for loop, and instead of setting the value of the array string element, set the value of the string member of the FileLine instance. Like so:

// Given an array of instantiated FileLines...
for (FileLine fileLine : fileLines) {
    fileLine.setLine(...);
}

Less effort and you don't have to worry about trying to iterate over a file.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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