Java编程基础之IO流

Posted Ocean:)

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java编程基础之IO流相关的知识,希望对你有一定的参考价值。

IO流

IO流基类

  • InputStream

    输入流基类

    read

  • OutputStream

    输出流基类

    write

IO流分类

  • 流向分类

    输入输出

  • 文件操作处理单元分类

    字节流和字符流

  • FileInputStream

    文件操作输入字节流

  • FileOutputStream

    文件操作输出字节流

  • FileReader

    文件操作输入字符流

  • FileWriter

    文件操作输出字符流

文件操作字节流

文件操作输入字节流

FileInputStream

Constructor构造方法

  • FileInputStream(File file);

    这里是根据提供的File类对象创建对应的文件操作输入字节流

  • FileInputStream(String pathName);

    这里是根据提供的String类型文件路径,创建对应的文件操作输入字节流

两个方法都会抛出FileNotFoundException文件未找到异常

Method成员方法

  • int read();

    从文件中读取一个字节数据返回到方法外

    虽然返回值是一个int类型,但是整个int类型当中存储的数据是一个byte类型,有且只有低8位数据有效

  • int read(byte[] buf);

    读取文件的内容是存储在byte类型数组中,返回值是读取到的字节个数

  • int read(byte[] buf, int offset, int count);

    读取文件的内容是存储在byte类型数组中,要求byte数组offset位置开始,到count长度结束,返回值是读取到的字节个数

这三个方法,如果读取到文件末尾,返回值都是-1 EOF (End Of File),并且都要抛出IOException异常

FileInputStream实例:

package obj_file;

import java.io.File;
import java.io.FileInputStream;

