要使用标准输入流 System.in
,比较麻烦,首先需要构建一个 Scanner 对象,并与 System.in
关联。
import java.util.Scanner;
Scanner in = new Scanner(System.in);
就可以调用各种 API 来输入
// 读取一行,以换行符结束
String str = in.nextLine();
// 读取一个单词,以空白符作为分隔符,换行符结束
String str = in.next();
// 读取整数
String str = in.nextInt();
// 读取浮点数
String str = in.nextDouble();
// 检测输入中是否还有其他单词
boolean b = in.hasNext();
使用 Scanner 的输入是可见的,可以使用 Console 来读取密码,让密码不可见
Console cons = System.console();
String data = cons.readLine("User name: ");
char[] passwd = cons.readPassword("Password: ");
注意:Console 类仅在 IDE 外部可用,也就是说你必须手动编译代码运行。否则, Console 会返回 null
为了安全起见,返回的密码存放在一维字符数组中,而不是字符串中。在对密码进行处理之后,应该马上用一个填充值覆盖数组元素。
采用 Console 对象处理输入不如采用 Scanner 方便。每次只能读取一行输入,而没有能够读取一个单词或一个数值的方法。但,你可以针对一行输入的内容进行处理,以达到这样的效果。
格式化输出
Java SE 5.0 沿用了 C 语言库函数中的 printf 方法。
转换符:
| 转换符 | 说 明 | 示 例 | | —- | —- | —- |
| %s | 字符串类型 | “NeFeed” |
| %c | 字符类型 | ‘m’ |
| %b | 布尔类型 | true OR false |
| %d | 整数类型(十进制) | 10 |
| %x | 整数类型(十六进制) | FF |
| %o | 整数类型(八进制) | 77 |
| %f | 浮点类型 | 6.66 |
| %a | 十六进制浮点类型 | 0x1.fccdp3 |
| %e | 指数类型 | 6.23e+24 |
| %g | 通用浮点类型(f和e类型中较短的) | 42.5000 |
| %h | 散列码 | ‘A’ -> 41 |
| %% | 百分比类型 | % |
| %n | 换行符 | 相当于”\n”换行作用 |
| %t(日期转换符) | 日期和时间 | 2020-07-24 |
还有一些控制格式化输出的各种标志:
| 标志 | 目的 | 举例 | 结 果 | | —- | —- | —- | —- |
| + | 为正数或者负数添加符号 | (“%+d”,15) | +15 |
| − | 左对齐 | (“n%-5dn”,25) | n25 n |
| 0 | 数字前面补 0 | (“%04d”, 21) | 0021 |
| 空格 | 在整数之前添加指定数量的空格 | (“n% 4dn”, 99) | n 99n |
| , | 以“,”对数字分组(英式数字计数法) | (“%,f”, 9999.99) | 9,999.990000 |
| ( | 使用括号包含负数 | (“%(f”, -99.99) | (99.990000) |
|
#
| 如果是浮点数则包含小数点,如果是 16 进制或 8 进制则添加 0x 或 0
| (“%#x”, 99)
(“%#o”, 99)
(“%#f”, 99)
| 0x63
0143
99.
|
|
<
| 格式化前一个转换符所描述的参数
| (“%f”, 99.45)
(“%d%<x”, 159)
| 99.450000
159 9F
|
| $ | 被格式化的参数索引。注意,参数索引从 1 开始 | (“%1$d %1$x”, 159) | 159 9F |
可以使用 %s 转换符格式化任意的对象。对于任意实现了 Formattable 接口的对象都将调用 formatTo 方法;否则将调用 toString 方法。
可以使用静态的String.format方法创建一个格式化的字符串,而不打印输出
String message = String.format("Hello, %s. Next year, you'll be %d", name, age);
更多内容可以看 文档 和下面这张图来规范使用 printf()
许多格式化规则是本地环境特有的。例如,在德国,组分隔符是句号而不是逗号,Monday 被格式化为 Montag。
文件输入与输出
可以使用 Scanner 来进行文件读取。Scanner 读取文件,需要 File 对象来进行构造:
// 抛出 IOException 异常
public static void main(String[] args) throws IOException {
Scanner in = new Scanner(Paths.get("myfile.txt"), "UTF-8");
while(in.hasNextLine()) {
System.out.println(in.nextLine());
}
}
写入文件,就要构造 PrintWriter 对象,与 Scanner 不同,它只需要提供文件名:
PrintWriter out = new PrintWriter("myfile.txt", "UTF-8");
如果文件不存在,则创建该文件。
如果,你像 PrintWriter 来构建 Scanner 是不会报错的,因为这是 Scanner 允许的,Scanner 会将字符串解释为数据,而不是文件名:
Scanner in = new Scanner("myfile.txt");
System.out.println(in.nextLine()); // output: myfile.txt
最后来说一下文件名的格式和文件的相对路径。
在 Linux 中,文件路径有一种写法:/home/me/mydirectory/myfile.txt
。
但在 Windows 中,可以有多种写法:C:\\mydirectory\\myfile.txt
or C:/mydirectory/myfile
or C:\\mydirectory/myfile
。
可以看到,在 Windows 中,不仅可以使用 Windows 自身的写法,还可以使用 Linux 的写法,甚至可以将两者融合。需要注意的是 Windows 写法中,反斜杠需要考反斜杠转移,写起来比较繁琐。
还有一个奇淫技巧,如果你当前文件目录在 D 盘,路径
/mydirecotry/myfile
等于D:\mydirecotry\myfile
。了解一下即可。
你在命令行中运行 Java 文件时,该启动路径就是你当前所在的路径。但是在 IDE 中,就可能不是这样的。个人实测,在 IDEA 中,你的启动路径就是你当前打开的项目路径,比如,你现在打开的是,D:\language\java
这个项目,你运行的是 D:\language\java\src\Welcome.java
这个文件,它还是会将启动路径定到 D:\language\java
这个路径上。
当然,如果不知道启动路径,可以用下面的方式来查看:
System.out.println(System.getProperty("user.dir"));
IDEA 启动路径的一个例子
我的项目代码在 D:\language\java
中,树形图为:
java
├── java.iml
└── src
├── Main.java
└── myfile.txt
我现在运行 Main.java 读取 myfile.txt
中的内容,对于文件路径有两种方式:绝对路径和相对路径
- 绝对路径
// 因为当前目录在 D 盘,所以还可以这样写。但如果是别的盘,就不能这样写
// Path path = Paths.get("/language/java/src/myfile.txt");
Path path = Paths.get("D:\\language\\java\\src\\myfile.txt");
// or D:/language/java/src/myfile.txt
Scanner in = new Scanner(path, "UTF-8");
System.out.println(in.nextLine());
while(in.hasNextLine()) {
System.out.println(in.nextLine());
}
- 相对路径
// 因为启动目录是 D:\language\java, 所以这里必须加上 src
// 如果直接写 myfile.txt, IDEA 会找 D:\language\java\myfile.txt 这个文件
Path path = Paths.get("src/myfile.txt");
// or src\\myfile.txt
Scanner in = new Scanner(path, "UTF-8");
System.out.println(in.nextLine());
while(in.hasNextLine()) {
System.out.println(in.nextLine());
}