1.打印流
如果想要通过程序实现内容的输出,核心的本质一定要依靠OutputStream
类完成,但是OutputStream
类有一个缺点,,这个类的输出操作功能有限:public void write(byte[] b) throws IOException
,所有的数据一定要转为字节数组才能输出。
【范例】打印流设计思想:
package demo;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
File file = new File("d:" + File.separator + "mldn.txt");
PrintUtil pu = new PrintUtil(new FileOutputStream(file));
pu.println("姓名:小小");
pu.print("年龄:");
pu.println(78);
}
}
class PrintUtil implements AutoCloseable{ //实现一些常用数据的输出
private OutputStream output; //不管如何进行输出操作,核心的就是使用OutputStream
public PrintUtil(OutputStream output) {//由外部决定输出的位置
this.output = output;
}
@Override
public void close() throws Exception {
this.output.close();
}
public void println(long num) {
this.println(String.valueOf(num));
}
public void print(long num) {
this.println(String.valueOf(num));
}
public void print(String str) {
try {
this.output.write(str.getBytes());//输出
} catch (IOException e) {
e.printStackTrace();
}
}
public void println(String str) {
this.print(str + "\n");
}
}
在整个的操作过程之中打印流的设计思想的本质在于:提高已有类的功能,例如:OutputStream是唯一可以实现输出的标准类,应该以其为核心根本,但是或者类数据功能优先,不方便进行各种类型的输出,所以就为它做出一层包装,所以此时采用的设计思想就是“装饰设计模式”。
java.io包里提供有打印流:PrintStream
、PrintWriter
。
PrintStream:
public class PrintStream extends FileterOutputStream implements Appendable, Closeable
- 构造方法:
public PrintStream(OutputStream out);
PrintWriter:
public class PrintStream extends Writer
.- 构造方法:
public PrintWriter(OutputStream out)
、public PrintWriter(Writer out)
;
下面使用PrintWriter来实现数据的输出操作
【范例】
package demo;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
File file = new File("d:" + File.separator + "mldn.txt");
PrintWriter pu = new PrintWriter(new FileOutputStream(file));
pu.println("姓名:小小");
pu.print("年龄:");
pu.println(78);
pu.close();
}
}
从JDK1.5开始PrintWriter类里面追加有格式化输出的操作支持:
public PrintWriter printf(String format, Object...args)
。
【范例】格式化输出
package demo;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
File file = new File("d:" + File.separator + "mldn.txt");
PrintWriter pu = new PrintWriter(new FileOutputStream(file));
String name = "嘿嘿";
int age = 20;
double salary = 72165.654;
pu.printf("姓名: %s、年龄:%d、薪水:%9.2f", name, age, salary);
pu.close();
}
}
比起直接使用OutputStream
类,那么使用PrintWriter
、PrintStream
类的操作更加简单。以后只要是程序进行输出的时候全部使用打印流。
2.System类对IO的支持
System类是一个系统类,而且是一个从头到尾一直都在使用的系统类,系统提供有三个常量:
- 标准输出(显示器):
public static final PrintStream out
; - 错误输出:
public static final PrintStream err
; - 标准输入(键盘):
public static final InputStrem in
。
System.out 和 System.err都是同一种类型的,如下使用的是Eclipse则在使用System.err输出的时候会使用红色字体,而System.out会使用黑色字体。- 修改out的输出位置:
public static void setOut(PrintStream out)
; - 修改err的输出位置:
public static void setErr(PrintStream err)
。
【范例】:修改System.err位置:
- 修改out的输出位置:
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
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);
}
}
}
java.lang.NumberFormatException: For input string: "a"
err则输出到err.txt文件里面了。
在System类里面还提供有一个in的常量,而这个常量对应的是标准输入设备键盘的输入处理,可以实现键盘数据输入。
【范例】实现键盘输入:
package demo;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
InputStream input = System.in;
System.out.println("请输入信息:");
byte [] data = new byte[1025];
int len = input.read(data) ;
System.out.println("输入的内容为:" + new String(data, 0 ,len));
}
}
请输入信息:
I miss you
输入的内容为:I miss you
这样的键盘输入处理本身是有缺陷的,如果长度不足,那么只能接收部分数据,输入就有可能进行重复的输入流数据接收,而且在接收的时候可能还会牵扯到输入中文的情况,如果对于输入的中文处理不当,则会造成乱码。
BufferedReader缓冲输入流
BufferedReader类提供的是一个缓冲字符输入流的概念,也就是说利用BufferedReader
类可以很好的解决输入流数据的读取问题。这个类提供有一个重要的数据:
- 读取一行数据:
public String readLine() throws IOException
;
利用这个类实现键盘输入数据的标准化:
【范例】
package demo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入信息:");
String msg = input.readLine();//接收输入信息
System.out.println("输入内容为:" + msg);
}
}
【范例】接收整型数据进行验证:
package demo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入年龄:");
String msg = input.readLine();//接收输入信息
if(msg.matches("\\d{1,3}")) {//是否由数字组成
int age = Integer.parseInt(msg);
System.out.println("输入的年龄为:" + msg);
}else {
System.out.println("输入内格式有问题:");
}
}
}
请输入年龄:
999
输入的年龄为:999
实际开发中所有的输入数据都是字符串,这样可以方便用户验证和进行字符串的复杂处理。
Scanner扫描类
java.util.Scanner从JDK1.5之后追加的一个程序类,其主要目的是为了解决输入流的访问问题,可以理解为BufferedReader的替代功能类,在Scanner
类里面由如下操作方法;
- 构造:
public Scanner(InputStream source)
; - 判断是否有数据:
public boolean hasNext()
; - 取出数据:
public String next()
; - 设置分隔符:
public Scanner useDelimiter(String pattern)
;
【范例】使用Scanner实现键盘输入
package demo;
import java.util.Scanner;
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
Scanner scan = new Scanner(System.in);
System.out.println("请输入年龄:");
if(scan.hasNextInt()) {//判断是否有整数输入
int age = scan.nextInt();
System.out.println("您的年龄:" + age);
}else {
System.out.println("输入有误!请输入整数!");
}
}
}
还可以正则表示:
package demo;
import java.text.SimpleDateFormat;
import java.util.Scanner;
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
Scanner scan = new Scanner(System.in);
System.out.println("请输入生日:");
if(scan.hasNext("\\d{4}-\\d{2}-\\d{2}")) {//判断是否有整数输入
String str = scan.next("\\d{4}-\\d{2}-\\d{2}");
System.out.println("您的生日:" + new SimpleDateFormat("yyyy-MM-dd").parse(str));
}else {
System.out.println("输入有误!请输入整数!");
}
}
}
Scanner的整体设计要好于BufferedReader,而且要比直接使用InputStream类读取要方便。读取一个文本文件中的所有信息,如果采用的是InputStream类,那么必须依靠内存输出流进行临时数据的保存,还要判断读取的内容是否是换行。
【范例】读取正片文章
package demo;
import java.io.File;
import java.util.Scanner;
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
Scanner scan = new Scanner(new File("d:" + File.separator + "mldn.txt"));
scan.useDelimiter("\n");//设置读取分隔符
while(scan.hasNext()) {
System.out.println(scan.next());
}
scan.close();
}
}
参考资料:
https://edu.aliyun.com/lesson_1012_9014#_9014