【Java文件流】我尝试用一文把“字节流”说清楚

本文详细介绍初学者学习IO流的标准操作步骤,包括输入字节流如InputStream、FileInputStream、BufferedInputStream,以及输出字节流如OutputStream、FileOutputStream、BufferedOutputStream的使用方法。通过实例演示了如何进行文件的读写操作,以及在IO流中使用异常处理机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

初学者学习IO流的标准操作步骤:
第一,需要知道实现一个IO操作需要什么步骤,需要哪些API;
第二,不要去深究它的底层原理(我说的是新手);
第三,搞清楚各个流的类之间的继承、实现关系,另外就是它那迷一样的类名。

诞生背景:

  1. 计算机中都是二进制数据,一个字节是8个2进制位。字节可以表 示所有的数据,比如文本,音频,视频。图片,都是作为字节存在的。也就是说字节流处理的数据非常多。
  2. 在文本文件中存储的数据是以我们能读懂的方式表示的。而在二进制文件中存储的数据是用二进制形式表示的。我们是读不懂二进制文件的,因为二进制文件是为了让程序来读取而设计的。
  3. 例如,Java的源程序(.java源文件)存储在文本文件中,可以使用文本编辑器阅读,但是Java的类(字节码文件)存储在二进制文件中,可以被Java虚拟机阅读。二进制文件的优势在于它的处理效率比文本文件高。
  4. 总结:把人能看懂的文件内容转换为机器能看懂的文件内容。

输入字节流InputStream

功能: 从磁盘文件中读取,到内存。

输入字节流体系结构
在这里插入图片描述

  • java.lang.AutoCloseable:JDK1.7引入的自动关闭资源特性
  • java.lang.Closeable:使得可以关闭流
  • java.io.InputStream:字节输入流接口,定义了许多字节输入的操作
  • java.io.FileInputStream:文件字节流
  • java.io.BufferedInputStream:带缓冲的文件字节流

输入字节流(InputStream)核心方法:

  • public abstract int read() throws IOException
    • 读取一个字节,范围为0至255;
    • 返回读取的字节
    • 读到了末尾时为-1;
  • public int read(byte[] b) throws IOException
    • 读取字节数组容量个字节,暂存到字节数组;
    • 返回读取成功的字节数
    • 读到了末尾时为-1;
  • public int read(byte[] b, int off, int len) throws IOException
    • 从第off个字节处开始,读len个字节,暂存到字节数组
    • 返回读取成功的字节数
    • 读到了末尾时为-1;
  • public byte[] readAllBytes() 读取所有字节

特性:

  1. 一般来说,字节流不可以写中文,但是由于String类的有些方法中有一个可以按照平台解码的功能使得其具备写中文的能力;
  2. 包:java.io.*;
  3. 本质:读取文件中的数据是文件中的二进制,并不会将其转化为人看得懂的;
  4. 凡是缓冲流都不具备读写文件的能力,只不过是建立了一个缓冲区提高读写速度;

FileInputStream类

使用FileInputStream类的标准步骤:
Step1:找到目标文件,File类实现;
Step2:建立数据的输入通道,FileInputStream类实现;
Step3:读取内容,read() 方法;
Step4:关闭通道,close() 方法;

使用示例:

FileInputStream示例
import java.io.IOException;
import java.io.FileInputStream;
import java.io.File;

public class Main {
	public static void main(String[] args) throws IOException {
		readOneByte(); //读取一个字节
		readByteArray(); //读取一个字节数组
	}

	public static void readOneByte() throws IOException {
		String path = "C:\\users\\kyle\\desktop\\a.txt";
		File file = new File(path);
		FileInputStream fis = new FileInputStream(file);
		int len = 0; //接受read方法的返回值,读取成功的数目
		while((len = fis.read())!=-1) {
			System.out.print((char)len);
		}
		fis.close();
	}
	public static void readByteArray() throws IOException {
		String root = "C:\\users\\kyle\\desktop\\a.txt"; //原本桌面上没有NewDir文件夹
		File file = new File(root);
		FileInputStream fis = new FileInputStream(file);
		byte[] tmp = new byte[8];
		int len = 0; //保存读取成功的字节数
		while((len = fis.read(tmp))!= -1) {
			System.out.println("读取成功的字节数:"+len);
			System.out.println("读取到的内容是:"+new String(tmp,"UTF-8"));
		}
		fis.close();
	}
}

BufferInputSteam类

是FileInputSteam类的升级版,因为使用缓冲可提高读取效率;

标准操作流程:
Step1:找到目标文件;File实现;
Step2:建立通道;FileInputStream类实现;
Step3:把FileInputStream类对象传入BufferInputStream的构造方法中;
Step4:读取文件数据;
Step5:关闭;

原理图

缓冲区类的原理图

如何使用:

//BufferInputStream示例
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.BufferedInputStream;

