Java基础19 IO基础

为热爱编程的你点赞!
学习SpringBoot实战课程 https://edu.csdn.net/course/detail/31433
学习SpringCloud入门课程 https://edu.csdn.net/course/detail/31451


前言

在Java知识体系中IO是重要一环,因为我们需要从磁盘或网络中读取获得数据,这样我们才能完成数据的持久化和网络通信,本文带大家了解IO流。

IO流分类

在这里插入图片描述

按操作数据的类型分类:

  • 字节流
    • 一般用于操作二进制数据,数据的单位是byte(视频、音频、图片、exe、dll等文件)
    • 以InputStream或OutputStream结尾
  • 字符流
    • 一般用于操作文本数据,数据的单位是char(txt、xml、html等文件)
    • 以Reader或Writer结尾

按数据的流向分类:

  • 输入流
    • 从磁盘文件或网络流到Java程序中,用于读取数据
    • 所有字节输入流的父类是InputStream
    • 所有字符输入流的父类是Reader
  • 输出流
    • 从Java程序流向磁盘文件或网络,用于写入数据
    • 所有字节输出流的父类是OutputStream
    • 所有字符输出流的父类是Writer

文件读写

文件读取

文件输入流 FileInputStream
作用是:读取磁盘文件或网络的数据
构造方法:

FileInputStream(File file)
FileInputStream(String filepath)

主要方法:

  • int read(byte[] buffer) 读取文件数据,保存到字节数组中,返回值是读取长度-1代表读取完毕。
  • void close() 关闭文件流

try-with-resource
IO流使用完后必须关闭,否则文件流无法得到释放,close方法调用要写在finally中。
为简化关闭流的代码,Java1.7引入了try-with-resource语法,让资源在try-catch完毕后自动关闭。
语法:

try(类 对象 = new 类()){
	可能出现异常的代码
}catch(异常类型 对象){
	处理异常的代码
}

注意:关闭的对象必须实现Closable接口,IO流都实现了该接口。

文件读取的过程

  1. 创建文件输入流
  2. 创建byte数组
  3. 循环调用read方法读取数据,存入byte数组
  4. 操作byte数组
  5. 读取完毕关闭文件流
    在这里插入图片描述
