目录
一、缓冲流
1、缓冲流
原始流读数据是不带缓冲区的,缓冲区就是一块内存区域,由于没有缓冲区,它每次传输数据都是基于图中的小书包进行传输,每次能装的数据有限,也就是这个管道能流进来的数据有限,而缓冲流可以将原始流进行包装,变成一个缓冲流,缓冲流自带一个缓冲区(缓冲输入流的数组),缓冲区的大小默认为8KB,它每次能装的数据比较多,每次通过字节流管道向缓冲区装8KB数据存放,当从缓冲区中拿数据时,只需要用桶(数组)取出数据,每次取出一点数据,缓冲区又会将这8KB填满,也就相当于是一个水箱,另一边源源不断的进水,取水时由于有高压所以取水会变快。
缓冲流自带缓冲区,可以提高原始字节流、字符读写流数据的性能
2、字节缓冲流
public static void main(String[] args) {
try(
//创建一个文件字节输入流管道与源文件接通
InputStream is = new FileInputStream("stream-max/src/max1.txt");
//将原始字节输入流管道包装成高级的字节缓冲输入流
InputStream bis = new BufferedInputStream(is);
//创建一个文件字节输出流管道与目标文件接通
OutputStream os = new FileOutputStream("stream-max/src/max2.txt");
//将原始字节输出流管道包装成高级的字节缓冲输出流
OutputStream bos = new BufferedOutputStream(os);
)
{
//创建一个桶
byte[] buffer = new byte[10];
while (bis.read(buffer) != -1){
bos.write(buffer);
}
} catch (Exception e) {
e.printStackTrace();
}
}
缓冲流的桶一般建议1KB足够了,内置的8KB空间,桶越大对缓冲流来说效果越差,
虽然低级流的桶定义的越大,它传输的数据也越多,但是系统效率相对减少,因为桶越大,转满就慢,转满之后倒出去也慢,所以更建议使用缓冲流的1KB桶。
3、字符缓冲流
public static void main(String[] args) {
try(
//创建一个文件字符输入流与源文件接通
Reader r = new FileReader("stream-max/src/max2.txt");
//将低级字符输入流包装成高级的字符输入流
BufferedReader br = new BufferedReader(r);
) {
/*//一次读取一个字符数组
char[] buffer = new char[10];
int len;
while ((len = br.read(buffer)) != -1){
String rs = new String(buffer);
System.out.print(rs);
}*/
//自带方法,一次读取一行
String s = br.readLine();
System.out.println(s);
//按行读经典代码
String s1;
while ((s1 = br.readLine()) != null){
System.out.println(s1);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
//拷贝出师表并恢复顺序
try(
//定义一个缓存输入流管道与源文件接通
/*Reader r = new FileReader("stream-max/src/max1.txt");
BufferedReader br = new BufferedReader(r);*/
BufferedReader br = new BufferedReader(new FileReader("stream-max/src/max1.txt"));
//定义一个缓存输出流管道与源文件接通
/*Writer w = new FileWriter("stream-max/src/max3.txt");
BufferedWriter bw = new BufferedWriter(w);*/
BufferedWriter bw = new BufferedWriter(new FileWriter("stream-max/src/max3.txt"));
) {
//定义字符串集合,将每一行都加进去
List<String> bufferList = new ArrayList<>();
//开始读取数据,按行读
String s;
while ((s = br.readLine()) != null){
bufferList.add(s);
}
//对集合按首字符进行排序,实现对中文排序
List<String> size = new ArrayList<>();
Collections.addAll(size,"一","二","三","四","五","六","七");
//如果以数字字符开头,list会自动排好序
Collections.sort(bufferList, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
//获取o1首字符
String s1 = o1.substring(0,o1.indexOf("、"));
//获取o2首字符
String s2 = o2.substring(0,o2.indexOf("、"));
//获取元素序号 按升序排序
return size.indexOf(s1) - size.indexOf(s2);
}
});
//将集合元素写入新文件
for (String s1 : bufferList) {
bw.write(s1);
bw.newLine();
}
} catch (Exception e) {
e.printStackTrace();
}
}
二、转换流(字节流转字符流)
不同编码读取会存在乱码的问题,使用转化流解决乱码问题。
1、字符输入转换流
public static void main(String[] args) throws Exception {
//用UTF-8读取GBK文件
//1、创建一个文件字节输入流与原始流接通
InputStream is = new FileInputStream("D:\\2ProgramTool\\JavaTest\\date.txt");
//2、将文件原始字节流转为字符流
Reader r = new InputStreamReader(is,"GBK");
//3、将低级的文件字符输入流包装成高级的文件字符输入流
BufferedReader br = new BufferedReader(r);
//读取数据 解决乱码问题
String len;
while ((len = br.readLine()) != null){
System.out.println(len);
}
//关闭管道
br.close();
}
2、字符输入转换流
public static void main(String[] args) throws IOException {
//1、创建一个文件字节输出流管道与源文件接通
OutputStream os = new FileOutputStream("stream-max/src/data1.txt");
//2、将原始文件字节流转换成文件字符流,使用指定的编码对文件输出
Writer w = new OutputStreamWriter(os,"GBK");
//3、将低级的文件字符输出流包装成高级的文件字符输出流
BufferedWriter bw = new BufferedWriter(w);
//写入数据
bw.write("我爱中国1");
bw.write("我爱中国2");
//关闭字符流
bw.close();
}
三、序列化对象
1、对象序列化
为什么要对象序列化?开发中,程序中间处理的对象,如果不将他存起来会造成数据丢失,或者对数据库取数据时,将取出的数据输出到文件中,让下次取数据时可以直接在文件中存取,在数据库中取数据性能差,而在文件中性能更高。
//对象继承Serializable接口
public class Student implements Serializable {
//声明序列化的版本号码
//序列化的版本号与反序列化的版本号必须一致才不会出错
private static final long serialVersionUID = 1;
private String name;
private int age;
private String sex;
...
}
public static void main(String[] args) throws Exception {
//创建学生对象
Student s = new Student("李阳",23,"男");
//对象序列化:使用对象字节输出流包装字节输出流管道
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("stream-max/src/data2.txt"));
//写入学生对象
oos.writeObject(s);
//关闭流
oos.close();
}
2、对象反序列化
transient对象属性不参与序列化
public static void main(String[] args) throws Exception {
//创建高级的字节输入流管道
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("stream-max/src/data2.txt"));
//从文件中读数据 强转成子类
Student s = (Student)ois.readObject();
System.out.println(s);
//关闭管道
ois.close();
}
如果希望对象其中某个属性不参与序列化,可以对该属性设置transient
//对象继承Serializable接口 public class Student implements Serializable { private String name; private int age; //不参与对象序列化,反序列化结果为空 private transient String sex; } //反序列化结果 Student{name='李阳', age=23, sex='null'}
四、打印流
目前最高效的输入流,高效的打印数据到文件中。
public static void main(String[] args) throws Exception {
//创建打印流对象
//可以直接用文件路径,其底层仍然是创建低级文件流对象
PrintStream ps = new PrintStream("stream-max/src/ps.txt");
//声明文件编码
//PrintStream ps = new PrintStream("stream-max/src/ps.txt","GBK");
//打印什么数据就是什么数据
ps.print(89);
ps.println("打印流");
//只支持写字节
ps.write(32);
ps.write(89);
ps.close();
}
public static void main(String[] args) throws Exception {
//创建一个字符打印流对象
//也是 覆盖管道
PrintWriter pw = new PrintWriter("stream-max/src/pw.txt");
//如果不希望覆盖,用追加,使用文件对象构造器
//PrintWriter pw = new PrintWriter(new FileWriter("stream-max/src/pw.txt"));
pw.write("sdcdcs");
pw.println(4342);
pw.close();
}
printStream和printWriter 的区别
打印数据功能相同,printStream支持写字节,printWriter支持写字符
打印流的重定向(自定义输出位置)
五、补充:Properties
public static void main(String[] args) throws Exception {
//一、使用properties把键值对信息存入到属性文件中去
//创建Properties对象
Properties properties = new Properties();
//properties属于map集合,但却脱离map类,setProperties的底层仍然是map集合的put方法
properties.setProperty("金刚山","345");
properties.setProperty("雪山","565");
properties.setProperty("高山","349");
//加入进文件中 store存储键值对数据
properties.store(new FileWriter("stream-max/src/user.properties"),"这里写注释");
//二、使用properties读取属性文件的键值对信息
Properties properties1 = new Properties();
//加载文件属性信息
properties1.load(new FileReader("stream-max/src/user.properties"));
System.out.println(properties1);
//根据键获取值
String s1 = properties1.getProperty("金刚山");
System.out.println(s1);
}
六、补充:IO框架
一、IO框架概述
二、IO框架使用步骤
public static void main(String[] args) throws Exception {
//1、完成文件复制
IOUtils.copy(new FileInputStream("stream-max/src/data1.txt"),
new FileOutputStream("stream-max/src/io.txt"));
//2、文件复制到某个文件夹
FileUtils.copyDirectory(new File("stream-max/src/data1.txt"),
new File("C:/"));
//3、删除文件或文件夹 可以删除非空文件
FileUtils.delete(new File("D:\\2ProgramTool\\新建文件夹"));
//JDK1.7 自己也做了一些代码完成赋值操作:New IO技术 NIO
Files.copy(Path.of("D:\\2ProgramTool\\新建文件夹"),Path.of("D:\\2ProgramTool\\新建文件夹"));
//只能删除空文件夹
Files.deleteIfExists(Path.of("D:\\2ProgramTool\\新建文件夹"));
}