IO:
即in和out,也就是输入和输出,指应用程序和外部设备之间的数据传递,常见的外部设备包括文件、管道、网络连接。
Java 中是通过流处理IO 的,那么什么是流?
流(Stream),是一个抽象的概念,是指一连串的数据(字符或字节),是以先进先出的方式发送信息的通道。
当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件,内存,或是网络连接。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。这时候你就可以想象数据好像在这其中“流”动一样。
一般来说关于流的特性有下面几点:
1.先进先出:最先写入输出流的数据最先被输入流读取到。
2.顺序存取:可以一个接一个地往流中写入一串字节,读出时也将按写入顺序读取一串字节,不能随机访问中间的数据。(RandomAccessFile除外)
3.只读或只写:每个流只能是输入流或输出流的一种,不能同时具备两个功能,输入流只能进行读操作,对输出流只能进行写操作。在一个数据传输通道中,如果既要写入数据,又要读取数据,则要分别提供两个流。
IO流分类
IO流主要的分类方式有以下3种:
按数据流的方向:输入流、输出流
按处理数据单位:字节流、字符流
按功能:节点流、处理流
1、输入流与输出流
输入与输出是相对于应用程序而言的,比如文件读写,读取文件是输入流,写文件是输出流,这点很容易搞反。
2、字节流与字符流
字节流和字符流的用法几乎完成全一样,区别在于字节流和字符流所操作的数据单元不同,字节流操作的单元是数据单元是8位的字节,字符流操作的是数据单元为16位的字符。
为什么要有字符流?
Java中字符是采用Unicode标准,Unicode 编码中,一个英文字母或一个中文汉字为两个字节。
而在UTF-8编码中,一个中文字符是3个字节。例如下面图中,“云深不知处”5个中文对应的是15个字节:-28-70-111-26-73-79-28-72-115-25-97-91-27-92-124
那么问题来了,如果使用字节流处理中文,如果一次读写一个字符对应的字节数就不会有问题,一旦将一个字符对应的字节分裂开来,就会出现乱码了。为了更方便地处理中文这些字符,Java就推出了字符流。
字节流和字符流的其他区别:
字节流一般用来处理图像、视频、音频、PPT、Word等类型的文件。字符流一般用于处理纯文本类型的文件,如TXT文件等,但不能处理图像视频等非文本文件。用一句话说就是:字节流可以处理一切文件,而字符流只能处理纯文本文件。
字节流本身没有缓冲区,缓冲字节流相对于字节流,效率提升非常高。而字符流本身就带有缓冲区,缓冲字符流相对于字符流效率提升就不是那么大了。
字节输入流InputStream主要方法:
read() :从此输入流中读取一个数据字节。
read(byte[] b) :从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。
read(byte[] b, int off, int len) :从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。close():关闭此输入流并释放与该流关联的所有系统资源。
package OutPut;
import java.io.*;
/**
* @author ZhangXiaoDie 2022/12/9 16:23
* @version 1.0
*/
public class InPutTest05 {
public static void main(String[] args) throws IOException {
File f1=new File("D:/a.txt");
InputStream in=new FileInputStream(f1);
//使用缓冲区进行数据读取
byte[] b=new byte[10];
//一次最多读取数组长度个字节,读取的内容转换成对应数字存入byte数组中,返回的是实际读取的字节数
int n=in.read(b);
System.out.println("读取的字节数:"+n);
String s=new String(b,0,n);
System.out.println(s);
byte[] b1=new byte[10];
int n1=in.read(b1);//只剩五个字节,实际读取了5个字节 数组后五个是默认值(无效值)
System.out.println("读取的字节数:"+n1);
String s1=new String(b1,0,n1);//对数组中从0索引开始截取读取到的有效字符数个内容 组成字符串
System.out.println(s1);
byte[] b2=new byte[10];
int n2=in.read(b2);
System.out.println("读取的字节数:"+n2);
String s2=new String(b2,0,n2);
System.out.println(s2);
}
}
运行结果:
字节输出流OutputStream主要方法:
write(byte[] b) :将 b.length 个字节从指定 byte 数组写入此文件输出流中。
write(byte[] b, int off, int len) :将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。
write(int b) :将指定字节写入此文件输出流。
close() :关闭此输入流并释放与该流关联的所有系统资源。
package OutPut;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* @author ZhangXiaoDie 2022/12/8 10:29
* @version 1.0
*/
public class OutPutTest01 {
public static void main(String[] args) throws IOException {
File f1=new File("d:/唐秋博.txt");
f1.createNewFile();
OutputStream out=new FileOutputStream(f1);
String msg="陪伴是最长情的告白";
byte[] bytes=msg.getBytes();
out.write(bytes);
out.close();
}
}
运行结果:
文件复制案例:
package OutPut;
import java.io.*;
/**
* @author ZhangXiaoDie 2022/12/11 20:48
* @version 1.0
*/
public class CopyFileTest06 {
public static void main(String[] args) throws IOException {
//1,定义源文件和目标文件的File对象
File f1=new File("D:/a.txt");
File newFile=new File("D:/newFile.txt");
//2,定义输入输出流关联文件
InputStream in=new FileInputStream(f1);
OutputStream out=new FileOutputStream(newFile);
byte[] buffer=new byte[10];
int n;
while((n=in.read(buffer)) !=-1){
out.write(buffer,0,n);
}
}
}
运行结果: