我刚看过文件I / O,现在,我想弄脏手。我想:
System.in
对象的Scanner对象从控制台读取输入作为其参数。我想使用PrintWriter
对象将从控制台读取的输入写入文件。
现在,使用另一个以File对象作为参数的Scanner对象,我想从文件中读取并将其显示在控制台输出上。
我试图以这种方式实现它:
import java.io.*;
import java.util.Scanner;
public class A {
public static void main(String[] args) throws FileNotFoundException {
PrintWriter pw = new PrintWriter("File.txt");
File f = new File("File.txt");
Scanner scan = new Scanner(f);
Scanner scan2 = new Scanner(System.in);
String s;
System.out.println("Please enter the input:\n");
while (scan2.hasNext()) {
s = scan2.nextLine();
pw.println(s);
}
scan2.close();
pw.close();
System.out.println("****************************************");
System.out.println("Displaying output:\n");
while (scan.hasNext()) {
System.out.println(scan.nextLine());
}
scan.close();
}
}
为了停止从控制台输入,我点击ctrl
+ z
。 这是最好的,也是标准的做法吗?
另外,如果我需要在线之间输入空格,我该怎么做?它只是忽略了空白行。
答案 0 :(得分:1)
关于你的主要问题," [...]我点击ctrl+z
。 这是最好的,也是标准的做法吗?"
我假设您使用的是Windows cmd.exe
,因此ctrl+z
实际上意味着终端会在EOF
上生成模拟stdin
。因此,是标准方式,但可能对所有用户都不方便。
在Windows cmd.exe
上,ctrl+z
在终端提供的EOF
上生成stdin
。它与POSIX系统上的ctrl+d
相同。这是程序读取的标准方式 - 它们从流中读取,直到它们达到EOF
。
确实有成千上万的程序显示出这种行为。该行为是程序使用重定向与<
/ >
和管道与{{1}成功交互文件和其他程序的前提条件}。最简单的程序显示了这种行为,例如|
,cat
,head
,tail
,sort
,grep
以及更复杂的程序sed
,avconv
等程序。
等待mplayer
的特定令牌而是坏主意。这将使您的程序行为非直观,甚至在用户使用重定向时崩溃,并且不知道该令牌。即使他们知道这个令牌,也会给他们带来额外的负担。
另外等待特定令牌到EOF
可能是一个好主意。例如,程序EOF
,二进制计算器可以使用bc
终止,也可以通过向其发送包含文本EOF
的行。如果您想添加用户友好性,可以这样做。
但这也取决于你输入的性质。如果您的程序要处理任意输入,最终从任意文件重定向,例如,计算行或单词或字符,等待特定标记将是一个非常糟糕的主意。
只要您支持使用quit
但使用令牌终止程序,您需要考虑:如果该令牌也可以是有效输入怎么办?那么您需要开始考虑逃生机制。虽然这是标准解决方案的标准问题而不是过于复杂,但对于像这样的简单程序来说,额外的复杂性通常是不合理的。
您的程序关闭资源很好。 但是,资源不仅应该在好的情况下关闭,而且应该在坏的情况下关闭。如果发生异常,您的程序不会关闭资源。
只使用扫描仪从EOF
读取的程序可以这样写:
stdin
这使用Java import java.io.InputStream;
import java.util.Scanner;
import static java.lang.System.in;
import static java.lang.System.out;
public class ScanCat {
public static void main(final String... args) {
scanCat(in);
}
public static void scanCat(final InputStream in) {
try (final Scanner scanner = new Scanner(in)) {
tryScanCat(scanner);
}
}
public static void tryScanCat(final Scanner scanner) {
while (scanner.hasNextLine())
out.println(scanner.nextLine());
}
}
- with-resources 语句。 try
块上的右括号在try
上执行隐式close()
,无论Scanner scanner
块是成功完成还是异常。
try
通过致电Scanner
,您可以询问scan.hasNext()
是否有下一个令牌。这与询问是否有下一行不同。简单来说,令牌是一系列非空白字符。 (这实际上已经过度简化,但对于这种情况已经足够了。)当您使用Scanner
读取行时,您实际上想要询问它是否有行,因此您想使用 Scanner
而不是scan.hasNextLine()
。您的scan.hasNext()
也是如此。
您的方法scan2
实际上很长。理想情况下,方法只做一件事。这保持了可维护性。当然,如果在特定情况下更简洁,只有一个方法可以内置一切,但有一个小方法(或函数/程序/操作/闭包)只做一件事可以让更多的重用,更容易测试和更好的源代码可读性(只要你给你的方法好名字。)
答案 1 :(得分:0)
为了停止从控制台输入,我点击了ctrl + z。这是最好的,也是标准的做法吗?
绝对不是。您应该让程序停止提示您的代码。
另外,如果我需要在线之间输入空格,我该怎么做?它只是忽略了空白行。
您只需执行以下操作即可决定拥有“break-command”:
这是一个开箱即用的解决方案,与hasNext()
和hasNextLine()
的传统用法不同。
String breakCommand = "~end"; //Set a string combination which is unlikely to be used
Scanenr scan2 = new Scanner(System.in);
String input = "";
do{
input = scan2 .nextLine();
}while(!input.equals(breakCommand));
//^Keeps prompting for input from console as long as input is not "~end".
在这种情况下,您可以输入所需的任何(breakCommand除外)(包括空格和新行)。
答案 2 :(得分:0)
我完全改写了你的程序并做了各种改变 我希望你从那段代码中学到一些东西。 :-)
public static void main(String[] args) {
File f = new File("File.txt");
// I am defining the Writer, the Scanner and the Reader inside a try with resources statement.
// This assures that all streams are closed properly even if an exception occurs.
// Also I am not giving the file directly to the PrintWriter directly but instead putting a BufferedWriter in between.
// This makes it so that if content is printed, it is not immediately written to the File, but instead is being buffered.
// In general this is more efficient because the file has to be only opened once.
try (PrintWriter fileWriter = new PrintWriter(new BufferedWriter(new FileWriter(f)));
Scanner inputScanner = new Scanner(System.in);
// Instead of using a Scanner for reading the File I am using a BufferedReader.
// This one also buffers the content so it only has to be opened once.
BufferedReader fileReader = new BufferedReader(new FileReader(f))) {
System.out.println("Please enter the input:\n");
String line;
// In addition to using Ctrl-Z you can terminate the input by writing the line "exit."
while (inputScanner.hasNextLine() && !(line = inputScanner.nextLine()).equals("exit")) {
fileWriter.println(line);
}
// This line makes sure that all content that is saved inside the BufferedWriter gets written to the file before we read it again.
fileWriter.flush();
System.out.println("****************************************");
System.out.println("Displaying output:\n");
// Here I am simply reading the file using the BufferedReader.
// Also I am reusing the variable line because it is no longer needed to scan the input.
while ((line = fileReader.readLine()) != null) {
System.out.println(line);
}
}
catch (IOException e) {
e.printStackTrace();
}
}
你的空白线似乎也适合我。也许这是你的IDE做奇怪的事情。 (我正在使用eclipse)