什么是IO流?流是什么?
流是一种抽象概念,它代表了数据的无结构化传递。
按照流的方式进行输入输出,数据被当成无结构的字节序或字符序列。从流中取得数据的操作称为提取操作,而向流中添加数据的操作称为插入操作。用来进行输入输出操作的流就称为IO流。
Java.io 包几乎包含了所有操作输入、输出需要的类。所有这些流类代表了输入源和输出目标。
IO流的类图
java.io 下的类的关系图:
流的分类
- 按照操作的数据的单位的不同可以分为 字符流(按字符)和 字节流 (bit)二进制文件.
- 输入和输出的流向不同 输入流,输出流
- 根据流的角色不同分为:节点流,处理流/包装流
根据上图也可以观察到,流的类有好多个,但是都是由四个基类派生出来的。
抽象基类类名 | 类型 |
---|---|
InputStream | 字节输入流 |
OutputStream | 字节输出流 |
Reader | 字符输入流 |
Writer | 字节输出流 |
字符与字节的区别
字节 (Byte)是计量单位,表示数据量多少,是计算机信息技术用于计量存储容量的一种计量单位,通常情况下一字节等于八位。
字符 (Character)计算机中使用的字母、数字、字和符号,比如’A’、‘B’、‘$’、'&'等。一般在英文状态下一个字母或字符占用一个字节,一个汉字用两个字节表示。
总的来说,字节流一般用来处理图像、视频、音频、PPT、Word等类型的文件(二进制文件)。 字符流一般用于处理纯文本类型的文件,如TXT文件等,但不能处理图像视频等非文本文件。 用一句话说就是:字节流可以处理一切文件,而字符流只能处理纯文本文件。 字节流本身没有缓冲区,缓冲字节流相对于字节流,效率提升非常高。 而字符流本身就带有缓冲区,缓冲字符流相对于字符流效率提升就不是那么大了。
FileInputStream的使用
1.构造器
构造方法 | 描述 |
---|---|
FileInputStream(File file) | 通过File对象来获取一个FileInputStream的对象 |
FileInputStream(FileDescriptor fdObj) | 通过使用文件描述符 fdObj创建 FileInputStream |
FileInputStream(File file) | 通过File对象来获取一个FileInputStream的对象 |
FileInputStream(String name) | 通过文件路径字符串来获取一个FileInputStream的对象 |
2.常用方法
方法名 | 描述 |
---|---|
void close() | 关闭此文件输入流并释放与流相关联的任何系统资源。 |
int read() | 从该输入流读取一个字节的数据。 |
int read(byte[] b) | 从该输入流读取最多 b.length个字节的数据到一个字节数组 |
int read(byte[] b, int off, int len) | 从该输入流读取最多 len个字节的数据到字节数组,off限定了读取的起始地址 |
3.使用FileInputStream来读取txt文件
使用read() ,读取单个字节的数据,效率较低,且中文不可读取:
package re;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class FileInputStream_01 {
public static void main(String[] args) {
// 1.确定文件路径 注意 windows 的路径,需要使用双斜杠,因为java中的转义字符....
String filePath = "D:\\a.txt";
// 2.读取到的数据
int readLine = 0;
FileInputStream fis = null;
// 使用try-catch来捕获异常
try {
fis = new FileInputStream(filePath);
// 因为字节流不可能是一次性的将txt文件中的内容读取
// 所以使用 while 循环来读取 ,
// read方法如果读取到 末尾的话则会返回 -1
while((readLine = fis.read())!=-1){
System.out.print((char)readLine);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
// 关闭流,释放资源
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
使用多个字节读取 int read(byte[] b) 从该输入流读取最多 b.length个字节的数据到一个字节数组:
读取中文文本时,如果该中文文本有空格,中文字符还会乱码,因为中文空格和字符都是按照半个字节计算的。解决中文乱码的问题使用字符流即可
package re;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class FileInputStream_02 {
public static void main(String[] args) {
// 1.文件路径
String filePath = "D:\\b.txt";
// 2.字节数组 定义一个字节长度为8的字节数组
byte[] buf = new byte[8];
// 读取长度
int readLen = 0;
FileInputStream fis = null;
try {
fis = new FileInputStream(filePath);
// 如果读取正常,返回读取的字节数
// 到达文件末尾,返回-1
while ((readLen=fis.read(buf))!=-1){
// 控制台打印显示
System.out.print(new String(buf,0,readLen));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭释放流
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
FileOutputStream的使用
FileOutputStream用于写入诸如图像数据的原始字节流。 对于写入字符流,应该使用FileWriter 。
1.构造器
构造器 | 描述 |
---|---|
FileOutputStream(File file) | 创建文件输出流以写入由指定的 File对象表示的文件。 |
FileOutputStream(File file, boolean append) | 创建文件输出流以写入由指定的 File对象表示的文件,其中append用来决定该输出流的写出模式,是从头开始覆盖(false)还是末尾追加写出的方式(true) |
FileOutputStream(FileDescriptor fdObj) | 创建文件输出流以写入指定的文件描述符,表示与文件系统中实际文件的现有连接。 |
FileOutputStream(String name) | 创建文件输出流以指定的名称写入文件。 |
FileOutputStream(String name, boolean append) | 创建文件输出流以指定的名称写入文件,append为true表示末尾追加,append为false表示从头开始覆盖。 |
2.常用方法
方法名及返回值类型 | 功能 |
---|---|
void write(byte[] b) | 将 b.length个字节从指定的字节数组写入此文件输出流。 |
void write(byte[] b, int off, int len) | 将 len字节从位于偏移量 off的指定字节数组写入此文件输出流。 |
void write(int b) | 将指定的字节写入此文件输出流。 |
void close() | 关闭此文件输出流并释放与此流相关联的任何系统资源。 |
3.使用FileOutputStream写入字符到txt文件
需要注意的是
1.使用fileOutputStream = new FileOutputStream(filePath);
创建方式,写入文件是覆盖写的模式
2.使用 fileOutputStream = new FileOutputStream(filePath,true);
创建方式,则写入文件是末尾追加。—>查看相关的构造器即可
package re;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
// 字符输出流
public class FileOutputStream_01 {
public static void main(String[] args) {
// 1.写入文件路径
String filePath = "D:\\c.txt";
// 2.获取 fileOutputStream 对象
FileOutputStream fos = null;
try {
fos = new FileOutputStream(filePath);
// 简单的写入一段英文字符串
String str = "hello!txt";
// 读取指定长度的字节 void write(byte[] b, int off, int len)
// 将 len字节从指定的字节数组开始,从偏移量 off开始写入此文件输出流。
fos.write(str.getBytes(),0,str.length());
} catch (IOException e) {
e.printStackTrace();
}finally {
// 关闭流,释放资源
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
图片文件拷贝
1.使用fileInputStream流读取文件
2.使用fileOutPutStream流输出文件
3.采用边读边写的方式
package com.gothic.outputStream_;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileCopy {
//文件拷贝
public static void main(String[] args) {
// 1.使用fileInputStream流读取文件
// 2.使用fileOutPutStream流输出文件
// 3.采用边读边写的方式
//源文件目录
String srcFilePath = "D:\\雷神.jpg";
//目的文件目录
String destFilePath = "D:\\LS.jpg";
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
fileInputStream = new FileInputStream(srcFilePath);
fileOutputStream = new FileOutputStream(destFilePath);
// 每次读取1024个字节
byte[] buf = new byte[1024];
int readLen = 0;
while ((readLen=fileInputStream.read(buf))!=-1){
// 边读边写
fileOutputStream.write(buf,0,readLen);
}
System.out.println("ok,拷贝成功!");
} catch (IOException e) {
e.printStackTrace();
}finally {
// 关闭流,释放资源
try {
if(fileInputStream!=null){
fileInputStream.close();
}
if(fileOutputStream!=null){
fileOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
用到的图片: