缓冲流和常用的API

缓冲流和API

1.缓冲流

1.1 缓冲流概述
  1. 分类:

    (1)BufferedInputStream 字节缓冲输入流

    (2)BufferedOutputStream 字节缓冲输出流

    (3)BufferedReader 字符缓冲输入流

    (4)BufferedWriter 字符缓冲输入流

  2. 缓冲流是Java中提供的系统缓冲,底层都是一个缓冲数组,根据处理的数据方式不同,提供的数据有字节缓冲数组和字符缓冲数组。

  3. 字节缓冲流,默认的字节数组缓冲区是8KB

    byte[] buffer = new byte[1024 * 8];

  4. 字符缓冲流,默认的字符数组缓冲区是16KB

    char[] buffer = new char[1024 * 8];

  5. 重点

    任何一个缓冲流都没有任何操作文件的能力。读取文件、写入文件数据都是依赖于对应的字节流或字符流。

  6. 缓冲流使用的方法,也是read和write,而且是对应创建当前缓冲流使用的字符流或者字节流的。

  7. 缓冲流减少了CPU通过内存访问磁盘或者说文件的次数,极大地提高了开发效率。IO流操作文件内容都是在缓冲流内部的缓冲数组中,也就是内存中。

1.2 BufferedInputStream 字节缓冲输入流
  1. Constructor构造方法

    BufferedInputStream(InputStream in);
    	这里需要的参数是字节输入流对象
  2. Method成员方法

    int read();
    int read(byte[] buf);
    
    其实就是InputStream中使用的方法
  3. 代码演示

    package com.qfedu.a_buffer;
    
    import java.io.BufferedInputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    
    /*
     * 字节缓冲输入流操作
     */
    public class Demo1 {
    	public static void main(String[] args) throws IOException {
    		// 1. 明确操作文件
    		File file = new File("D:/aaa/1.txt");
    		
    		// 2. 创建对应的FileInputStream对象
    		FileInputStream fis = new FileInputStream(file);
    		
    		// 3. 根据FileInputStream创建对应的BufferedInputStream,给缓冲流提供必要的读写能力
    		BufferedInputStream bis = new BufferedInputStream(fis);
    		
    		// BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("D:/aaa/1.mp4"));
    		// 4. 读取数据
    		System.out.println((char) bis.read()); 
    		System.out.println((char) bis.read()); 
    		System.out.println((char) bis.read()); 
    		System.out.println((char) bis.read()); 
    		System.out.println((char) bis.read()); 
    		
    		byte[] buf = new byte[1024 * 4];
    		int length = -1;
    		
    		while ((length = bis.read(buf)) != -1) {
    			System.out.println(new String(buf, 0, length));
    		}
    		
    		// 5. 关闭资源
    		bis.close();
    	}
    }
1.3 BufferedOutputStream 字节缓冲输出流
  1. Constructor构造方法

    BufferedOutputStream(OutputStream out);
    	这里需要一个字节输出流作为方法的参数
  2. Method成员方法

    void write(int b);
    void write(byte[] buf);
    void write(byte[] buf, int off, int len);
    
    以上方法都是OutputStream提供的方法
  3. 操作流程

    所有的数据都是首先通过写入保存到BufferedOutStream底层操作的数组中,当数组填满以后,或者执行指定的方法,才会将数据直接写入到内存中

  4. 代码演示

    package com.qfedu.a_buffer;
    
    import java.io.BufferedOutputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.util.Scanner;
    
    /*
     * 字节缓冲输出流操作
     */
    public class Demo2 {
    	public static void main(String[] args) throws IOException {
    		// 1. 直接创建对应的缓冲输出流对象
    		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:/aaa/2.txt"));
    		
    		for (int i = 0; i < 10000; i++) {
    			bos.write("1234567890".getBytes());
    		}
    		
    		new Scanner(System.in).next();
    		
    		for (int i = 0; i < 10000; i++) {
    			bos.write("1234567890".getBytes());
    		}
    		
    		bos.close();
    	}
    }
1.4 使用缓冲和不使用缓冲的时间效率问题
package com.qfedu.a_buffer;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/*
 * 使用缓冲和非缓冲情况下操作对比!!!
 */
public class Demo3 {
	public static void main(String[] args) throws IOException {
		// 空间换时间!!!
		// 210 8KB
		//useBuffer();
		
		// 50373 4byte
		noBuffer();
	}

	public static void noBuffer() throws IOException {
		long start = System.currentTimeMillis();

		// 使用基本IO流
		FileInputStream fis = new FileInputStream("D:/aaa/2.txt");
		FileOutputStream fos = new FileOutputStream("D:/aaa/noBuffer.txt");

		int content = -1;

		while ((content = fis.read()) != -1) {
			fos.write(content);
		}

		fos.close();
		fis.close();

		long end = System.currentTimeMillis();

		System.out.println("Time:" + (end - start));
	}

