内容学习于:edu.aliyun.com
在java.io包里面最为原始的输出支持的操作方法是: OutputStream.write()、 Writer.write(),但是这两个操作方法实际上都有问题,功能设计上不足,因为这两个操作只支持字符串或字节数组的输出,但是从实际的开发来讲,输出的操作可能有各种数据类型。现在假设说要求你设计一一个类,这个类可以实现各种数据类型的输出。
class PrintUtil implements AutoCloseable {
private OutputStream outputStream;
public PrintUtil(OutputStream outputStream) {
this.outputStream = outputStream;
}
public void print(String str) {
try {
outputStream.write(str.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
public void println(String str) {
this.print(str + "\r\n");
}
public void print(int num) {
this.print(String.valueOf(num));
}
@Override
public void close() throws Exception {
outputStream.close();
}
}
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
PrintUtil util = new PrintUtil(new FileOutputStream(new File("d:" + File.separator + "mldn.txt")));
util.print("张三");
util.println(",你好");
util.print(20);
util.close();
}
}
此时的代码只是调用的形式简化了,但是本质上并没有发生任何的改变。那么这样的设计思想就称为装饰设计模式。但是既然我们都已经知道OutputStream类的输出操作不方便了,那么Java设计人员也一定明白,那么为此提供了两个输出功能类:PrintStream、PrintWriter, 观察这两个类的定义以及构造方法:
类名称 | 定义 | 构造方法 |
---|---|---|
PrintStream | public class PrintStream extends FilterOutputStream implements Appendable, Closeable | PrintStream(OutputStream out) |
PrintWriter | public class PrintWriter extends Writer | PrintWriter(Writer out) |
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
PrintWriter util = new PrintWriter(new FileOutputStream(new File("d:" + File.separator + "mldn.txt")));
util.print("张三");
util.println(",你好");
util.print(20);
util.close();
}
}
JDK 1.5之后,String 类提供有format(字符串格式化方法,实际上在PrintStream、PrintWriter 类里面也提供有格式化的输出
操作方法: public PrintWriter printf(String format, Object… args)
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
PrintWriter pw = new PrintWriter(new FileOutputStream(new File("d:" + File.separator + "mldn.txt")));
String name = "张三";
int age = 16;
double salary = 8634.96479864;
pw.printf("姓名:%s、年龄:%d、工资:%5.2f", name, age, salary);
pw.close();
}
}
在以后程序进行(非二进制数据)内容输出的时候,优先考虑使用打印流完成,如果有中文建议使用PrintWriter.OutputStream只适合于输出二进制数据,如果是明文的数据一定要使用打印流完成,打印流使用装饰设计模式。
System类是整个在Java学习中最为常见的一一个程序类,实际上在这个类中提供有三个与IO有关的系统常量:
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
try {
Integer.parseInt("a");
}catch (Exception e){
System.out.println(e);
System.err.println(e);
}
}
}
java.lang.NumberFormatException: For input string: “a”
java.lang.NumberFormatException: For input string: “a”
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
System.setErr(new PrintStream(new FileOutputStream(new File("d:"+File.separator+"Err.txt"))));
try {
Integer.parseInt("a");
}catch (Exception e){
System.out.println(e);
System.err.println(e);
}
}
}
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
InputStream in = System.in;//该输入流为键盘输入流
System.out.println("请输入内容:");
byte [] data = new byte[1024];
int len = in.read(data);
System.out.println("输入的内容为:" + new String(data,0,len));
}
}
请输入内容:
hadk’
输入的内容为:hadk’
此时虽然实现了键盘数据的输入处理操作,但是这种操作却存在有如下的问题:
InputStream类在进行读取时所存在的一系列问题:
所以针对于文本数据(可能是文件中,也可能是键盘输入)的读取,在Java里面提供有一个新的支持类: BufferedReader(缓冲区字符输入流)。
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入内容:");
String msg = br.readLine();
System.out.println("输入的内容为:" + msg);
}
}
输入的内容为:abc
在Java里面并没有提供有像其它语言那样简单的键盘数据输入支持,它的输入操作一定要在掌握IO之后才可以正常的使用,另外以上在进行数据接收的时候使用的是String型进行接收,那么这样就可以继续使用String类中提供的各种方法进行数据处理。
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入内容:");
String msg = br.readLine();
if (msg.matches("\\d{1,3}")){
int age = Integer.parseInt(msg);
System.out.println("您的年龄为:" + age);
}else {
System.out.println("请输入正确内容!!");
}
}
}
您的年龄为:55
java.util.Scanner是从JDK1.5之后追加的一个程序类,其主要的目的是为了解决输入流的访问问题的,可以理解为BufferedReader的替代功能类,在Scanner类里面有如下几种操作方法:
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入您的年龄:");
if (scanner.hasNextInt()){//判断是否有整数输入
int age = scanner.nextInt();
System.out.println("您的年龄:" + age);
}else {
System.out.println("请输入数字!!!");
}
scanner.close();
}
}
请输入您的年龄:
55
您的年龄:55
使用Scanner输入数据还有一个最大的特点是可以直接利用正则进行验证判断。
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入您的生日:");
if (scanner.hasNext("\\d{4}-\\d{2}-\\d{2}")) {//正则匹配
String str = scanner.next("\\d{4}-\\d{2}-\\d{2}");
System.out.println("生日" + new SimpleDateFormat("yyyy-MM-dd").parse(str));
} else {
System.out.println("请输入生日!!!");
}
scanner.close();
}
}
请输入您的生日:
2000-08-12
生日Sat Aug 12 00:00:00 CST 2000
现在可以发现Scanner的整体设计要好于BufferedReader,而且要比直接使用InputStream类读取要方便。例如,现在 如果要读取一个文本文件中的所有内容信息,如果采用的是InputStream 类,那么就必须依靠内存输出流进行临时数据的保存,随后还需要判断读取的内容是否是换行。
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
Scanner scanner = new Scanner(new File("C:\\Users\\正好\\Desktop\\寒假学习\\2020-1-19"+File.separator+"比较器--笔记.txt"));
while (scanner.hasNext()){
scanner.useDelimiter("\n");//设置分割符
System.out.println(scanner.next());
}
scanner.close();
}
}
在以后的开发过程之中,如果程序需要输出数据一定使用打印流,输入数据使用Scanner (BufferedReader)。