Java 标准输入/输出/错误流
Java IO教程 - Java标准输入/输出/错误流
我们可以使用System.out和System.err对象引用,只要我们可以使用OutputStream对象。
我们可以使用System.in对象,只要我们可以使用InputStream对象。
System类提供了三个静态设置器方法setOut(),setIn()和setErr(),以用您自己的设备替换这三个标准设备。
要将所有标准输出重定向到一个文件,我们需要通过传递一个代表我们文件的PrintStream对象来调用setOut()方法。
import java.io.PrintStream; import java.io.FileOutputStream; import java.io.File; public class Main { public static void main(String[] args) throws Exception { File outFile = new File("stdout.txt"); PrintStream ps = new PrintStream(new FileOutputStream(outFile)); System.out.println(outFile.getAbsolutePath()); System.setOut(ps); System.out.println("Hello world!"); System.out.println("Java I/O is cool!"); } }
上面的代码生成以下结果。
标准输入流
我们可以使用System.in对象从标准输入设备(通常是键盘)读取数据。
当用户输入数据并按Enter键时,输入的数据变得可用,read()方法每次返回一个字节的数据。

以下代码说明如何读取使用键盘输入的数据。\n是Windows上的新行字符。
import java.io.IOException; public class EchoStdin { public static void main(String[] args) throws IOException { System.out.print("Please type a message and press enter: "); int c = "\n"; while ((c = System.in.read()) != "\n") { System.out.print((char) c); } } }
由于System.in是InputStream的一个实例,我们可以使用任何具体的装饰器从键盘读取数据;例如,我们可以创建一个BufferedReader对象,并从键盘读取数据一行一次作为字符串。
上面的代码生成以下结果。
例子
以下代码说明如何将System.in对象与BufferedReader一起使用。程序不断提示用户输入一些文本,直到用户输入Q或q退出程序。
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String text = "q"; while (true) { System.out.print("Please type a message (Q/q to quit) and press enter:"); text = br.readLine(); if (text.equalsIgnoreCase("q")) { System.out.println("We have decided to exit the program"); break; } else { System.out.println("We typed: " + text); } } } }
如果我们想要标准输入来自一个文件,我们必须创建一个输入流对象来表示该文件,并使用System.setIn()方法设置该对象,如下所示。
FileInputStream fis = new FileInputStream("stdin.txt"); System.setIn(fis); // Now System.in.read() will read from stdin.txt file
上面的代码生成以下结果。
标准错误设备
标准错误设备用于显示任何错误消息。Java提供了一个名为System.err的PrintStream对象。我们使用它如下:
System.err.println("This is an error message.");
Java 控制台
Java IO教程 - Java控制台
控制台类的目的是使Java程序和控制台之间的交互更容易。
Console类是java.io包中的一个实用程序类,用于访问系统控制台。
控制台不能保证在所有机器上的Java程序中可访问。例如,如果您的Java程序作为服务运行,则不会有控制台与JVM相关联。
我们通过使用System类的静态console()方法获得控制台类的实例,如下所示:
Console console = System.console(); if (console != null) { console.printf("Console is available.") }
控制台类有一个printf()方法,用于在控制台上显示格式化的字符串。我们还在PrintStream类中有一个printf()方法来写入格式化的数据。
以下代码说明如何使用控制台类。
程序提示用户输入用户名和密码。如果用户输入password letmein,程序将打印一条消息。
import java.io.Console; public class Main { public static void main(String[] args) { Console console = System.console(); if (console != null) { console.printf("Console is available.%n"); } else { System.out.println("Console is not available.%n"); return; // A console is not available } String userName = console.readLine("User Name: "); char[] passChars = console.readPassword("Password: "); String passString = new String(passChars); if (passString.equals("letmein")) { console.printf("Hello %s", userName); } else { console.printf("Invalid password"); } } }
上面的代码生成以下结果。
Java 扫描器
Java IO教程 - Java扫描器
要从标准输入读取数字,我们必须将其读取为字符串并将其解析为数字。
java.util包中的Scanner类根据模式读取并解析基本类型和字符串中的文本。
文本源可以是InputStream,文件,String对象或可读对象。
我们可以使用Scanner对象从标准输入System.in中读取原始类型值。
以下代码说明了如何使用Scanner类构建一个简单的计算器来执行加,减,乘和除。
import java.util.Scanner; public class Calculator { public static void main(String[] args) { System.out.println("type something like: 1+3"); Scanner scanner = new Scanner(System.in); double n1 = Double.NaN; double n2 = Double.NaN; String operation = null; try { n1 = scanner.nextDouble(); operation = scanner.next(); n2 = scanner.nextDouble(); double result = calculate(n1, n2, operation); System.out.printf("%s %s %s = %.2f%n", n1, operation, n2, result); } catch (Exception e) { System.out.println("An invalid expression."); } } public static double calculate(double op1, double op2, String operation) { switch (operation) { case "+": return op1 + op2; case "-": return op1 - op2; case "*": return op1 * op2; case "/": return op1 / op2; } return Double.NaN; } }
上面的代码生成以下结果。
Java 令牌
Java IO教程 - Java令牌
Java有一些实用程序类,让我们将一个字符串分解成称为令牌的部分。
我们通过定义分隔符字符来定义被认为是令牌的字符序列。
StringTokenizer类位于java.util包中。 StreamTokenizer类位于java.io包中。
StringTokenizer将字符串拆分成令牌,而StreamTokenizer让我们在基于字符的流中访问令牌。
StringTokenizer
StringTokenizer对象根据您对定界符的定义将字符串拆分为标记。它一次返回一个令牌。
我们还可以随时更改分隔符。我们可以通过指定字符串并接受默认分隔符来创建一个StringTokenizer,它是空格,制表符,换行符,回车符和换行符(“\t \n \r \f”)如下:
StringTokenizer st = new StringTokenizer("here is my string");
我们可以在创建StringTokenizer时指定自己的分隔符,如下所示:下面的代码使用空格,逗号和分号作为分隔符。
String delimiters = " ,;"; StringTokenizer st = new StringTokenizer("my text...", delimiters);
我们可以使用hasMoreTokens()方法来检查是否有更多的令牌和nextToken()方法从字符串中获取下一个令牌。
我们还可以使用String类的split()方法将字符串拆分为基于分隔符的令牌。
split()方法接受正则表达式作为分隔符。
以下代码显示如何使用StringTokenizer和String类的split()方法。
import java.util.StringTokenizer; public class Main { public static void main(String[] args) { String str = "This is a test, this is another test."; String delimiters = " ,"; // a space and a comma StringTokenizer st = new StringTokenizer(str, delimiters); System.out.println("Tokens using a StringTokenizer:"); String token = null; while (st.hasMoreTokens()) { token = st.nextToken(); System.out.println(token); } } }
上面的代码生成以下结果。
StreamTokenizer
要根据标记的类型区分标记,请使用StreamTokenizer类。
import static java.io.StreamTokenizer.TT_EOF; import static java.io.StreamTokenizer.TT_NUMBER; import static java.io.StreamTokenizer.TT_WORD; import java.io.IOException; import java.io.StreamTokenizer; import java.io.StringReader; public class Main { public static void main(String[] args) throws Exception { String str = "This is a test, 200.89 which is simple 50"; StringReader sr = new StringReader(str); StreamTokenizer st = new StreamTokenizer(sr); try { while (st.nextToken() != TT_EOF) { switch (st.ttype) { case TT_WORD: /* a word has been read */ System.out.println("String value: " + st.sval); break; case TT_NUMBER: /* a number has been read */ System.out.println("Number value: " + st.nval); break; } } } catch (IOException e) { e.printStackTrace(); } } }
该程序使用StringReader对象作为数据源。我们可以使用FileReader对象或任何其他Reader对象作为数据源。
重复调用StreamTokenizer的nextToken()方法。它填充StreamTokenizer对象的三个字段:ttype,sval和nval。ttype字段指示已读取的令牌类型。
以下是类型字段的四个可能的值:
领域 | 意义 |
---|---|
TT_EOF | 已达到流的结尾。 |
TT_EOL | 已达到行尾。 |
TT_WORD | 字(字符串)已从流中读取为令牌。 |
TT_NUMBER | 数字已从流中读取为令牌。 |
如果ttype具有TT_WORD,则字符串值存储在其字段sval中。
如果返回TT_NUBMER,其数值存储在nval字段中。
上面的代码生成以下结果。