public class Demo6 {
	public static void main(String[] args) {
		// 打开文件创建句柄
		File file = new File("D:\\\\JavaCode\\\\test\\\\1.txt");
		
		// 2.字节输入流读取文件对象
		FileInputStream fileInputStream = null;
		
		try {
			// 3.根据File类对象创建对应的字节输入流
			fileInputStream = new FileInputStream(file);
			
			// 4.准备一个8KB字节缓冲数组
			byte[] buf = new byte[1024 * 8];
			int length = -1;
			
			// 5.读取数组
			while ((length = fileInputStream.read(buf)) != -1) {
				System.out.println(new String(buf));
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 在finally代码中关闭资源
			if (fileInputStream != null) {
				try {
					fileInputStream.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
}

使用缓冲区速度会提高很多

FileOutputStream

FileOutputStream 文件操作输出字节流

Constructor构造方法

  • FileOutputStream(File file);

    根据File类对象创建对应的文件的输出字节流对象

  • FileOutputStream(String pathName);

    根据String类型文件路径创建对应的文件输出字节流对象

两个构造方法都是删除写方式,删除原文件后创建新文件写入数据

  • FileOutputStream(File file, boolean append);

    根据File类对象创建对应的文件的输出字节流对象

  • FileOutputStream(String pathName, boolean append);

    根据String类型文件路径创建对应的文件输出字节流对象

append为true表示追加写

Method成员方法

  • void write(int b);

    写入一个字节数据到当前文件中,参数是int类型,但是有且指挥操作对应的第八位数据

  • void write(byte[] buf);

    写入字节数组中的内容到文件中

  • void write(byte[] buf, int offset, int length);

    写入字节数组中的内容到文件中,从指定的offset开始,到指定长度length

以上方法会抛出IOException异常

实例:

package obj_file;

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

public class Demo8 {
	public static void main(String[] args) {
		copyTest();
	}
	
	public static void copyTest() {
		FileInputStream fis = null;
		FileOutputStream fos = null;
		
		try {
			// 1.创建文件输入字节流
			fis = new FileInputStream("D:\\\\JavaCode\\\\test\\\\1.txt");
			// 2.创建文件输出字节流
			fos = new FileOutputStream("D:\\\\JavaCode\\\\test\\\\2.txt");
			
			// 3.准备一个缓冲数组8KB
			byte[] buf = new byte[1024 * 8];
			int length = -1;
			
			// 4.读取文件数据
			while ((length = fis.read(buf)) != -1) {
				fos.write(buf, 0, length);
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 先开的后关,先关的后开
			if(fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
			if(fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}

文件操作字符流

字符流特征

字符流 = 字节流 + 解码过程

字符组合过程 => 对应当前环境编码集的一个字符

如果字符找不到,该数据无效,需要被删除

如果是字符内容操作,效率较高,如果是非字符操作效率较低

文件操作字符输入流

Constructor构造方法

  • FileInputStream(File file);

    这是根据提供的File类对象创建对应的文件操作输入字节流

  • FileInputStream(String pathName);

    这里是根据提供的String类型文件路径,创建对应的文件操作输入字节流

两个构造方法都会抛出异常,FileNotFoundException文件未找到异常

Method成员方法

  • int read();

    从文件中读取一个字节数据返回到方法外

    虽然返回值是一个int类型,但是在整个int类型中存储的数据是一个byte类型,有且只有低8位数据有效

  • int read(byte[] buf);

    读取文件的内容是存储在byte类型数组中,返回值是读取到的字节个数

  • int read(byte[] buf, int offset, int count);

    读取文件的内容是存储在byte类型数组中,要求从byte数组offset位置开始,到count长度结束,返回值是读取到的字节个数

这三个方法如果读取到文件末尾,返回值都是-1 EOF End Of File,都要抛出异常IOException

实例

统计字符串内每个英文字母的个数

package obj_file;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;

public class Demo9 {
	public static void main(String[] args) throws IOException {
		FileReader fileReader = new FileReader(new File("D:\\\\JavaCode\\\\test\\\\1.txt"));
		
		int[] counts = new int[52];
		char[] buf = new char[1024];
		int length = -1;
		
		length = fileReader.read(buf);
		
		for (int i = 0; i < length; i++) {
			if (buf[i] >= 'A' && buf[i] <= 'Z') {
				counts[buf[i] - 65] += 1;
			} else if (buf[i] >= 'a' && buf[i] <= 'z') {
				// 71 = 97 -26
				counts[buf[i] - 71] += 1;
			}
		}
		
		System.out.println(Arrays.toString(counts));
		fileReader.close();
	}
}

输出结果

结果有些抽象,但是计算很快,从左到右分别表示大写字母A到Z的个数,小写字母a到z的个数

文件操作字符输出流

Constructor

写入过程中,发生问题会产生IOException

package obj_file;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class Demo10 {
	public static void main(String[] args) {
		FileWriter fileWriter = null;
		
		try {
			fileWriter = new FileWriter(new File("D:\\\\JavaCode\\\\test\\\\test.txt"));
			
			fileWriter.write("O");
			fileWriter.write("C");
			fileWriter.write("E");
			fileWriter.write("A");
			fileWriter.write("N");
			
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (fileWriter != null) {
				try {
					fileWriter.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

字符流文件拷贝

如果文件不是文本文件,拷贝可能因为编码方式不同,导致文件损坏

缓冲流

使用缓冲数组以后,整体的读取,写入效率提升很大

降低了CPU通过内存访问硬盘的次数

  • 字节输入缓冲

    BufferInputStream

  • 字节输出缓冲

    BufferInputStream

  • 字符输入缓冲

    BufferedReader

  • 字符输出缓冲

    BufferedWrite

注意:所有的缓冲流都没有任何的读取,写入文件能力,这里都需要对应的输入流和输出流来提供对应的能力

在创建缓冲流对象时,需要传入对应的输入流对象和输出流对象

底层就是提供了一个默认大小的缓冲数组,用于提高效率

字节缓冲流

  • 输入

    BufferedInputStream(InputStream in);

    这里需要的对象是一个字节输入流基类对象,同时也可以传入InputStream子类对象

  • 输出

    BuffedOutputStream(OutputStream out);

    这里需要的对象是一个字节输出流基类对象,同时也可以传入OutputStream子类对象

以上传入的InputStream和OutputStream都是用于提供对应文件的读写能力

实例:

package obj_file;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class Demo11 {
	public static void main(String[] args) throws IOException {
		// 1.找到对应文件
		File file = new File("D:\\\\JavaCode\\\\test\\\\1.txt");
		
		// 2.创建对应的FileInputStream输入流
		FileInputStream fileInputStream = new FileInputStream(file);
		
		// 3.根据文件操作字节输入流对象,创建对应的缓冲流对象
		BufferedInputStream bis = new BufferedInputStream(fileInputStream);
		
		// 4.读取数据过程,读取过程中使用的方法是FileInputStream提供的方法
		int content = -1;
		while ((content = bis.read()) != -1) {
			
		}
		
		bis.close();
	}
}

运行速度大大提升

字节输入流缓冲效率问题

  1. 在BufferedInputStream底层中有一个默认容量为8KB的byte类型缓冲数组
  2. fill方法是一个操作核心
    • 从硬盘中读取数据,读取的数据容量和缓冲数组容量一致
    • 所有read方法,都是从缓冲数组中读取数据
    • 每一次读取数据之前,都会检查缓冲区内是否有数据,如果没有,fill方法执行,填充数据
  3. 利用缓冲,fill方法,可以极大的降低cpu通过内存访问硬盘的次数,同时程序操作的数据是在内存中进行交互的

字节输出缓冲效率问题

  1. BufferedOutputStream类对象,默认有一个8KB的byte类型缓冲数组
  2. 数据写入文件时并不是直接保存到文件中,而是保存在内容8KB字节缓冲数组中
  3. 如果8KB空间填满,会直接flush缓冲区,数据保存到硬盘中,同时清空整个缓冲区
  4. 在BufferedOutputStream关闭时,首先会调用flush方法,保存数据到文件,清空缓冲区,并且规划缓冲区占用内存,同时关闭缓冲流使用的字节输出流

字符缓冲流

  • BufferedReader

    字符缓冲输入流

    BufferedReader(Reader reader);

  • BufferedWriter

    字符缓冲输出流

    BufferedWriter(Writer writer)

实例:

package obj_file;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;import javax.lang.model.type.NullType;

public class Demo12 {
	public static void main(String[] args) {
		bufferedReader();
		bufferedWriter();
	}
	
	private static void bufferedWriter() {
		BufferedWriter bw = null;
		
		try {
			bw = new BufferedWriter(new FileWriter(new File("D:\\\\JavaCode\\\\test\\\\1-1.txt")));
			bw.write("ocean");
			bw.newLine();
			bw.write("ocean");
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				bw.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}
	
	private static void bufferedReader() {
		BufferedReader br = null;
		
		try {
			br = new BufferedReader(new FileReader(new File("D:\\\\JavaCode\\\\test\\\\1.txt")));
			
			System.out.println(br.readLine());
			System.out.println(br.readLine());
			System.out.println(br.readLine());

		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (br != null) {
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

以上是关于Java编程基础之IO流的主要内容,如果未能解决你的问题,请参考以下文章

java内存流:java.io.ByteArrayInputStreamjava.io.ByteArrayOutputStreamjava.io.CharArrayReaderjava.io(代码片段

JAVA之IO流

java基础之 IO 流(RandomAccessFile类)

java缓冲字符字节输入输出流:java.io.BufferedReaderjava.io.BufferedWriterjava.io.BufferedInputStreamjava.io.(代码片段

java网络编程系列之java.io专业术语

java基础之 IO 流(InputStream/OutputStream)