输入与输出
作者:互联网
输入与输出
读取输入
Scanner对象
将输出打印到“标准输出流”(即控制台窗口)是一件非常容易的事情,只要调用System.out.println即可。然而,读取“标准输入流”System.in就没有那么简单了。要想通过控制台进行输入,首先需要构造一个与“标准输入流”
System.in
关联的Scanner对象。
Scanner in = new Scanner(System.in);
nextline方法
现在,就可以使用Scanner类的各种方法读取输入了。例如,nextline方法将读取一行输入。
System.out.print("What is your name?");
String name = in.nextline();
next方法
在这里,使用nextLine方法是因为在输入行中有可能包含空格。要想读取一个单词(以空白符作为分隔符),可以调用
String firstName = in.next();
nextInt方法
要想读取一个整数,就调用nextInt方法。
System.out.print("How old are you?");
int age = in.nextInt();
nextDouble方法
与此类似,要想读取下一个浮点数,就调用nextDouble方法。
最后,在程序的最前面添加一行代码:
import java.util.*;
Scanner类定义在java.util包中。当使用的类不是定义在基本java.lang包中时,一定要使用import指令导入相应的包。
注释
因为输入是可见的,所以Scanner类不适用于从控制台读取密码。Java 6特别引入了Console类来实现这个目的。要想读取一个密码,可以使用下列代码:
Console cons = System.console();
String username = cons.readLine("User name:");
char[] passwd = cons.readPassword("Password:");
为安全起见,返回的密码存放在一个字符数组中,而不是字符串中。在对密码处理完成之后,应该马上用一个填充值覆盖数组元素。
采用Console对象处理输入不如采用Scanner方便。必须每次读取一行输入,而没有能够读取单个单词或数值的方法。
程序示例
import java .util.*;
public class HuangZiHanTest
{
public static void main(String[] args)
{
Scanner huangzihan_in=new Scanner(System.in);
System.out.println("你叫什么名字?");
String huangzihan_name=huangzihan_in.nextLine();
System.out.println("你今年几岁?");
int huangzihan_age=huangzihan_in.nextInt();
System.out.println("你多高?(m)");
double huangzihan_tall=huangzihan_in.nextDouble();
System.out.println("你好,"+huangzihan_name+",今年你"+huangzihan_age+"岁,身高"+huangzihan_tall+"m。");
}
}
运行结果
你叫什么名字?
黄子涵
你今年几岁?
27
你多高?(m)
1.77
你好,黄子涵,今年你27岁,身高1.77m。
格式化输出
Systen.out.print(x)
可以使用语句
Systen.out.print(x)
将数值x输出到控制台。这条命令将以x的类型所允许的最大非0数位个数打印输出x。例如:
double x = 10000.0/3.0;
System.out.print(x);
打印
3333.3333333333335
如果希望显示美元、美分数,这就会有问题。
程序示例
public class HuangZiHanTest
{
public static void main(String[] args)
{
double huangzihan_x = 10000.0/3.0;
System.out.print(huangzihan_x);
}
}
运行结果
3333.3333333333335
printf方法
在早期的Java版本中,格式化数值曾引起过一些争议。庆幸的是,Java 5沿用了C语言函数库中的printf方法。例如,调用
System.out.printf("%8.2f",x);
会以一个字段宽度(field
width)打印x:这包括8个字符,另外精度为小数点后2个字符。也就是说,这会打印一个前导的空格和7个字符,如下所示:
3333.33
程序示例
public class HuangZiHanTest
{
public static void main(String[] args)
{
double huangzihan_x = 10000.0/3.0;
System.out.println(huangzihan_x);
System.out.println();
System.out.printf("%8.2f",huangzihan_x);
}
}
运行结果
3333.3333333333335
3333.33
printf提供多个参数
可以为printf提供多个参数,例如:
System.out.printf("Hello,%s,Next year,you'll be %d",name,age);
每一个以%字符开始的格式说明符都用相应的参数替换。格式说明符尾部的转换符指示要格式化的数值的类型:f表示浮点数,s表示字符串,d表示十进制整数。表(用于printf的转换符)列出了所有转换符。
程序示例
import java .util.*;
public class HuangZiHanTest
{
public static void main(String[] args)
{
Scanner huangzihan_in=new Scanner(System.in);
System.out.println("你叫什么名字?");
String huangzihan_name=huangzihan_in.nextLine();
System.out.println("你今年几岁?");
int huangzihan_age=huangzihan_in.nextInt();
System.out.println("你多高?(m)");
double huangzihan_tall=huangzihan_in.nextDouble();
System.out.println("你好,"+huangzihan_name+",今年你"+huangzihan_age+"岁,身高"+huangzihan_tall+"m。");
System.out.printf("你好,%s,今年,你%d岁啦!",huangzihan_name,huangzihan_age);
}
}
运行结果
你叫什么名字?
黄子涵
你今年几岁?
27
你多高?(m)
1.77
你好,黄子涵,今年你27岁,身高1.77m。
你好,黄子涵,今年,你27岁啦!
用于printf的转换符
转换符 | 类型 | 示例 |
---|---|---|
d | 十进制整数 | 159 |
x | 十六进制整数 | 9f |
o | 八进制整数 | 237 |
f | 定点浮点数 | 15.9 |
e | 指数浮点数 | 1.59e+01 |
g | 通用浮点数(e和f中较短的一个) | - |
a | 十六进制浮点数 | 0x1.fccdp3 |
s | 字符串 | Hello |
c | 字符 | H |
b | 布尔 | true |
h | 散列码 | 42628b2 |
tx或Tx | 日期时间(T强制大写) | 已经过时 |
% | 百分号 | % |
n | 与平台有关的行分隔符 | - |
用于printf的标志
另外,还可以指定控制格式化输出外观的各种标志。表(用于printf的标志)列出了所有的标志。例如,逗号标志可以增加分组分隔符。即
System.out.printf("%,.2f",10000.0/3.0);
会打印
3,333.33
可以使用多个标志,例如,"%,(.2f"会使用分组分隔符并将负数括在括号内。
程序示例
public class HuangZiHanTest
{
public static void main(String[] args)
{
double huangzihan_x = 10000.0/3.0;
System.out.println(huangzihan_x);
System.out.println();
System.out.printf("%8.2f",huangzihan_x);
System.out.println();
System.out.printf("%,.2f",10000.0/3.0);
}
}
运行结果
3333.3333333333335
3333.33
3,333.33
用于printf的标志
注释
String.format方法
可以使用s转换符格式化任意的对象。对于实现了Formattable接口的任意对象,将调用这个对象的formatTo方法;否则调用toString方法将这个对象转换为字符串。
可以使用静态的String.format方法创建一个格式化的字符串,而不打印输出:
String message = String.format("Hello,%s.Next year,you'll be %d",name,age);
基于完整性的考虑,下面简略地介绍printf方法中日期与时间的格式化选项。不过你可能会在遗留代码中看到Date类和相关的格式化选项。这个格式包括两个字母,以t开始,以表(日期和时间的转换符)中的任意字母结束。
程序示例
import java .util.*;
public class HuangZiHanTest
{
public static void main(String[] args)
{
Scanner huangzihan_in=new Scanner(System.in);
System.out.println("你叫什么名字?");
String huangzihan_name=huangzihan_in.nextLine();
System.out.println("你今年几岁?");
int huangzihan_age=huangzihan_in.nextInt();
System.out.println("你多高?(m)");
double huangzihan_tall=huangzihan_in.nextDouble();
System.out.println("你好,"+huangzihan_name+",今年你"+huangzihan_age+"岁,身高"+huangzihan_tall+"m。");
System.out.printf("你好,%s,今年,你%d岁啦!",huangzihan_name,huangzihan_age);
System.out.println();
String huangzihan_message = String.format("你好,%s.今年,你%d岁啦!",huangzihan_name,huangzihan_age);
System.out.println(huangzihan_message);
}
}
运行结果
你叫什么名字?
黄子涵
你今年几岁?
27
你多高?(m)
1.77
你好,黄子涵,今年你27岁,身高1.77m。
你好,黄子涵,今年,你27岁啦!
你好,黄子涵.今年,你27岁啦!
打印当前的日期和时间
例如,
System.out.printf("%tc",new Date());
这条语句将用下面的格式打印当前的日期和时间:
Mon Feb 09 18:05:19 PST 2015
程序示例
import java.util.Date;
public class HuangZiHanTest
{
public static void main(String[] args)
{
System.out.printf("%tc",new Date());
}
}
运行结果
周六 7月 03 16:58:14 CST 2021
日期和时间的转换符
索引
从表(日期和时间的转换符)可以看到,某些格式只给出了指定日期的部分信息。例如,只有日期或月份。如果需要多次提供日期来分别格式化每一部分就太笨拙了。为此,可以用一个格式字符串指示要格式化的参数索引。索引必须紧跟在%后面,并以$终止。例如,
System.out.printf("%1$s %2$tB %2$te,%2$tY","Due date:",new Date());
会打印
Due date:February 9,2015
还可以选择使用<标志。它指示前面格式说明中的参数将被再次使用。也就是说,以下语句将产生与前面语句同样的输出结果:
警告:参数索引值从1开始,而不是从0开始,%1$...对第1个参数格式化。这就避免了与0标志混淆。
程序示例
运行结果
截止日期: 七月 3,2021
截止日期: 七月 3,2021
现在,我们已经了解了printf方法的所有特性。图(格式说明符)给出了格式说明符的语法图。
注释
数字和日期的格式化规则是特定于本地化环境的。例如,在德国,分组分隔符是点号而不是逗号,另外Monday被格式化为Montag。
文件输入与输出
读取文件
要想读取一个文件,需要构造一个Scanner对象,如下所示:
Scanner in =new Scanner(Path.of("myfile.txt"),StandardCharsets.UTF_8);
如果文件名中包含反斜杠符号,就要记住在每个反斜杠之前再加一个额外的反斜杠转义:
"c:\\mydirectory\myfile.txt"
注释
在这里指定了UTF-8字符编码,这对于互联网上的文件很常见(不过并不是普遍适用)。读取一个文本文件时,要知道它的字符编码。如果省略字符编码,则会使用运行这个Java程序的机器的“默认编码”。这不是一个好主意,如果在不同的机器上运行这个程序,可能会有不同的表现。
现在,就可以利用前面介绍的任何一个Scanner方法对文件进行读取。
Printwriter对象
要想写入文件,就需要构造一个Printwriter对象。在构造器(constructor)中,需要提供文件名和字符编码:
PrintWriter out = new PrintWriter("myfile.txt",StandardCharsets.UTF_8);
如果文件不存在,创建该文件。可以像输出到System.out一样使用print、println以及printf命令。
警告
可以构造一个带有字符串参数的Scanner,但这个Scanner会把字符串解释为数据,而不是文件名。例如,如果调用:
Scanner in = new Scanner("myfile.txt"); //ERROR?
这个scanner会将参数看作包含10个字符('m'、'y'、'f'等)的数据。
注释
当指定一个相对文件名时,例如,"myfile.txt""mydirectory/myfile.txt"或"../myfile.txt",文件位于相对于Java虚拟机启动目录的位置。如果在命令行方式下执行以下命令启动程序:
java MyProg
启动目录就是命令解释器的当前目录。然而,如果使用集成开发环境,那么启动目录将由IDE控制。可以使用下面的调用找到这个目录的位置:
String dir=System.getProperty("user.dir");
如果觉得定位文件太麻烦,可以考虑使用绝对路径名,例如:
"C:\\mydirectory\\myfile.txt"
或者
"/home/me/mydirectory/myfile.txt"
正如读者所看到的,访问文件与使用System.in和System.out一样容易。要记住一点:如果用一个不存在的文件构造一个Scanner,或者用一个无法创建的文件名构造PrintWriter,就会产生异常。Java编译器认为这些异常比“被零除”异常更严重。至于现在,只需要告诉编译器:你已经知道有可能出现“输入/输出”异常。这需要在main方法中用throws子句标记,如下所示:
public static void main(String[] args) throws IOException
{
Scanner in=new Scanner(Path.of("myfile.txt"),StandardCharsets.UTF_8);
...
}
注释
当采用命令行方式启动一个程序时,可以利用shell的重定向语法将任意文件关联到System.in和System.out:
java MyProg <myfile.txt> output.txt
这样,就不必担心处理IOException异常了。
标签:输出,Scanner,System,huangzihan,printf,println,输入,out 来源: https://www.cnblogs.com/Huang-zihan/p/15183236.html