简体   繁体   English

如何使用Stream API和Printwriter写入文件时避免使用上一个新行?

[英]How to avoid the last new line in when writing to a File using the Stream API and Printwriter?

I am studying the Lambdas and Stream API that comes with Java 8. I wanted to create a file something like this using Stream API just for exercising purposes: 我正在研究Java 8附带的Lambdas和Stream API。我想使用Stream API创建一个类似于此类的文件,仅用于练习目的:

b
bb
bbb
bbbb
bbbbb
bbbb
bbb
bb
b

and this is the implementation I came up with: 这是我提出的实现:

final File file = new File("/Users/kt/sample.data");
final PrintWriter printWriter = new PrintWriter(file);

Stream.concat(IntStream.iterate(1, i -> i + 1).limit(6).boxed(), 
              IntStream.iterate(5, i -> i - 1).limit(5).boxed())
      .map(counter -> {
          StringBuilder stringBuilder = new StringBuilder();
          IntStream.range(1, counter).forEach(c -> stringBuilder.append("b"));
          return stringBuilder.toString();
      }).filter(s -> s.length() != 0).forEach(s -> printWriter.println(s));

printWriter.flush();
printWriter.close();

Now the only problem is, I end up with an empty last line in the file, since printwriter is printing the last 'b' together with a new line. 现在唯一的问题是,我最终在文件中留下了一个空的最后一行,因为printwriter正在用新行打印最后一个'b'。

Obviously I can pass 4 instead of 5 to 2nd IntStream.iterate I have and before flushing the printWriter I can do: printWriter.print("b"); 显然我可以传递4而不是5到第二个IntStream.iterate我已经和刷新printWriter之前我可以做: printWriter.print("b"); , but my goal is to harness the Stream API. ,但我的目标是利用Stream API。

How can I achieve this more Streamy ? 我怎样才能实现更多Streamy

You can do you job much simpler as 你可以更简单地工作

Files.write(Paths.get("/Users/kt/sample.data"),
    () -> IntStream.range(1, 10)
        .<CharSequence>mapToObj(i -> "bbbbb".substring(Math.abs(5-i)))
        .iterator());

Not to speak of 不说了

Files.write(Paths.get("C:\\Users\\pietsch\\AppData\\Local\\Temp\\output"),
    Collections.singletonList("b\nbb\nbbb\nbbbb\nbbbbb\nbbbb\nbbb\nbb\nb"));

If it feels too much like cheating due to hardcoded invariants, change the code to allow to specify an arbitrary maximum string size: 如果由于硬编码不变量而感觉太像欺骗,请更改代码以允许指定任意最大字符串大小:

int size = 5;

int[] codepoints = IntStream.range(0, size).map(i -> 'b').toArray();
Files.write(Paths.get("/Users/kt/sample.data"),
    () -> IntStream.range(1, size*2)
        .<CharSequence>mapToObj(i -> new String(codepoints, 0, size-Math.abs(size-i)))
        .iterator());

I recommend to use a variable to store the size, as there is several places that requires it : maxSize 我建议使用变量来存储大小,因为有几个地方需要它: maxSize


  1. You can join your elements with a return line, and then print , and as a tip you can simplify your use of StringBuilder with a map operation 您可以使用返回行连接元素,然后进行print ,作为提示,您可以通过map操作简化StringBuilder使用
int maxSize = 5;
String str =
        IntStream.concat(IntStream.iterate(2, i -> i + 1).limit(maxSize),
                         IntStream.iterate(maxSize, i -> i - 1).limit(maxSize - 1))
                 .mapToObj(count -> IntStream.range(1, count).mapToObj(c -> "b").collect(Collectors.joining()))
                 .collect(Collectors.joining("\n"));

printWriter.print(str);
  1. A second option, to avoid the String variable, would be add a \\n between each block, then limit to remove the last one and print all, but this is not the more efficient between both : 第二个选项,为了避免String变量,将在每个块之间添加\\n ,然后限制删除最后一个并打印全部,但这两者之间的效率不是更高:
int maxSize = 5;
IntStream.concat(IntStream.iterate(2, i -> i + 1).limit(maxSize),
                 IntStream.iterate(maxSize, i -> i - 1).limit(maxSize - 1))
         .mapToObj(count -> IntStream.range(1, count).mapToObj(c -> "b").collect(Collectors.joining()))
         .flatMap(b -> Stream.of(b, "\n"))
         .limit((maxSize * 2 - 1) * 2 - 1)
         .forEach(printWriter::print);

Do not know exactly what the Streamy way means, but how about this: 不知道Streamy方式到底意味着什么,但是这个怎么样:

    int[] arr = new int[max * 2 - 1];
    arr[(max * 2) / 2] = max;

    IntStream.range(0, max)
             .forEachOrdered(x -> {
                 arr[x] = x + 1;
                 arr[x + max - 1] = max - x;
             });

    String result = Arrays.stream(arr)
                          .mapToObj(x -> IntStream.range(0, x)
                                                  .mapToObj(i -> "b")
                                                  .collect(Collectors.joining()))
                          .collect(Collectors.joining("\n"));

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

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