Java IO操作之字节流与字符流

本文详细介绍了Java中字节流与字符流的概念、使用方法及它们之间的区别。包括OutputStream、InputStream、Writer、Reader等流的实例操作,以及如何进行文件的读写、复制等常见操作。

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

字节流与字符流

Java 程序中所有的数据都是以流的方式进行传输或者保存的。File 类虽然可以操作文件,但是并不是操作文件的内容,如果要进行内容的操作,只能通过两种途径完成:字节流与字符流。

字节流 --> byte类型,JDK 1.0提供

字节流
输入InputStream
输出OutputStream

字符流 --> 字符类型,JDK 1.1提供

字符流
输入Reader
输出Writer

在 Java 中 I/O 操作是有相应的步骤的

  1. 使用 File 类打开一个文件
  2. 通过字节流或者字符流的子类指定输出的位置
  3. 进行读(输入)、写(输出)操作
  4. 关闭输入/输出流。

字节输出流

OutputStream 字节输出流类,是一个专门进行字节数据输出的类,这个类定义如下:

public abstract class OutputStream
extends Object
implements Closeable, Flushable

由此可见,OutputStream 是一个抽象类,如果需要使用此类,就必须要通过子类实例化对象。并且可以发现实现了两个接口:Closeable(表示可以关闭) 与 Flushable(表示可以刷新)。但是在 OutputStream 类中已经定义了两个方法,所以直接使用 OutputStream 类的中的方法就好。

在OutputStream类里面一共提供了三个输出方法

  • 输出单个字节:public abstract void write(int b)throws IOException;
  • 输出全部字节数组:public abstract void write (byte[ ]b)throws IOException;
  • 输出部分字节数组:public abstract void write (byte[ ]b,int off ,int len)throws Exception;

如果只是对文件进行操作,可以使用 FileOutputStream 类

  • 创建或者覆盖已有文件:public FileOutputStream(String name) throws FileNotFoundException
  • 文件内容追加:public FileOutputStream(String name, boolean append) throws FileNotFoundException
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
 
public class Demo {
	public static void main(String[] args) throws Exception {
		// 1.定义要输出的文件路径
		File file = new File("e:" + File.separator + "demo" + File.separator + "test.txt");
		// 2.此时路径不存在,文件不能输出,应该首先创建目录
		if (!file.getParentFile().exists()) {// 文件目录不存在
			file.getParentFile().mkdirs();// 创建目录
		}
		// 3.使用 OutputStream 子类对其进行对象实例化,此时目录存在,文件还不存在
		// new FileOutputStream(file, true) 表示可以追加
		OutputStream output = new FileOutputStream(file);
		String str = "Hello World!";
		// 只能输出 byte 数组,所以讲字符串变为byte数组
		byte data[] = str.getBytes();
		// 讲内容输出,保存文件
		output.write(data);
		// 关闭输出流
		output.close();
		System.out.println(new String(data));
	}
}

字节输入流

对应于字节输出流有一个字节输入流:InputStream 从文件中把内容读取进来。InputStream 定义如下:

public abstract class InputStream
extends Object
implements Closeable

与类 OutputStream 一样,InputStream 本身也是一个抽象类,必须依靠子类完成。如果是对文件进行操作,子类肯定是 FileInputStream,而这个子类构造:

public FileInputStream(File file)throws FileNotFoundException.

InputStream提供数据读取方法

  • 读取单个字节public abstract int read() throws IOException;

    • 返回值:返回读取的字节内容,如果现在已经没有内容。
  • 将读取的数据保存在字节数组里public int read(byte [] b)throws IOException;

    • 返回值:返回读取的数据长度,但是如果已经读到结尾了,返回-1
  • 将读取的数据保存在部分字节数组里public int read(byte [] b, int off, int len) throws IOException;

    • 返回值:返回读取的数据长度,但是如果已经读到结尾了,返回-1;

向数组里读取数据

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
 
public class Demo {
	public static void main(String[] args) throws Exception {
		// 1.定义要输入的文件路径
		File file = new File("e:" + File.separator + "demo" + File.separator + "test.txt");
		// 2.判断路径是否存在才能读取
		if (file.exists()) {
			// 3.使用InputStream进行读取
			InputStream input = new FileInputStream(file);
			// 3.进行数据读取
			byte[] data = new byte[1024];
			// 将内容保存到字节数组中
			int len = input.read(data);
			// 4.关闭输入流
			input.close();
			System.out.println("【" + new String(data, 0, len) + "】");
		}
	}
}

将读取的数据保存在部分字节数组里

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
 
