- IO流的分类
按操作数据单位的不同分为:字节流和字符流
按数据流的流向不同分为:输入流和输出流
按流的角色不同分为:节点流和处理流(包装流)
字节流主要用于处理二进制数据,例如图片、视频、音频等非文本数据。
字符流主要用于处理文本数据,例如读取和写入文本文件中的字符数据。
输入流:输入流用于从数据源(如文件、网络连接、内存等)读取数据到程序中。(往内存中写入)
输出流:输出流用于将程序中的数据写入到目标位置(如文件、网络连接、内存等)。(从内存中写)出
节点流:节点流是直接与数据源或目标进行连接的流,它们提供了最基本的数据读取和写入功能。(直接跟数据源相接)
处理流:处理流是对节点流的功能增强,通过对节点流的包装,提供了更高级别的数据处理功能。处理流不直接操作数据源或目标,而是通过包装节点流来实现数据的加工和处理。处理流可以在节点流的基础上提供缓冲、字符编码转换、数据压缩等功能。
Java的IO流共涉及40+个类,实际上非常规则,都是从上面4个抽象基类中派生的。由这4个基类派生出来的子类名称都是以其父类名作为子类名后缀
字节流和字符流一览图:
节点流和处理流一览图:
FileInputStream 字节流读文件
代码:
public class FileInputStream_ {
public static void main(String[] args) {
}
@Test
public void fileInputStream() {
String filePath = "d:\\hello.txt";
int fileData = 0;
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(filePath);
while ((fileData = fileInputStream.read())!= -1){//read()一次只能读取一个字节,效率低,用read(byte[])一次可以读取多个字节,效率较高
//read()返回的是0,1组成的字节
System.out.print((char)fileData);//若不转化为char类型,则输出的是字节10410110810811132119111114108100
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void fileInputStreamImprove() {
String filePath = "d:\\hello.txt";
byte[] buf = new byte[8];
int length = 0;
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(filePath);
while ((length = fileInputStream.read(buf))!= -1){//read(byte[])一次可以读取多个字节,效率较高
//read(byte[])返回的是字节长度
System.out.print(new String(buf,0,length));//将char数组转化为String类型
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
FireReader 字符流读文件
代码:
public class FireRead {
public static void main(String[] args) {
}
/**
* 单个字符读取文件
*/
@Test
public void readFile01() {
String filePath = "d:\\read.txt";
FileReader fileReader = null;
int data = 0;
//1. 创建 FileReader 对象
try {
fileReader = new FileReader(filePath);
//循环读取 使用 read, 单个字符读取
while ((data = fileReader.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileReader != null) {
fileReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 字符数组读取文件
*/
@Test
public void readFile02() {
String filePath = "d:\\read.txt";
FileReader fileReader = null;
int readLen = 0;
char[] buf = new char[8];
//1. 创建 FileReader 对象
try {
fileReader = new FileReader(filePath);
//循环读取 使用 read(buf), 返回的是实际读取到的字符数
//如果返回-1, 说明到文件结束
while ((readLen = fileReader.read(buf)) != -1) {
System.out.print(new String(buf, 0, readLen));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileReader != null) {
fileReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
FileOutputStream 字节流写文件
代码:
public class FileOutputStream_ {
public static void main(String[] args) {
}
@Test
public void writeFile(){
String filePath = "d:\\hello.txt";
FileOutputStream fileOutputStream = null;
try {
//若在此d:\hello.txt路径下没有找到该文件,则自己自动创建一个该文件
fileOutputStream = new FileOutputStream(filePath);//这种方式会将之前文件中的内容清除后在输入,FileOutputStream(filePath,true)这种方式会在后面直接追加内容,而不会清除原先的内容
//fileOutputStream = new FileOutputStream(filePath,true);//这种方式会在后面直接追加内容,而不会清除原先的内容
//方式1 输入单个字符
//fileOutputStream.write('R');
//方式2 输入多个字符
//fileOutputStream.write("hello".getBytes());//getBytes()将字符串转化为byte[]
//方式3 输入多个字符,指定输入的偏移量和长度
fileOutputStream.write("hello".getBytes(),0,2);
System.out.println("输入成功");
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
FireWriter 字符流写文件
代码:
public class FileWriter_ {
public static void main(String[] args) {
String filePath = "d:\\writer.txt";
//创建 FileWriter 对象
FileWriter fileWriter = null;
char[] chars = {'a', 'b', 'c'};
try {
fileWriter = new FileWriter(filePath);//默认是覆盖写入
// 3) write(int):写入单个字符
fileWriter.write('H');
// 4) write(char[]):写入指定数组
fileWriter.write(chars);
// 5) write(char[],off,len):写入指定数组的指定部分
fileWriter.write("hello world".toCharArray(), 0, 3);
// 6) write(string):写入整个字符串
fileWriter.write(" 你好北京~");
fileWriter.write("风雨之后,定见彩虹");
// 7) write(string,off,len):写入字符串的指定部分
//在数据量大的情况下,可以使用循环操作.
} catch (IOException e) {
e.printStackTrace();
} finally {
//对应 FileWriter , 一定要关闭流,或者 flush 才能真正的把数据写入到文件
//看源码就知道原因.
/*
看看代码
private void writeBytes() throws IOException {
this.bb.flip();
int var1 = this.bb.limit();
int var2 = this.bb.position();
assert var2 <= var1;
int var3 = var2 <= var1 ? var1 - var2 : 0;
if (var3 > 0) {
if (this.ch != null) {
assert this.ch.write(this.bb) == var3 : var3;
} else {
this.out.write(this.bb.array(), this.bb.arrayOffset() + var2, var3);
}
}
this.bb.clear();
}
*/
try {
//fileWriter.flush();
//关闭文件流,等价 flush() + 关闭
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("程序结束...");
}
}
BufferReader 使用处理流读文件
代码:
public class BufferReader {
public static void main(String[] args) throws Exception {
String filePath = "d:\\bufferRead.java";
//创建 bufferedReader
BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
//读取
String line; //按行读取, 效率高
//1. bufferedReader.readLine() 是按行读取文件
//2. 当返回 null 时,表示文件读取完毕
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
//关闭流, 这里注意,只需要关闭 BufferedReader ,因为底层会自动的去关闭 节点流
//FileReader。
/*
源码:
public void close () throws IOException {
synchronized (lock) {
if (in == null)
return;
try {
in.close();//in 就是我们传入的 new FileReader(filePath), 关闭了. } finally {
in = null;
cb = null;
}
}
}
*/
bufferedReader.close();
}
}
BufferWriter 使用处理流写文件
代码:
public class BufferWriter {
public static void main(String[] args) throws IOException {
String filePath = "d:\\bufferWriter.txt";
//创建 BufferedWriter
//1. new FileWriter(filePath, true) 表示以追加的方式写入
//2. new FileWriter(filePath) , 表示以覆盖的方式写入
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath));
bufferedWriter.write("hello, world1");
bufferedWriter.newLine();//插入一个和系统相关的换行
bufferedWriter.write("hello, world2");
bufferedWriter.newLine();
bufferedWriter.write("hello, world3");
bufferedWriter.newLine();
//说明:关闭外层流即可 , 传入的 new FileWriter(filePath) ,会在底层关闭
bufferedWriter.close();
}
}
处理流读文件(BufferReader)和写文件(BufferWriter)的应用之复制文件(文本文件)
代码:
public class BufferCopy {
public static void main(String[] args) {
//1. BufferedReader 和 BufferedWriter 是适用于字符操作,不要去操作二进制文件[声音,视频,doc, pdf ], 可能造成文件损坏
//BufferedInputStream
//BufferedOutputStream
String srcFilePath = "d:\\bufferRead.txt";
String destFilePath = "d:\\bufferWriter2.txt";
BufferedReader br = null;
BufferedWriter bw = null;
String line;
try {
br = new BufferedReader(new FileReader(srcFilePath));
bw = new BufferedWriter(new FileWriter(destFilePath));
while ((line = br.readLine()) != null) {
//每读取一行,就写入,否则内容全都输入在一行了
bw.write(line);
//插入一个换行
bw.newLine();
}
System.out.println("拷贝完毕...");
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流
try {
if(br != null) {
br.close();
}
if(bw != null) {
bw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
处理流读文件(BufferInputStreacm)和写文件(BufferOutputStram)的应用之复制文件(二进制文件---图片)
代码:
public class BufferInputStreamBufferOutputStreamStreamCopy {
public static void main(String[] args) {
String srcFilePath = "d:\\线程状态.bmp";
String destFilePath = "d:\\拷贝线程状态buffer.bmp";
//创建 BufferedOutputStream 对象 BufferedInputStream 对象
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
//因为 FileInputStream 是 InputStream 子类
bis = new BufferedInputStream(new FileInputStream(srcFilePath));
bos = new BufferedOutputStream(new FileOutputStream(destFilePath));
//循环的读取文件,并写入到 destFilePath
byte[] buff = new byte[1024];
int readLen = 0;
//当返回 -1 时,就表示文件读取完毕
while ((readLen = bis.read(buff)) != -1) {
bos.write(buff, 0, readLen);
}
System.out.println("文件拷贝完毕~~~");
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流 , 关闭外层的处理流即可,底层会去关闭节点流
try {
if (bis != null) {
bis.close();
}
if (bos != null) {
bos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}