IO流的众多类的介绍
Io技术是什么,这里不做介绍。本文介绍了IO流的众多类的使用和区别。
本文介绍的类有
- IO流的众多类的介绍
- File类
- InputStream+FileInputStream
- OutputStream+FileOutputStream
- Reader+FileReader
- Writer+FileWriter
- InputStreamReader+OutputStreamWriter
- InputStream+ByteArrayOutputStream
- BufferedInputStream
- BufferedOutputStream
- BufferedReader
- BufferedWriter
- DataOutputStream+DataInputStream
- ObjectOutputStream+ObjectInputStream
- ByteArrayOutputStream+ByteArrayInputStream
- RandomAccessFile
先看看IO众多类的关系。如图
好了,直接上代码。
File类
File类称源,数据源。主要获取文件的信息。
public static void main(String[] args) {
//参数是你要操作文件的路径
File file = new File("D:/bc/idea_java/javase/");
//基本信息
System.out.println("名称:"+file.getName());
System.out.println("路径:"+file.getPath());
System.out.println("绝对路径:"+file.getAbsolutePath());
System.out.println("父路径:"+file.getParent());
System.out.println("父对象:"+file.getParentFile());
System.out.println("是否是文件夹"+file.isDirectory());
System.out.println("是否存在"+file.exists());
System.out.println("是否是文件"+file.isFile());
//获取目录下的全部文件
File[] files = file.listFiles();
for (File file1 : files) {
if(file1.isDirectory()){
//file1.length()该文件的大小
System.out.println("目录:"+file1.getPath()+file1.length());
}else{
System.out.println("文件:"+file1.getPath()+file1.length());
}
}
File newfile = new File("src/3.txt");
//创建一个文件名字是3.txt。就是new File("src/3.txt");的参数路径最后的名
try {
newfile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
File mkdirFile = new File("src/A");
//创建一个目录。目录名是A。就是new File("src/A");的参数
//mkdirFile.mkdirs()和mkdirFile.mkdir();的区别
//mkdirFile.mkdirs()如果父级的路径不存在会自动创建,mkdirFile.mkdir()父级目录不存在抛出异常
mkdirFile.mkdir();
}
利用File类结合递归算出文件夹的字节数
递归就是自己调用自己。是循环的简写。
public class FileDemo03 {
private Long fileSize=0l;
public void dfs(File file){
if(file.isFile()){
fileSize+=file.length();
return ;
}
File[] files = file.listFiles();
for (File file1 : files) {
dfs(file1);
}
}
public static void main(String[] args) {
FileDemo03 demo = new FileDemo03();
demo.dfs(new File("D:/bc/idea_java/javase/src"));
System.out.println("文件大小:"+demo.fileSize);
}
}
InputStream+FileInputStream
把数据源读取到出来。会出现中文乱码。因为是以字节的方式读取中文3个字节,英文是1个。不能保证每个中文都能完整读出
public class Main {
public static void main(String[] args) {
File file = new File("src/2.txt");
try ( InputStream is = new FileInputStream(file);){
int len=-1;
//is.read();放回的是int类型。转回字符就好、当读取到文件结尾时返回-1
//is.read();是一个字节一个字节的读取的。使用文件出现中文会乱码
//is.read(bytes);加入字节缓存区。一次读取三个字节。
//is.read(bytes);中文还是会乱码。因为字母是1个字符。中文是3个。
byte[] bytes = new byte[3];
while((len=is.read(bytes))!=-1){
//解码
String value = new String (bytes,0,len);
System.out.print(value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
OutputStream+FileOutputStream
把数据(字节数组)写入数据源中。
public class Main {
public static void main(String[] args) {
File file = new File("src/2.txt");
String msg = "我是输出流。我将会出现在2.txt文件中";
//FileOutputStream(file,true);file代表要写入的目的地,true代表追加。默认是false.先清空再写入
try ( OutputStream out = new FileOutputStream(file,true);){
byte[] bytes = msg.getBytes();
//以字节的方式写入数据源(文件)中
out.write(bytes,0,bytes.length);
//刷新
out.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
}
实现文件复制OutputStream+InputStream
public class Main {
public static void main(String[] args) {
File from = new File("src/1.txt");
File to = new File("src/2.txt");
//实现文件1.txt的内容复制到文件2.txt中
try(InputStream in = new FileInputStream(from);
OutputStream out = new FileOutputStream(to)) {
byte[] bytes = new byte[1024];
int len;
//读取1.txt文件数据到bytes中.每次读取1K
while ((len=in.read(bytes))!=-1){
//数据读取到了bytes中
//把数据写到2.txt中
out.write(bytes,0,len);
out.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Reader+FileReader
以字符的形式读取。不会出现中文乱码。但是无法读到图片视频。
只能读取纯字符文件
public class Main {
public static void main(String[] args) {
File file = new File("src/2.txt");
try(FileReader reader = new FileReader(file);) {
int lenth = 0;
char data[] = new char[1024];
//把数据读取出来。以字符的形式
while((lenth=reader.read(data))!=-1){
System.out.print(String.valueOf(data));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Writer+FileWriter
字符的形式写入
public class Main {
public static void main(String[] args) {
File file = new File("src/2.txt");
//FileWriter(file,true);数据源,是否是追加的方式
try(FileWriter writer = new FileWriter(file,true);) {
String msg = "我将去到2.txt。我是以字符的方式过去的";
//把数据读取出来。以字符的形式
// writer.write(msg);参数可以是字符串也可以是字符数组等等。。。
writer.write(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
}
InputStreamReader+OutputStreamWriter
InputStreamReader将字节输入流转换成字符输入流。解决乱码问题
FileReader底层也是调用了InputStreamReader才解决了中文乱码问题
OutputStreamWriter反之
public class Main {
public static void main(String[] args) {
File file = new File("src/2.txt");
try {
//都知道FileInputStream无法保证中文完整输出。是字节流
InputStream inputStream = new FileInputStream(file);
//转化为字符流。因为好多高级框架最终返回的都在字节流。所以需要InputStreamReader来转化
//参数是要转化的字节流。字符编码可以选择性填写
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
//接下来就和FileReader类一样操作就好
FileOutputStream fileOutputStream = new FileOutputStream(file);
//把输出字节流转化为输出字符流
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "utf-8");
} catch (Exception e) {
e.printStackTrace();
}
}
}
InputStream+ByteArrayOutputStream
InputStream对文件读取时都是读取完就关闭了。第二次需要是只能再次读取。ByteArrayOutputStream可以保存数据,起到缓存的作用。ByteArrayOutputStream操作的是字节。
public class Main {
public static void main(String[] args) {
File file = new File("src/2.txt");
try( InputStream in = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
) {
int len;
byte[] bytes = new byte[1024];
while((len=in.read(bytes))!=-1){
//把获取的数据保存到ByteArrayOutputStream数据源中
bos.write(bytes,0,len);
}
//单需要二次调用是
byte[] bosValue = bos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
}
}
}
BufferedInputStream
BufferedInputStream是对FileInputStream的加强。使用了修饰模式
修饰模式就是不动源代码的情况下## 标题对其进行加强。主要在获取大点的文件时可以加快其获取速度
public static void main(String[] args) {
File file = new File("src/2.txt");
//本是->InputStream is = new FileInputStream(file);
//现在变成了BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(file));
//在获取数据的速度变快了。在获取大文件才会体现出优势
try ( BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(file));){
int len=-1;
byte[] bytes = new byte[3];
while((len=bufferedInputStream.read(bytes))!=-1){
//解码
String value = new String (bytes,0,len);
System.out.print(value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
BufferedOutputStream
BufferedOutputStream是对FileOutputStream的加强。同样是修饰模式。
public class Main {
public static void main(String[] args) {
File file = new File("src/2.txt");
String msg = "我是输出流。我将会出现在2.txt文件中";
//FileOutputStream(file,true);file代表要写入的目的地,true代表追加。默认是false.先清空再写入
//原理是-》OutputStream out = new FileOutputStream(file,true);
//修饰加强-》BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file,true));
try (BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file,true));){
byte[] bytes = msg.getBytes();
//以字节的方式写入数据源(文件)中
out.write(bytes,0,bytes.length);
//刷新
out.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
}
BufferedReader
BufferedReader是对FileReader的加强。
reader.readLine()是加强的方法可以一行一行的读取
public static void main(String[] args) {
File file = new File("src/2.txt");
//原来->FileReader reader = new FileReader(file);
// 加强->BufferedReader reader = new BufferedReader(new FileReader(file));
try(BufferedReader reader = new BufferedReader(new FileReader(file));) {
char data[] = new char[1024];
//把数据读取出来。以字符的形式
//原来-》(lenth=reader.read(data))!=-1
String value = null;
//reader.readLine()是加强的方法可以一行一行的读取
while((value = reader.readLine())!=null){
System.out.println(String.valueOf(value));
}
} catch (Exception e) {
e.printStackTrace();
}
}
BufferedWriter
BufferedWriter是对FileWriter的加强
新增了 bufferedWriter.newLine();//换行
public static void main(String[] args) {
File file = new File("src/2.txt");
//FileWriter(file,true);数据源,是否是追加的方式
//原来->FileWriter writer = new FileWriter(file,true);
//加强->BufferedWriter writer =new BufferedWriter(new FileWriter(file,true));
try(BufferedWriter writer =new BufferedWriter(new FileWriter(file,true));) {
String msg = "我将去到2.txt。我是以字符的方式过去的";
//把数据读取出来。以字符的形式
// writer.write(msg);参数可以是字符串也可以是字符数组等等。。。
writer.write(msg);
writer.flush();
writer.newLine();//换行
writer.write("换行插入,writer.newLine();我是加强的方法");
} catch (Exception e) {
e.printStackTrace();
}
}
DataOutputStream+DataInputStream
DataInputStream和DataOutputStream,可以存取数据类型
public static void main(String[] args) {
// DataOutputStream data = new DataOutputStream(bufferedOutputStream);
//DataOutputStream需要一个输出流
try (
BufferedOutputStream bufferedOutputStream =new BufferedOutputStream(new FileOutputStream("src/1.ss"));
DataOutputStream data = new DataOutputStream(bufferedOutputStream);){
data.writeChar('c');
data.writeDouble(1.25);
data.writeLong(17888);
data.writeUTF("小明");
data.flush();//记得刷新,一定要
//DataInputStream dataIn = new DataInputStream(new FileInputStream("src/1.ss"));
//参数是输入流
DataInputStream dataIn = new DataInputStream(new FileInputStream("src/1.ss"));
//注意获取的顺序和写入的要一致
System.out.println(dataIn.readChar());
System.out.println(dataIn.readDouble());
System.out.println(dataIn.readLong());
System.out.println(dataIn.readUTF());
} catch (IOException e) {
e.printStackTrace();
}
}
ObjectOutputStream+ObjectInputStream
ObjectInputStream和ObjectInputStream可以存取数据类型加对象
public class Main {
public static void main(String[] args) {
//和DataOutputStream+DataInputStream做法差不多
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try( ObjectOutputStream oo = new ObjectOutputStream(new BufferedOutputStream(bos));) {
//存的对象必须要实现implements java.io.Serializable
//implements java.io.Serializable告诉jvm可以序列化
oo.writeObject(new String("1223"));
oo.writeObject(new Date());
oo.flush();
byte[] bytes = bos.toByteArray();
ObjectInputStream oi = new ObjectInputStream(new BufferedInputStream(new ByteArrayInputStream(bytes)));
String o = (String)oi.readObject();
Date date = (Date)oi.readObject();
System.out.println(o);
System.out.println(date.getTime());
} catch (Exception e) {
e.printStackTrace();
}
}
ByteArrayOutputStream+ByteArrayInputStream
当你想把对象变量转换成字节数组是就用到了ByteArrayOutputStream。ByteArrayOutputStream除了缓存IO流数据还有一个好处是,把输入的转换成字节数组
可以说和OutputStreamWriter相反。ByteArrayOutputStream和ByteArrayIntputStream是有对可以类比
public class Main {
public static void main(String[] args) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
//原来是 new FileOutputStream("src/1.java");这个要进行本地文件的读取会好慢
DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream);
try {
dataOutputStream.writeUTF("你好");
dataOutputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
//转成字节数组
byte[] bytes = byteArrayOutputStream.toByteArray();
//把new FileInputStream("src/1.java");换成了new ByteArrayInputStream(bytes);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
DataInputStream dataInputStream = new DataInputStream(byteArrayInputStream);
try {
String value = dataInputStream.readUTF();
System.out.println(value);
} catch (IOException e) {
e.printStackTrace();
}
//结果
// 你好
}
}
RandomAccessFile
RandomAccessFile可以拆分存取。
public class Main {
public static void main(String[] args) {
//RandomAccessFile("src/2.txt","r");第二个参数r代表读,rw代表写
try(RandomAccessFile from =new RandomAccessFile("src/1.txt","r");
RandomAccessFile to =new RandomAccessFile("src/2.txt","rw");) {
//从什么位置读起,单位是字节
from.seek(10);
int size=100;//设置读取多少个字节
byte[] bytes = new byte[1024];
int len;
while((len=from.read(bytes))!=-1){
if(len<size){
to.write(bytes,0,len);
size-=len;//一个读起size个字节。读一次size就剩下size-len
}else{
//len大于size只能要size。要不就读多了
to.write(bytes,0,size);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
可以考虑做一个类似分批下载的功能