	private static void useBuffer() throws IOException {
		long start = System.currentTimeMillis();

		// 使用缓冲流
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:/aaa/2.txt"));
		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:/aaa/useBuffer.txt"));
		
		int content = -1;
		
		while ((content = bis.read()) != -1) {
			bos.write(content);
		}
		
		bos.close();
		bis.close();

		long end = System.currentTimeMillis();

		System.out.println("Time:" + (end - start));
	}
}
1.5 关于字节缓冲流使用总结
  1. 使用缓冲时间效率是远远高于未使用缓冲情况,这里是一个非常经典的空间换时间概念
  2. 利用代码可以发现,非缓冲IO操作使用数组作为缓冲区和使用缓冲流操作,时间效率相似。这里还是推荐使用系统提供的缓冲流,更加安全,并且提供了一些其他方法,可以作为一定参考使用。
1.6 BufferedReader字符输入缓冲流
  1. 构造方法

    BufferedReader(Reader in);
  2. Method成员方法

    int read();
    int read(byte[] buf);
    String readLine();【新方法】
        从文件中读取一行数据,返回值类型是字符串,如果读取到文件末尾,返回null。
        一行数据??? 结尾标记  \r\n
  3. 代码演示

    package com.qfedu.a_buffer;
    
    import java.io.BufferedReader;
    import java.io.FileReader;
    import java.io.IOException;
    
    public class Demo4 {
    	public static void main(String[] args) throws IOException {
    		BufferedReader br = new BufferedReader(new FileReader("D:/aaa/3.txt"));
    		
    		System.out.println(br.read());
    		String str = null;
    		while ((str = br.readLine()) != null) {
    			System.out.println(str);
    		}
    		
    		br.close();
    	}
    }
1.7 BufferedWriter字符输出缓冲流
  1. 构造方法

    BufferedWriter(Writer in);
  2. Method成员方法

    void write(int ch);
    void write(char[] buf);
    void write(char[] buf, int off, int len);
    void write(String str);
    void write(String str, int off, int len);
    void newLine();// 换行操作
  3. 代码演示

    package com.qfedu.a_buffer;
    
    import java.io.BufferedWriter;
    import java.io.FileWriter;
    import java.io.IOException;
    
    public class Demo5 {
    	public static void main(String[] args) throws IOException {
    		BufferedWriter bw = new BufferedWriter(new FileWriter("D:/aaa/4.txt"));
    		
    		bw.write("没有什么知识点是20遍抄写解决不了的");
    		bw.newLine();
    		
    		bw.write("如果有???!!!");
    		bw.newLine();
    		
    		bw.write("那就再来20遍!!!\r\n");
    		
    		bw.close();
    	}
    }

2.Java中常用API

2.1 关于String字符串的冗余问题
String str = "烤羊排";
str += "烤羊肉串";
str += "烤韭菜";
str += "烤鸡翅";
str += "烤鸡心";
str += "烤羊腿";
str += "烤蘑菇";
str += "烤鸡腿";

System.out.println("请问这里有几个字符串" );

正确答案:16

String字符串是一个常量

常量可以修改吗?不可以!

String str = “烤羊排”;
str += “烤羊肉串”;

“烤羊排”、“烤羊肉串”、“烤羊排烤羊肉串”

三个字符串

String字符常量操作会导致大量的字符串冗余问题,浪费内存。

为了解决这个冗余问题,Java中提供了两个可变长字符串

StringBuffer和StringBuilder 底层保存字符串数据的都是字符串数组形式,并且该数组的初始化容量为16个char类型

2.2 StringBuffer方法
2.2.1 StringBuffer概述

StringBuffer是一个线程安全的可变长字符串对象

涉及的方法:增删改查

2.2.2 StringBuffer构造放法
StringBuffer();
	创建一个StringBuffer类对象,在底层char类型数组中,初始化容量为16,并且未存储任何的数据
StringBuffer(String str);【最常见】
	根据用户传入参数String类型字符串,创建对应的StroingBuffer对象,底层char类型数组保存对应的字符串信息
StringBuffer(int capacity);
	根据用户传入初始化底层char类型数组容量确定StringBuffer对象
