【JAVA】IO流

1 缓冲流

缓冲自带缓冲区、可以提高字节流、字符流读写数据的性能

字节缓冲流:

  • 字节缓冲输入流:BufferedInputStream
  • 字节缓冲输出流:BufferedOutputStream

字符缓冲流

  • 字符缓冲输入流:BufferedReader
  • 字符缓冲输出流:BufferedWriter

1.1 字节缓冲流

字节缓冲输入流

  • BufferedInputStream,提高字节输入流读取数据的性能,读写功能上并无变化。
  • 自带了8KB缓冲池,直接从缓冲池中读取数据,所以性能较好

字节缓冲输出流

  • BufferedOutputStream,提高字节输出流读取数据的性能,读写功能上并无变化
  • 自带了8KB缓冲池,数据直接写入到缓冲池中,写数据性能极高
构造器 说明
public BufferedInputStream(InputStream is) 可以把低级的字节输入流包装成一个高级的缓冲字节输入流管道,从而提高字节输入流读数据的性能
public BufferedOutputStream(OutputStream os) 可以把低级的字节输出流包装成一个高级的缓冲字节输出流,从而提写数据的性能
// 1 创建一个字节输入流管道与源文件接通
InputStream is = new FileInputStream("a.txt");
// 把字节输入流包装为缓冲字节输入流
InputStream bis = new BufferedInputStream(is)

// 2 创建一个字节输出流管道与目标文件接通
OutputStream os = new FileOutputStream("a1.txt");
// 把字节输出流包装成缓冲字节输出流
OutputStream bos = new BufferedOutputStream(os);
try(){
    // 3 定义一个字节数组转移数据
    byte[] buffer = new byte[1024]
    int len;
    while ((len = bis.read(buffer)) != -1){
        bos.write(buffer, 0, len);
    }
}catch(Exception e){
    e.printStackTrace();
}

/**
    目标:利用字节流的复制统计各种写法形式下缓冲流的性能执行情况。

    复制流:
        (1)使用低级的字节流按照一个一个字节的形式复制文件。
        (2)使用低级的字节流按照一个一个字节数组的形式复制文件。
        (3)使用高级的缓冲字节流按照一个一个字节的形式复制文件。
        (4)使用高级的缓冲字节流按照一个一个字节数组的形式复制文件。

    源文件:D:\原视频.avi
    目标文件:D:\

 */
public class ByteBufferTimeDemo {
    private static final String SRC_FILE = "D:\\原视频.avi";
    private static final String DEST_FILE = "D:\\";

    public static void main(String[] args) {
        // copy01();   // 1、低级字节流一个一个字节的复制 (慢的让人无法忍受,直接淘汰)
        copy02();   // 2、低级字节流一个一个字节数组复制 (较慢,不推荐使用)
        // copy03();   // 3、高级流一个一个字节的复制(很慢,直接淘汰)
        copy04();   // 4、高级流一个一个字节数组的复制(飞快,推荐使用)
    }