/**
	 * 读取文件内容
	 * @param filepath
	 */
	public void read(String filepath){
		//1、创建文件输入流
		try(FileInputStream fis = new FileInputStream(filepath)) {
			//2、创建byte数组
			byte[] buffer = new byte[1024];
			//3、循环调用read方法读取数据,存入byte数组
			int len = 0;
			while((len = fis.read(buffer)) != -1){				
				//4、操作byte数组,如果是文字将byte[]转换为String
				String str = new String(buffer,0,len,"UTF-8");
				System.out.println(str);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}
	
	@Test
	public void testRead(){
		read("C:/xpp/Test6.java");
	}

文件写入

文件输出流 FileOutputStream
作用是:将数据写入磁盘文件或网络
构造方法:

FileOutputStream(File file)
FileOutputStream(String filepath)

主要方法:

  • write(byte[] buffer,int offset,int length) 写入文件,offset开始位置,length写入长度
  • write(byte[] buffer)
  • close() 关闭流

文件写入步骤:

  1. 创建文件输出流
  2. 将字符串转换为byte数组
  3. 调用write写入文件
  4. 关闭文件流
/**
	 * 写入磁盘文件
	 * @param filepath
	 * @param content
	 */
	public void write(String filepath,String content){
		//1、创建文件输出流
		try (FileOutputStream fos = new FileOutputStream(filepath)){
			//2、将字符串转换为byte数组3、调用write写入文件
			fos.write(content.getBytes());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	@Test
	public void testWrite(){
		write("C:/xpp/xxxx.txt","这是我要写入的内容:Hello JavaEE!");
	}

文件的复制

文件的复制是在读取文件的同时,将数据写入到另一个文件中
思路:
1、创建输入流和输出流
2、通过输入流读取数据到byte数组中
3、同时将byte数组中的数据写入输出流
4、循环1、2、3
在这里插入图片描述

/**
	 * 复制文件
	 * @param source 原始文件路径
	 * @param target 目标文件路径
	 */
	public void copy(String source,String target){
		//创建文件输入流、文件输出流
		try(FileInputStream fis = new FileInputStream(source);
				FileOutputStream fos = new FileOutputStream(target)){
			//创建byte数组
			byte[] buffer = new byte[1024];
			int len = 0;
			//循环从输入流读取数据
			while((len = fis.read(buffer)) != -1){
				//写入到输出流中
				fos.write(buffer, 0, len);
			}
		}catch(Exception ex){
			ex.printStackTrace();
		}
		System.out.println("复制完毕");
	}
	
	@Test
	public void testCopy(){
		copy("C:\\xpp\\InletexEMCFree.exe","C:\\xpp\\InletexEMCFree2.exe");
	}

缓冲

什么是缓冲

前提是内存的读写速度要远高于磁盘的读写速度,缓冲就是内存中的一块空间,通过缓冲可以提高数据的读写速度。

为什么需要缓冲

如果没有缓冲,文件读写是直接从磁盘上进行的,速度比较慢;缓冲就是在内存建立一个空间,读写之前将一部分磁盘上的数据导入到缓冲内存中,后面读写就直接从缓冲中进行,减少了直接从磁盘读写的次数,从而提高读写效率。
缓冲流:在普通的IO流基础上,加入内存缓冲区,提高IO效率。

字节缓冲流

BufferedInputStream 缓冲输入流

创建方法:
new BufferedInputStream(InputStream in)
new BufferedInputStream(InputStream in,int bufferSize) 

说明:

  • 参数InputStream是一个字节输入流,传入缓冲输入流中后,就添加了缓冲区。
  • 参数bufferSize可以设置缓冲区大小

BufferedOutputStream 缓冲输出流

创建方法:
new BufferedOutputStream(OutputStream out)
new BufferedOutputStream(OutputStream out,int bufferSize)

下面案例用JUnit测试使用非缓冲流和缓冲流进行文件复制的效率对比:

public class TestIO {

    /**
     * 不使用缓冲复制文件
     * @param source
     * @param target
     */
    public void copyWithoutBuffer(String source,String target){
        System.out.println("不使用缓冲复制文件");
        //创建文件输入流和输出流
        try(FileInputStream in = new FileInputStream(source);
            FileOutputStream out = new FileOutputStream(target)){
            //定义字节数组
            byte[] buffer = new byte[100];
            int len = 0;
            //读取数据
            while((len = in.read(buffer)) != -1){
                //写入数据
                out.write(buffer,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 使用缓冲复制文件
     * @param source
     * @param target
     */
    public void copyWithBuffer(String source,String target){
        System.out.println("使用缓冲复制文件");
        //创建缓冲输入流和输出流
        try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(source));
            BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(target))) {
            //定义字节数组
            byte[] buffer = new byte[100];
            int len = 0;
            //读取数据
            while ((len = in.read(buffer)) != -1) {
                //写入数据
                out.write(buffer, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testCopyWithoutBuffer(){
        copyWithoutBuffer("D:/install/jdk-8u171-windows-x64.exe","D:/jdk1.exe");
    }

    @Test
    public void testCopyWithBuffer(){
        copyWithBuffer("D:/install/jdk-8u171-windows-x64.exe","D:/jdk2.exe");
    }
}

在这里插入图片描述
在这里插入图片描述
不用缓存复制文件消耗了10s多,使用缓存消耗了0.59s,速度提高接近20倍。

字符流

以字符char为单位进行的流,适合操作文本数据。

  • Reader 字符输入流的父类
  • Writer 字符输出流的父类

FileReader 文件读取器

创建方法:

new FileReader(String path) path是文件路径

主要方法:

  • int read(char[] buffer) 读取数据到字符数组中
  • close()

FileWriter 文件写入器

创建方法:

new FileWriter(String path) path是文件路径

主要方法:

  • write(char[] buffer) 写入字符数组
  • write(char[] buffer,int offset,int length)
  • write(String str) 写入字符串

字符缓冲流

BufferedReader

带缓冲的读取器
创建方法:

new BufferedReader(Reader reader)

特有方法:

  • readLine() 读取一行文字

BufferedWriter

带缓冲的写入器
创建方法:

new BufferWriter(Writer writer)

特有方法:

  • write(String str) 写入字符串
  • newLine() 插入换行

打印流

在输出时能控制打印格式
打印流分为:

  • PrintStream 字节打印流,System.out就是PrintStream
  • PrintWriter 字符打印流

常用方法:

  • print 输出
  • println 输出带换行
  • printf(“格式字符串”,可变参数) 带格式输出
    %s 输出字符串
    %d 输出整数
    %f 输出小数
    %n 输出换行

数据流

一种高层的字节流,能够以各种数据类型(byte\short\int\long\char\boolean\String…)读写流中的数据。

DataInputStream

构造方法:

DataInputStream(InputStream is)

常用方法:

  • readByte() 读取byte数据
  • readShort()
  • readInt()
  • readLong()
  • readChar()
  • readBoolean()
  • readFloat()
  • readDouble()
  • readUTF() 读取字符串
    注意:读取各种数据类型的方法的调用顺序,必须和写入顺序一致。

DataOutputStream

构造方法:

DataOutputStream(OutputStream os)

常用方法:

  • writeByte() 写入byte数据
  • writeShort()
  • writeInt()
  • writeLong()
  • writeChar()
  • writeBoolean()
  • writeFloat()
  • writeDouble()
  • writeUTF() 写入字符串

结束

作业:
假设文件中有多个单词,每一个单词单独一行
如:
Hello
World
Hello
JavaEE

将文件中的单词读取出来,去掉重复的单词,排序后写入新的文件


大家如果需要学习其他Java知识点,戳这里 超详细的Java知识点汇总

猜你喜欢

转载自blog.csdn.net/u013343114/article/details/112779774