public class Main {
	public static void main(String[] args) throws IOException {
		String path = "C:\\users\\kyle\\desktop\\a.txt";
		File file = new File(path);
		FileInputStream fis = new FileInputStream("C:\\users\\kyle\\desktop\\a.txt");
		BufferedInputStream bis = new BufferedInputStream(fis); //包装FileInputStream
		
		byte[] b = new byte[10];
		int len = 0;
		while((len = bis.read(b))!=-1) {
			System.out.println(new String(b,0,len)); //读取b数组中的数据,从0位置开始,读取len个
		}
		bis.close();
	}
}

输出字节流OutputStream

功能: 把内存中数据内容,写出到磁盘文件中。

输出字节流的体系结构
在这里插入图片描述

  • java.lang.AutoCloseable:JDK1.7引入的自动关闭资源特性
  • java.lang.Closeable:使得可以关闭流
  • java.io.Flushable:
  • java.io.OutputStream:字节输出流接口,定义了许多字节输出的操作
  • java.io.FileInputStream:文件字节流
  • java.io.BufferedInputStream:带缓冲的文件字节流

方法

  1. void close()关闭此输出流并释放与此流有关的所有系统资源
  2. void flush()刷新此输出流并强制写出所有缓冲的输出字节。
  3. void write(byte[] b):将 b.length 个字节从指定的 byte 数组写入此输出流。
  4. void write(byte[] b, int off, int len):将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
  5. abstract void write(int b):将指定的字节写入此输出流。

FileOutputStream类

核心构造方法:

  • FileOutputStream(File file);
  • FileOutputStream(String name);

标准操作流程
Step1:找到目标文件,File类实现;
Step2:建立数据输出通道,FileOutputStream类实现;
Step3:把数据写出,write() 方法;
Step4:关闭通道,close() 方法;

使用FileOutputStream 的时候:

  1. 如果目标文件不存在,那么会自动创建目标文件对象。

  2. 如果目标文件已经存在,那么会先清空目标文件中的数据,然后再写入数据。

  3. 如果目标文件已经存在,需要在原来数据基础上追加数据的时候应该使用new FileOutputStream(file,true)构造函数,第二参数为true。

  4. write方法写数据的时候,虽然接收的是一个int类型的数据,但是真正写出的只是一个字节的数据,只是把低八位的二进制数据写出,其他二十四位数据全部丢弃。如下例:

FileOutputStream对象.write(49);	写到文件中的数据,经过打开是“1”;
假如write(511); 00000000-000000000-00000001-11111111   511;
则只有低八位的数据才会被写到磁盘文件中;

使用示例:

//方法一:write(int b)方法,一次写入文件一个字节;
//方法二:write(byte[] b),就是使用缓冲,提高效率.

import java.io.IOException;
import java.io.File;
import java.io.FileOutputStream;

public class Main {
	public static void main(String[] args) throws IOException {
		//方法一:write(int b)方法,一次写入文件一个字节;
		writeOneByte();
		//方法二:write(byte[] b),就是使用缓冲,提高效率.
		writeByteArray();
	}
	
	public static void writeOneByte() throws IOException {
		File path = new File("C:\\users\\kyle\\desktop\\a.txt");
		FileOutputStream fos = new FileOutputStream(path);
		fos.write('j'); //报错语句:fos.write("j");
		fos.write('a');
		fos.write('v');
		fos.write('a');
		fos.close();
	}
	public static void writeByteArray() throws IOException {
		File path = new File("C:\\users\\kyle\\desktop\\a.txt");
		FileOutputStream fos = new FileOutputStream(path);
		String str = "java";
		byte[] byt = str.getBytes(); //把一个字符串转化为byte存入数组中
		fos.write(byt);
		fos.close();
	}
}

BufferOutputStream类

使用格式:

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.BufferedOutputStream;

public class Main {
	public static void main(String[] args) throws IOException {
		writerBuffer();
	}
	public static void writerBuffer() throws IOException {
		String path = "C:\\users\\kyle\\desktop\\a.txt";
		File file = new File(path);
		FileOutputStream fos = new FileOutputStream(file);
		BufferedOutputStream bos = new BufferedOutputStream(fos);
		bos.write("hello".getBytes());
		bos.close();
	}
}

在字节流中使用完善的异常机制

异常使用背景:
只在方法后抛出异常是很不合理的,因为异常并为得到处理,即异常发生后文件没有被关闭!

解决方案是:
一定需要使用try{} catch(){}finally{}语句。try中放入可能出现异常的语句,catch是捕获异常对象,fianlly是一定要执行的代码

//异常在IO流中的使用示例
import java.io.IOException;
import java.io.FileInputStream;

public class Main {
	public static void main(String[] args) throws IOException {
		String path = "C:\\users\\kyle\\desktop\\a.txt";
		readFile(path);
	}

	private static void readFile(String path) {
		FileInputStream fis = null;
		try {
			fis = new FileInputStream(path);
			byte[] byt = new byte[1024];
			int len = fis.read(byt);
			System.out.println(new String(byt, 0, len));
		} catch (IOException e) {
			// 抛出运行时异常
			throw new RuntimeException(e);
		} finally {
			// 把close方法放入finally中保证一定会执行
			// 先判断是否空指针
			if (fis != null) {
				try {
					fis.close();
				} catch (Exception e) {
					throw new RuntimeException(e);
				}
			}
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值