public class Demo {
	public static void main(String[] args) throws Exception {
		// 1.定义要输入的文件路径
		File file = new File("e:" + File.separator + "demo" + File.separator + "test.txt");
		// 2.判断路径是否存在才能读取
		if (file.exists()) {
			// 3.使用InputStream进行读取
			InputStream input = new FileInputStream(file);
			// 3.进行数据读取
			byte[] data = new byte[1024];
			int foot = 0;// 表示数组操作脚标
			int temp = 0;// 表示每次接受的字节数据
			while ((temp = input.read()) != -1) {
				data[foot++] = (byte) temp;// 有内容进行保存
			}
			// 4.关闭输入流
			input.close();
			System.out.println("【" + new String(data, 0, foot) + "】");
		}
	}
}

文件拷贝

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
 
public class Demo {
	public static void main(String[] args) throws Exception {// 此处直接抛出错误
		File inFile = new File("e:" + File.separator + "test.jpg");
		File outFile = new File("e:" + File.separator + "Demo" + File.separator + "testCopy.jpg");
		long start = System.currentTimeMillis();
		if (!inFile.exists()) {
			System.out.println("文件不存在!退出!");
			throw new Exception("文件不存在!退出!");
		}
		if (!outFile.getParentFile().exists()) {
			outFile.getParentFile().mkdirs();
		}
		InputStream in = new FileInputStream(inFile);
		OutputStream out = new FileOutputStream(outFile);
		int temp = 0;
		byte[] data = new byte[1024];
		while ((temp = in.read(data)) != -1) {
			out.write(data, 0, temp);
		}
		in.close();
		out.close();
		long end = System.currentTimeMillis();
		System.out.println("花费时间是:" + (end - start));
	}
}

字符输出流

字符输出流 Writer,定义此类的格式如下:

public abstract class Writer implements Appendable, Closeable, Flushable

Writer 本身也是一个抽象类,如果要使用此类,则肯定要使用其子类,此时如果是向文件中写入内容,应该使用 FileWriter 子类。

在 Writer 中除了可以实现 Closeable 和 Flushable 接口外,还实现了 Appendable 接口,定义如下:

public interface Appendable{
    // 追加一个字符
	public Writer append(char c) throws IOException;
	// 追加 CharSequence 就是指的是字符串
	public Writer append(CharSequence csq) throws IOException;
	// 追加 CharSequence 就是指的是字符串, start 开始,end 结束
	public Writer append(CharSequence csq, int start, int end) throws IOException;
}

实例

Writer里面定义一下输出方法:

  • 输出全部字符数组:public void write(char[ ]cbuf)throws IOException

  • 输出字符串:public void write(String str)throws IOException

import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
 
public class Demo {
	public static void main(String[] args) throws Exception {
		// 1.定义要输出的路径
		File file = new File("e:" + File.separator + "demo" + File.separator + "my.txt");
		if (file.getParentFile().exists()) {
			file.getParentFile().mkdirs();
		}
		// 2.实例化Writer类对象
		Writer out = new FileWriter(file, true);// 追加内容
		// 3.进行内容输出
		String str = "Writer 类输出!";
		// 4.关闭输出流
		out.write(str);
		out.close();
	}
}

字符输入流

Reader 是进行字符数据读取的输入流,其本身也是一个抽象类。

public abstract class Reader extends Object implements Readable, Closeable

在 Reader 类里面提供有

  • 读取内容到字符数组:public int read(char[] cbuf) throws IOException
    • 返回值:表示读取的数据长度,如果已经读取到了结尾了,返回 -1

实例

import java.io.File;
import java.io.FileReader;
import java.io.Reader;
 
public class Demo {
	public static void main(String[] args) throws Exception {
		File file = new File("e:" + File.separator + "my.txt");
		if (file.exists()) {
			Reader in = new FileReader(file);
			int temp = 0;
			int foot = 0;
			char[] data = new char[1024];
			while ((temp = in.read()) != -1) {
				data[foot++] = (char) temp;
			}
			System.out.println(new String(data, 0, foot));
			in.close();
		}
	}
}

字节流与字符流的区别

字节流与字符流最大的区别在于:

  • 字节流直接与终端进行数据交互
  • 字符流需要将数据经过缓冲区处理后才可以输出。

在使用 OutputStream 输出数据的时候,如果没有关闭输出流,流的数据会写入到文件中;如果是使用字符输出流,如果不关闭输出流,那么就表示在缓冲区之中的内容不会强制性的清空,也就是说不会写到文件中,此时需要使用 out.flush() 将内容刷新。

  • 对于字节流处理的是比较多的,例如:图片、音乐、电影、文件等。
  • 对于字符流最大的好处是可以进行中文处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wayfreem

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值