缓冲流
缓冲流是套接在响应的节点流之上,对续写的数据提供缓冲的功能,提高读写的效率,同时增加了一些新方法以介质是硬盘为例,字节流和字符流的弊端:在每一次读写的时候,都会访问硬盘。 如果读写的频率比较高的时候,其性能表现不佳。为了解决以上弊端,采用缓存流。缓存流在读取的时候,会一次性读较多的数据到缓存中,以后每一次的读取,都是在缓存中访问,直到缓存中的数据读取完毕,再到硬盘中读取。
package com.yan3;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.Reader;
/*
* ### 缓冲流
* 缓冲流是套接在响应的节点流之上,对续写的数据提供缓冲的功能,提高读写的
* 效率,同时增加了一些新方法
*
* 以介质是硬盘为例,字节流和字符流的弊端:在每一次读写的时候,都会访问硬
* 盘。 如果读写的频率比较高的时候,其性能表现不佳。为了解决以上弊端,采用
* 缓存流。
*
* 缓存流在读取的时候,会一次性读较多的数据到缓存中,以后每一次的读取,都
* 是在缓存中访问,直到缓存中的数据读取完毕,再到硬盘中读取。
*/
public class Test5 {
public static void main(String[] args) {
long start = System.currentTimeMillis();
// useReader(); //207ms
useReader2(); // 152ms
long end = System.currentTimeMillis();
System.out.println(end - start + "ms");
}
public static void useReader() {
try (Reader r = new FileReader("data/calcCharNum.txt")) {
while (true) {
int kk = r.read();
if (kk == -1) {
break;
}
System.out.print((char) kk);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void useReader2() {
try (Reader r = new BufferedReader(new FileReader("data/calcCharNum.txt"))) {
while (true) {
int kk = r.read();
if (kk == -1) {
break;
}
System.out.print((char) kk);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
构造方法
- BufferedReader(Reader)不定义缓存大小,默认8192
- BufferedReader(Reader in, int size)size为自定义缓冲区的大小
- BufferedWriter(Writer)
- BufferedWriter(Writer out, int size)size为自定义缓冲区的大小
- BufferedInputStream(InputStream)
- BufferedInputStream(InputStream in, int size)size为自定义缓冲区的大小
- BufferedOutputStream(OutputStream)
- BufferedOutputStream(OuputStream out, int size)size为自定义缓冲区的大小
缓冲输入流的方法
BuffedReader 提供了一个方法 readLine():String ,但是 BufferedInputStream 中并没有这个
- BufferedReader提供了readLine方法用于读取一行字符串,以\r或\n分割(换行符)
如果读取内容为null,则表示读取到了流的末尾readLine方法会自动剔除本行内容末尾的换行符
- BufferedWriter提供了newLine方法用于写入一个行分隔符
对于输出的缓冲流,写入的数据会先在内存中缓存,使用 flush 方法会使内存中的数据立即写出
键盘录入
System.in:InputStream 用于指代系统默认的输入设备 — 键盘方法 read():int 可以实现代码执行到这里则会阻塞等待,只要输入数据为止
package com.yan3;
import java.io.BufferedReader;
import java.io.InputStreamReader;
/*
* 缓冲输入流的方法
*
* BuffedReader提供了一个方法readLine():String,但是BufferedInputStream中并
* 没有这个
*
* - BufferedReader提供了readLine方法用于读取一行字符串,以\r或\n分割(换行符)
- 如果读取内容为null,则表示读取到了流的末尾
- readLine方法会自动剔除本行内容末尾的换行符
- BufferedWriter提供了newLine方法用于写入一个行分隔符
对于输出的缓冲流,写入的数据会先在内存中缓存,使用flush方法会使内存中的
数据立即写出
*/
public class Test7 {
public static void main(String[] args) throws Exception {
// 要求用户输入一个合法的整型数
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int age = 0;
while (true) {
String ss = br.readLine();// BufferedReader提供的特殊方法,用于实现整行读取
try {
age = Integer.parseInt(ss.trim());
if (age >= 18 && age <= 65) {
break;
} else {
System.out.println("年龄范围不合法!!!");
}
} catch (Exception e) {
System.out.println("格式错误!");
}
}
System.out.println("合法的年龄输入为 " + age);
}
}
使用缓存流并没有添加什么额外方法,只是它能够在执行过程中自动引入缓存,从而提高执行效率过滤流使用必须有对应的节点流,因为过滤流是装饰节点流,不是有具体的操作目标new BufferedReader(new FileReader(..)) 或 new BufferedWriter(new FileWriter()) 实际上使用的还是Reader/Writer那些方法,这里从编码的角度上说,没有任何区别,但是从执行性能上说,比FileReader/Writer效率高,可以减少磁盘的读写次数执行 close 方法会自动关闭被装饰的对象,所以不需要再关闭 FileReader 和 FileWriter执行 flush 会自动刷新数据到节点流上,但是并没有执行关闭流。针对输出流关闭时会自动先 flush 缓存再执行关闭
使用java的输入/输出流技术将一个文本文件的内容按行读出,每读出一行就顺序添加行号,并写入到另一个文件中。
package com.yan4;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
/*
* 使用java的输入/输出流技术将一个文本文件的内容按行读出,每
* 读出一行就顺序添加行号,并写入到另一个文件中。
*/
public class Exec01 {
public static void main(String[] args) throws Exception {
try (BufferedReader br = new BufferedReader(new FileReader("src/com/yan1/Test1.java"));
BufferedWriter bw = new BufferedWriter(new FileWriter("data/out1.txt"))) {
int cc = 0;
while (true) {
String ss = br.readLine();
if (ss == null)
break;
bw.write(++cc + "\t");
bw.write(ss);
bw.newLine();
}
}
}
}
数据流
DataInputStream 和 DataOutputStream 两个类创建的对象分别被称为数据输入流和数据输出流。这是很有用的两个流,它们允许程序按与机器无关的风格读写Java 数据。所以比较适合于网络上的数据传输。这两个流也是过滤器流,常以其它流如InputStream 或 OutputStream 作为它们的输入或输出DataInputStram和 DataOutputStream 分别继承自 InputStream 和 OuputStream ,属于过滤流,需要分别套接在InputStream 和 OutputStream 类型的节点流上
- 只有字节流,没有对应的字符流
DataInputStream和DataOutputStream 提供了可以存取与机器无关的 Java 原始类型数据的方法DataInputSteram 和 DataOutputStream 构造方法为
- DataInputStream(InputStream)
- DataOutputStream(OutputStream)
用数据输出流将斐波那契级数的前二十项存放在fei.dat文件中。
package com.yan3;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
/*
* 用数据输出流将斐波那契级数的前二十项存放在fei.dat文件中
*/
public class Test81 {
public static void main(String[] args) throws Exception {
DataOutputStream dos = new DataOutputStream(new FileOutputStream("data/fei.dat"));
for (int i = 0; i < 20; i++) {
int num = fei(i);
dos.writeInt(num);
}
dos.close();
DataInputStream dis = new DataInputStream(new FileInputStream("data/fei.dat"));
try {
while (true) {
int kk = dis.readInt();
System.out.print(kk + "\t");
}
} catch (EOFException e) {
System.out.println("文件读取完毕");
}
dis.close();
}
public static int fei(int pos) {
if (pos == 0) {
return 0;
}
if (pos == 1) {
return 1;
}
return fei(pos - 1) + fei(pos - 2);
}
}
从fei.dat文件中读出数列,显示输出,并计算累加和
package com.yan3;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
/*
* 1、用数据输出流将菲波那契级数列的前二十项存放内存中。
* 2、从内存中读出数列,显示输出,并计算累加和。
*/
public class Test82 {
public static void main(String[] args) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
for (int i = 0; i < 20; i++) {
int num = fei(i);
dos.writeInt(num);
}
byte[] data = baos.toByteArray();
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(data));
int sum = 0;
while (true) {
try {
int kk = dis.readInt();
sum += kk;
System.out.println(kk);
} catch (EOFException e) {
System.out.println("读取完毕!");
break;
}
}
System.out.println("累加和为 " + sum);
}
public static int fei(int n) {
if (n < 0)
throw new IllegalArgumentException();
if (n == 0)
return 0;
if (n == 1)
return 1;
return fei(n - 1) + fei(n - 2);
}
}
产生5000个1~9999之间的随机整数,将其存入二进制数据文件a.data中
package com.yan4;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Random;
/*
* 作业题:
* 练习:编写一个程序实现以下功能:
* (1)产生5000个1~9999之间的随机整数,将其存入二进制数据文件a.data中。
* (2)从文件中读取所有整数(文件中都是整数,但是个数未知),并计算其最大值、最小值和平均值并输出结果。
*/
public class Exec02 {
public static void main(String[] args) throws Exception {
DataOutputStream dos = new DataOutputStream(new FileOutputStream("data/a.data"));
Random r = new Random();
for (int i = 0; i < 5000; i++) {
dos.writeInt(r.nextInt(9999));
}
DataInputStream dis = new DataInputStream(new FileInputStream("data/a.data"));
for (int i = 0; i < 5000; i++) {
int kk = dis.readInt();
System.out.print(kk + "\t");
}
dis.close();
}
}
打印流
PrintStream 和 PrintWriter 都属于输出流,分别针对字节和字符PrintWriter 和 PrintStream 都提供了重载的 print 和 println 方法用于输出多种类型数据print(Object):void
- 输出引用类型,实际上是调用对象的toString方法转换为String进行输出
println 表示输出后自动换行
- PrintWriter和PrintStream的输出操作不会抛出异常,用户通过检测错误状态获取错误信息
- PrintWriter和PrintStream有自动的flush功能 textOut.flushBuffer();
PrintWriter(Writer)PrintWriter(Writer out, boolean autoFlush) 自动刷新 ----println
package com.yan3;
import java.io.FileWriter;
import java.io.PrintWriter;
/*
* 打印流 println和print
*
* PrintStream和PrintWriter都属于输出流,分别针对字节和字符
*
* PrintWriter和PrintStream都提供了重载的print和println方法
* 用于输出多种类型数据
*
* print(Object):void
- 输出引用类型,实际上是调用对象的toString方法转换为String进行输出
```java
public void println(Object x) {
String s = String.valueOf(x); //调用String类中的静态方法将object类型的数据转换为字符串
synchronized (this) {
print(s);
newLine(); //print('\n')
}
}
//String中的valueOf方法的定义
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString(); //如果输出对象非空,则调用对象的toString方法
}
```
println表示输出后自动换行
- PrintWriter和PrintStream的输出操作不会抛出异常,用户通过检测错误状态获取错误信息
- PrintWriter和PrintStream有自动的flush功能`textOut.flushBuffer();`
PrintWriter(Writer)
PrintWriter(Writer out, boolean autoFlush)自动刷新----println
*/
public class Test9 {
public static void main(String[] args) throws Exception {
// 注意实际上允许直接new PrintWriter(System.out)
PrintWriter pw = new PrintWriter(new FileWriter("data/out4.dat"));
for (int i = 0; i < 10; i++) {
pw.println(i);
// pw.print(i);
}
pw.close();
}
}