    private static void copy04() {
        long start = System.currentTimeMillis();
        try (
                // 1、创建一个字节输入流管道与原视频接通
                InputStream is = new FileInputStream(SRC_FILE);
                // 2、创建一个字节输出流管道与目标文件接通
                OutputStream os = new FileOutputStream(DEST_FILE + "4.avi");

                // a、把低级的字节输入流包装成高级的缓冲字节输入流:自带8KB的缓冲池
                InputStream bis = new BufferedInputStream(is);
                // b、把低级的字节输出流包装成高级的缓冲字节输出流
                OutputStream bos = new BufferedOutputStream(os);
        ){
            // 3、使用数组拷贝
            int len;
            byte[] buffer = new byte[1024];
            while ((len = bis.read(buffer)) != -1) {
                bos.write(buffer,0 , len);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("缓冲流一个一个字节数组复制耗时:" + (end - start) / 1000.0 + "s");
    }

    private static void copy03() {
        long start = System.currentTimeMillis();
        try (
                // 1、创建一个字节输入流管道与原视频接通
                InputStream is = new FileInputStream(SRC_FILE);
                // 2、创建一个字节输出流管道与目标文件接通
                OutputStream os = new FileOutputStream(DEST_FILE + "3.avi");

                // a、把低级的字节输入流包装成高级的缓冲字节输入流:自带8KB的缓冲池
                InputStream bis = new BufferedInputStream(is);
                // b、把低级的字节输出流包装成高级的缓冲字节输出流
                OutputStream bos = new BufferedOutputStream(os);
        ){
            // 3、定义一个变量记录每次读取的一个字节
            int ch;
            while ((ch = bis.read()) != -1) {
                bos.write(ch);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("缓冲流一个一个字节复制耗时:" + (end - start) / 1000.0 + "s");
    }

    private static void copy02() {
        long start = System.currentTimeMillis();
        try (
                // 1、创建一个字节输入流管道与原视频接通
                InputStream is = new FileInputStream(SRC_FILE);
                // 2、创建一个字节输出流管道与目标文件接通
                OutputStream os = new FileOutputStream(DEST_FILE + "2.avi");
        ){
            // 3、使用数组拷贝
            int len;
            byte[] buffer = new byte[1024];
            while ((len = is.read(buffer)) != -1) {
                os.write(buffer,0 , len);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("低级流一个一个字节数组复制耗时:" + (end - start) / 1000.0 + "s");
    }

    private static void copy01() {
        long start = System.currentTimeMillis();
        try (
                // 1、创建一个字节输入流管道与原视频接通
                InputStream is = new FileInputStream(SRC_FILE);
                // 2、创建一个字节输出流管道与目标文件接通
                OutputStream os = new FileOutputStream(DEST_FILE + "1.avi");
                ){
            // 3、定义一个变量记录每次读取的一个字节
            int ch;
            while ((ch = is.read()) != -1) {
                os.write(ch);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("低级流一个一个字节复制耗时:" + (end - start) / 1000.0 + "s");
    }
}

1.2 字符缓冲流

字符缓冲输入流

  • BufferedReader,提高字符输入流读取数据的性能,除此之外多了按照行读取数据的功能
  • 字符缓冲流自带8K缓冲区,提高了原始字符流读数据的性能

字符缓冲输出流

  • BufferedWriter提高字符输出流写数据的性能,多了换行功能
  • 字符缓冲流自带8K缓冲区
构造器 说明
public BufferedReader(Reader r) 可以把低级的字符输入流包装成一个高级的缓冲字符的输入流管道,从而提高字符输入流读数据的性能
public BufferedWriter(Writer w) 可以把低级的字符输出流包装成一个高级的缓冲字符输出流管道,从而提高字符输出流写数据的性能

新增功能

方法 说明
public String readLine() 读取一行数据返回,如果读取没有完毕,但是并没有行可读返回null
public void newLine() 字符输出流,换行操作

2 转换流

2.1 字符输入转换流

InputStreamReader,可以把原始的字节流按照指定编码转换成字符输入流

构造器 说明
public InputStreamReader(InputStream is) 可以把原始的字节流按照代码默认编码转换成字符输入流,几乎不用,与默认得FileReader一样
public InputStreamReader(InputStream is, String charset) 可以把原始得字节流按照指定编码转换成字符输入流,这样字符流中得字符就不乱码了
// 提交文件的原始字节流(GBK)
InputStream is = new FileInputStream("a.txt");
// 把字节输入流转换成字符输入流
Reader isr = new InputStreamReader(is, "GBK");
// 把字符输入流包装成缓冲字符输入流
BufferReader br = new BufferReader(isr);
// 编码一致情况
Reader fr = new FileReader("a.txt");
BufferedReader br = new BufferedReader(fr);

2.2 字符输出转换流

把字节输出流按照指定编码转换成字符输出流

构造器 说明
public OutputStreamWriter(OutputStream os) 可以把原始的字节输出流按照代码默认编码转换成字符输出流UTF-8
public OutputStreamWriter(OutputStream os, String charset) 把原始字节输出流按照指定编码转换成字符输出流
// 1、指定写出去的字符是:GBK。
OutputStream os = new FileOutputStream("a.txt");
// 2、自己指定字节写出去
//os.write("我爱你".getBytes("GBK"));
// os.close();

// 3、新方案:把字节输出流指定编码转换成字符输出转换流
Writer osw = new OutputStreamWriter(os, "GBK");
BufferedWriter bw = new BufferedWriter(osw);
bw.write("abc我爱你中国!");
bw.close();

3 对象序列化

把对象数据存入到文件中(对象必须实现序列化接口)

构造器 说明
public ObjectOutputStream(OutputStream out) 把低级字节输出流包装成高级的对象字节输出流
方法 说明
public final void writeObject(Object obj) 把对象写出去到对象序列流的文件中
public static void main(String[] args) throws Exception {
        // 1、创建一个对象
        Student s = new Student("赵四", 21);
        // 2、对象序列化:使用ObjectOutputStream
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.txt"));
        // 3、直接开始序列化
        oos.writeObject(s);
        // 4、资源释放
        oos.close();
        System.out.println("对象序列化完成~~");
}
public class Student implements Serializable{
...
}

 4 对象反序列化

以内存为基准,把存储到磁盘文件中去的对象数据恢复成内存中的对象

构造器 说明
public ObjectInputStream(InputStream out) 把低级字节输入流包装成高级的对象字节输入流
方法 说明
public Object readObject() 把存储到磁盘文件中的对象数据恢复成内存中的对象返回
 public static void main(String[] args) throws Exception {
        // 1、创建一个对象字节输入流管道与源文件接通
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("a.txt"));
        // 2、对象反序列化
        Student s = (Student) ois.readObject();
        System.out.println(s);
        ois.close();

补充

transient 修饰成员变量不参与序列化

 private transient String passWord;

5 打印流

打印流可以实现方便、高效的打印数据到文件中

PrintStream

构造器 说明

public PrintStream(OutputStream os)

打印流直接通向字节输出流管道

public PrintStream(File  f)

打印流直接通向文件对象

public PrintStream(String filepath)

打印流直接通向文件路径

方法 说明

public void print(Xxx xx)

打印任意类型的数据出去

PrintWriter

构造器 说明

public PrintWriter(OutputStream os)

打印流直接通向字节输出流管道

public PrintWriter (Writer w)

打印流直接通向字符输出流管道

public PrintWriter (File  f)

打印流直接通向文件对象

public PrintWriter (String filepath)

打印流直接通向文件路径

方法 说明

public void print(Xxx xx)

打印任意类型的数据出去

PrintStreamPrintWriter的区别

  • 打印数据功能上是一模一样的,都是使用方便,性能高效(核心优势)
  • PrintStream继承自字节输出流OutputStream,支持写字节数据的方法。
  • PrintWriter继承自字符输出流Writer,支持写字符数据出去。

输出语句重定向:打印流的一种应用,把输出语句的输入到文件中

PrintStream ps = new PrintStream("文件地址")
System.setOut(ps);

6 Properties

其实是一个Map集合,但是我们一般不会当集合使用,因为HashMap更好用。

作用:

  • Properties代表的是一个属性文件,可以把自己对象中的键值对信息存入到一个属性文件中去。
  • 属性文件:后缀是.properties结尾的文件,里面的内容都是 key=value,后续做系统配置信息的。
构造器 说明

void load​(InputStream inStream)

从输入字节流读取属性列表(键和元素对)

void load​(Reader reader)

从输入字符流读取属性列表(键和元素对)

void store​(OutputStream out, String comments)

将此属性列表(键和元素对)写入此 Properties表中,以适合于使用 load(InputStream)方法的格式写入输出字节流

void store​(Writer writer, String comments)

将此属性列表(键和元素对)写入此 Properties表中,以适合使用 load(Reader)方法的格式写入输出字符流

public Object setProperty(String key, String value)

保存键值对(put

public String getProperty(String key)

使用此属性列表中指定的键搜索属性值 (get)

public Set stringPropertyNames()

所有键的名称的集合  (keySet())

// 需求:使用Properties把键值对信息存入到属性文件中去。
Properties properties = new Properties();
properties.setProperty("admin", "123456");
// 存入到文件中去
/**
参数一:保存的管道
参数二:保存信息的描述
**/
properties.store(new FileWriter("a.properties"), "lucky");
// 需求:从属性文件中读取键值对信息
Properties properties = new Properties();
// 加载属性文件中的键值对信息到properties中去
properties.load(new FileReader("a.properties"));

Set keys = properties.stringPropertyNames();
// 1、读取属性文件的信息到Properties集合中去
Properties properties = new Properties();
properties.load(new FileReader("io-app2/src/people.txt"));

// 2、将admin密码改为123
if(properties.containsKey("admin")) {
properties.setProperty("admin", "123");
}

// 3、存储到文件中
properties.store(new FileWriter("a.txt"), "hhhhh!");

7 IO框架

commons-io是apache开源基金组织提供的一组有关IO操作的类库,可以提高IO功能开发的效率。commons-io工具包提供了很多有关io操作的类。有两个主要的类FileUtils, IOUtils

String readFileToString(File file, String encoding)

读取文件中的数据, 返回字符串

void copyFile(File srcFile, File destFile)

复制文件。

void copyDirectoryToDirectory(File srcDir, File destDir)

复制文件夹。

// 1.完成文件复制!
IOUtils.copy(new FileInputStream("a.jpeg"),new FileOutputStream("b.jpeg"));

// 2.完成文件复制到某个文件夹下!
FileUtils.copyFileToDirectory(new File("a.jpeg"), new File("D:/"));

// 3.完成文件夹复制到某个文件夹下!
FileUtils.copyDirectoryToDirectory(new File("D:\\a") , new File("D:\\b"));
// 删除文件夹
FileUtils.deleteDirectory(new File("D:\\b"));

// JDK1.7 自己也做了一些一行代码完成复制的操作:New IO的技术
Files.copy(Path.of("a.jpeg"), Path.of("b.jpeg"));

你可能感兴趣的:(java,开发语言)