Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modify file using Files.lines

I'd like to read in a file and replace some text with new text. It would be simple using asm and int 21h but I want to use the new java 8 streams.

    Files.write(outf.toPath(), 
        (Iterable<String>)Files.lines(inf)::iterator,
        CREATE, WRITE, TRUNCATE_EXISTING);

Somewhere in there I'd like a lines.replace("/*replace me*/","new Code()\n");. The new lines are because I want to test inserting a block of code somewhere.

Here's a play example, that doesn't work how I want it to, but compiles. I just need a way to intercept the lines from the iterator, and replace certain phrases with code blocks.

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import static java.nio.file.StandardOpenOption.*;
import java.util.Arrays;
import java.util.stream.Stream;

public class FileStreamTest {

    public static void main(String[] args) {
        String[] ss = new String[]{"hi","pls","help","me"};
        Stream<String> stream = Arrays.stream(ss);

        try {
            Files.write(Paths.get("tmp.txt"),
                    (Iterable<String>)stream::iterator,
                    CREATE, WRITE, TRUNCATE_EXISTING);
        } catch (IOException ex) {}

//// I'd like to hook this next part into Files.write part./////
        //reset stream
        stream = Arrays.stream(ss);
        Iterable<String> it = stream::iterator;
        //I'd like to replace some text before writing to the file
        for (String s : it){
            System.out.println(s.replace("me", "my\nreal\nname"));
        }
    }

}

edit: I've gotten this far and it works. I was trying with filter and maybe it isn't really necessary.

        Files.write(Paths.get("tmp.txt"),
                 (Iterable<String>)(stream.map((s) -> {
                    return s.replace("me", "my\nreal\nname");
                }))::iterator,
                CREATE, WRITE, TRUNCATE_EXISTING);
like image 665
brian Avatar asked Feb 13 '15 16:02

brian


People also ask

What does files Lines Path Path do?

What does Files. lines(Path path) do? Explanation: Files. lines(Path path) that reads all lines from a file as a Stream.

What is the easiest way to read text files line by line in Java 8?

Java Read File line by line using BufferedReader We can use java. io. BufferedReader readLine() method to read file line by line to String. This method returns null when end of file is reached.

How do I change the content of a text file in Java?

1) open the file for input 2) read the file 3) close the file 4) change the data in the file 5) open the file for output 6) write the changed data to the file 7) close the file Any book on Java will have the basics of Input and Output.


1 Answers

The Files.write(..., Iterable, ...) method seems tempting here, but converting the Stream to an Iterable makes this cumbersome. It also "pulls" from the Iterable, which is a bit odd. It would make more sense if the file-writing method could be used as the stream's terminal operation, within something like forEach.

Unfortunately, most things that write throw IOException, which isn't permitted by the Consumer functional interface that forEach expects. But PrintWriter is different. At least, its writing methods don't throw checked exceptions, although opening one can still throw IOException. Here's how it could be used.

Stream<String> stream = ... ; try (PrintWriter pw = new PrintWriter("output.txt", "UTF-8")) {     stream.map(s -> s.replaceAll("foo", "bar"))           .forEachOrdered(pw::println); } 

Note the use of forEachOrdered, which prints the output lines in the same order in which they were read, which is presumably what you want!

If you're reading lines from an input file, modifying them, and then writing them to an output file, it would be reasonable to put both files within the same try-with-resources statement:

try (Stream<String> input = Files.lines(Paths.get("input.txt"));      PrintWriter output = new PrintWriter("output.txt", "UTF-8")) {     input.map(s -> s.replaceAll("foo", "bar"))          .forEachOrdered(output::println); } 
like image 181
Stuart Marks Avatar answered Oct 20 '22 17:10

Stuart Marks