2.2.3 成员方法
  1. 添加方法

    append(EveryThing);
    	在StringBuffer末尾追加内容,可以是任意数据类型
    insert(int index, EveryThing);
    	在StringBuffer指定下标位置添加内容,可以是任意数据类型
    package com.qfedu.b_stringbuffer;
    
    import java.util.ArrayList;
    
    public class Demo3 {
    	public static void main(String[] args) {
    		StringBuffer stb = new StringBuffer("加多宝凉茶");
    		
    		Demo1 str = null;
    		stb.append(1);
    		stb.append(true);
    		stb.append('z');
    		stb.append(3.14F);
    		stb.append(5.5);
    		stb.append(new Demo3());
    		
    		stb.append(str);
    		
    		System.out.println(stb);
    		
    		StringBuffer stb2 = new StringBuffer("骚磊伦布");
    		
    		ArrayList<String> list = new ArrayList<String>();
    		list.add("123");
    		list.add("ABC");
    		list.add("BBC");
    		stb2.insert(0, list);
    		System.out.println(stb2);
    //		
    //		boolean flag = true;
    //		while (flag) {
    //			
    //		}
    //		
    //		System.out.println(1111);
    	}
    }
  2. 查看方法

    String toString();
    	将StringBuffer底层保存数据的char类型字符数组内容,转换为String类型返回
    String indexOf(String str);
    	指定字符串在StringBuffer出现的第一次下标位置
    String lastIndexOf(String str);
    	指定字符串在StringBuffer出现的最后一次下标位置
            
    String substring(int begin);
    	从指定位置开始,到字符串末尾截取获得对应的字符串
    String substring(int begin, int end);
    	从指定位置begin开始,到end结束,获取对应的字符串,要头不要尾
    package com.qfedu.b_stringbuffer;
    
    public class Demo4 {
    	public static void main(String[] args) {
    		StringBuffer stb = new StringBuffer("12345678901234567890");
    		
    		int index = stb.indexOf("78");	
    		System.out.println(index);
    		
    		int lastIndexOf = stb.lastIndexOf("78");
    		System.out.println(lastIndexOf);
    		
    		String substring = stb.substring(5);
    		System.out.println(substring);
    		
    		String substring2 = stb.substring(5, 9);
    		System.out.println(substring2);
    	}
    }
  3. 修改方法

    replace(int start, int end, String str);
    	使用给定String中的字符替换此序列的子字符串中的字符。该子字符串从指定的start出开始,一直索引到 end-1 出的字符
            
    setCharAt(int index, char ch);
    	指定索引位置日换一个字符
    package com.qfedu.b_stringbuffer;
    
    public class Demo5 {
    	public static void main(String[] args) {
    		StringBuffer stb = new StringBuffer("0123456789");
    		
    		StringBuffer replace = stb.replace(3, 9, "深圳是个好地方!!!");
    		
    		System.out.println("replace: " + replace);
    		System.out.println("stb: " + stb);
    		
    		stb.setCharAt(1, '你');
    		System.out.println(stb);
    	}
    }
  4. 删除方法

    delete(int start, int end);
    	删除从start开始,到end结束区间的所有内容,要头不要尾
    deleteCharAt(int index);
    	删除指定下标的字符
  5. 反序

    reverse();
    StringBuffer内容反序
2.2.4 StringBuilder和StringBuffer的关系

类比:ArrayList 线程不安全,效率高 与 Vector 线程安全,效率低,

StringBuffer 线程安全,效率低 StringBuilder 线程安全,效率低

StringBuffer和StringBuilder操作使用的方法是一致的,只不过StringBuffer的方法带有的大量的同步问题,效率比较低。

2.3 System类

System是系统类

static Properties getProperties();【重点】
	获取系统属性
static long currentTimeMillis();
	获取当前时间的毫秒数
static void exit();
	JVM退出程序,0表示正常退出

Properties类是一个重点:属性类,里面保存的数据都是键值对形式。

package com.qfedu.c_system;

import java.util.Properties;

public class Demo1 {
	public static void main(String[] args) {
		Properties properties = System.getProperties();
		
		properties.list(System.out);
		System.out.println();
	
		String property = properties.getProperty("os.name");
		System.out.println(property);
		
		System.out.println(System.currentTimeMillis());
		
		System.exit(0);
	}
}

3.反射

3.1 Java文件和.class字节码文件的关系
  1. Java文件(.java)就是写的代码,包含了所有的内容,而且现在貌似我们所有的代码都是一个class类 or interface接口 ==> 单独一个 .java 文件

  2. .class 字节码文件是二进制文件,是根据.java文件,通过Java编译器(javac)编译的得到,并且.class字节码文件可以让JVM执行。

  3. 复习:

    Demo1.java

    javac Demo1.java ==> 编译代码 得到Demo1.class

    java Demo1 ==> 执行代码,运行结果

    编译之后的java代码生成对应的.class字节码文件,通过反编译,可以看到整个.class文件中的内容都是对应java文件的。反编译命令如下:

    javap -c -l -private XXX.class

3.2 JVM运行Java程序加载的内容是.class文件
  1. 在static学习的过程中,对于类加载过程有一定的认知,类加载机制。

  2. .class文件是在代码运行之前需要加载到内存中,才可以支持整个程序的运行,.class文件在内存的代码区

  3. 在内存代码区,存在一个.class文件占用的内存空间,而该内存空间包含了对应Java文件的所有内容。Java文件的内容包基本上包含有:

    构造方法 Constructor

    成员方法 Method

    成员变量 Field

    注解 Annotation @Override @Test

你可能感兴趣的:(java)