Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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() ");. 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
real
name"));
        }
    }

}

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
real
name");
                }))::iterator,
                CREATE, WRITE, TRUNCATE_EXISTING);
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
200 views
Welcome To Ask or Share your Answers For Others

1 Answer

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);
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...