IO流(Java)
目录
案例:使用FileWiter和FileReader实现对文本文件的复制
一、概述
Hello,各位观众老爷,又到了每周的分享时间了,这周小的学习了Java中的IO流,在这里...算了不废话了,直接开始!
IO流其实在我理解看来就分成三部分,即I、O、流。I即Input,输入。O即Output,输出。流是数据传输的总称。
更通俗一点、把自己想成计算机的内存,以第一人称去理解这个问题。比如人要看书对吧,那么把书中的知识读取到自己的大脑(也就是内存)中这个操作就是输入,这个操作类比到计算机中就是从硬盘上读取数据到内存中,也就是IO流中的I(Input)。
同理,我们有时候要写博客对吧,那么写博客这个操作是不是人把自己大脑(也就是内存)中想的东西写到纸上,那这个操作类比到计算机上就是把内存中的数据写到硬盘上,即IO流中的O(Output)。
好了,上述是本人对IO流的一个最基本的理解,主要是助于快速理清Input和Output的区别,如果有错误的地方,请各位观众老爷指出。接下来正式进入IO流的探讨了!
二、File类
在计算机中,对于数据的存储都离不开文件,IO流也是对文件进行操作,所以我们先来探讨File类。
2.1作用
File类是文件和目录名路径的抽象表示形式,其封装的并不是一个真正存在的文件,而仅仅是一个路径名,可以存在,也可以不存在。
2.2构造方法
File(String pathName) | 根据字符串路径创建一个File对象 |
File(String parent,String child) |
根据字符串父级路径和子级路径创建File对象 |
File(File parent,String child) |
根据File类型父级路径和字符串子级路径创建File对象 |
2.3常用方法
2.3.1创建方法
boolean createNewFile() |
创建一个新文件 |
boolean mkdir() | 创建单级文件夹 |
boolean mkdirs() | 创建多级文件夹 |
2.3.2判断方法
boolean isDirectory() |
判断是否是文件夹 |
boolean isFile() | 判断是否是文件 |
boolean exists() | 判断文件是否存在 |
2.3.3获取方法
String getAbsolutePath() |
获取绝对路径 |
String getPath() | 获取构造方法中的路径 |
String getName() | 获取文件或文件夹的名称 |
String[] list() | 获取目录下所有内容,返回字符串数组 |
File[] listFiles() | 获取目录下所有内容,返回File对象数组 |
这里要提两个概念:相对路径和绝对路径 。
相对路径: 是一个简化的路径,不以根路径为开头。如:\a.txt 。
绝对路径:一个完整的路径,以根路径开头。如:D:\a.txt。
2.3.4删除方法
boolean delete() |
删除文件或文件夹(文件夹必须为空) |
注:当待删除文件夹中还有文件夹或者文件时,是不能直接删除此文件夹的,必须!!!把该文件夹以下的文件和文件夹全部删除之后才能删除此文件夹。
三、IO流
了解了File类时候,我们可以正式开始今天的探讨内容IO流了。在前面本人对IO流作了一个大概的讲述,下面我们来详细探讨!
3.1分类
按数据流向:输入流和输出流
输入流:把数据从硬盘上读取到内存中。
输出流: 把数据从内存中写出到硬盘上。
按数据类型:字节流和字符流
字节流:读写数据以字节为单位的流。
字符流:读写数据以字符为单位的流。
在实际应用中,文件的上传下载以及传输是比较常见的。
以下两张图概括性的描述了字节流和字符流:
字节流:
字符流:
看完这两张图之后,我们接着再来分别对字节流和字符流进行探讨。
3.2字节流
3.2.1字节输入流(InputStream)
InputStream:这个抽象类是表示字节输入流的所有类的超类。
字节输入流的共性方法;
void close() | 关闭此流并释放与此流相关的资源。 |
abstract int read() | 从输入流读取一个字符。 |
int read(byte[] b) | 该方法返回的int值代表的是读取了多少个字节,读到几个返回几个,读取不到返回-1 |
FileInputStream
文件输入流,读取的是字节。
构造方法:
FileInputStream(File file) | 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。 |
FileInputStream(String name) | 通过打开与实际文件的连接来创建一个FileInputStream ,该文件由文件系统中的路径名name命名。 |
FileInputStreram读取字节数据
1.一次读一个字符数据
2.一次读一个字节数组的数据
提问:如何实现图片的复制呢?
3.2.2字节输出流(OutputStream)
字节输出流,将数据以字节形式写到文件中。
构造方法:
public FileOutputStream(File file) | 以File对象为参数创建对象 |
public FileOutputStream(String name) | 以字符串名称为参数创建对象 |
OutputStream写数据:
write(int b) | 一次写一个字节数据 |
write(byte[] arr) | 一次写一个字节数组 |
write(byte[] arr,int index,int len) | 写字节数组的一部分 |
看到这里,我们就可以解决刚才的提问了。
现在我们再次把目光转回刚才的问题:如何实现文本文件的复制。对了,我们可以先创建FileInputStream对象先读取需要复制的文本文件,再创建FileOutputStream对象关联需要写出的文件,通过循环进行读和写的操作,最后释放资源。
步骤:
具体代码:
public class FosTest {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("D:\mytemp\mn.jpg");
//创建字节输入流对象,关联文件.这里的文件为自己需要复制文件的路径
FileOutputStream fos = new FileOutputStream("path08\mytemp\mn.jpg");
//创建字节输出流对象,关联文件
//循环读写操作
int len;
byte[] bys = new byte[1024];
while ((len = fis.read(bys))!=-1){
fos.write(bys,0,len);
}
//释放资源
fis.close();
fos.close();
}
}
两个问题:
3.3字符流
3.3.1字符输入流(Reader)
读取字符信息到内存中。
字符输入流的共性方法:
public void close() | 关闭此流并释放与此流相关联的任何系统资源。 |
int read() | 从输入流读取一个字符。 |
int read(char[] cbuf) | 从输入流中读取一些字符,并将它们存储到字符数组cbuf中 |
FileReader类
构造方法:
FileReader(File file) | 创建一个新的 FileReader ,给定要读取的File对象。 |
FileReader(String fileName) | 创建一个新的 FileReader ,给定要读取的文件的字符串名称。 |
FileReader读取字符数据
3.3.2字符输出流(Writer)
将指定的字符数据写到文件中。
共性方法:
Write(int b) | 写一个字符 |
write(char[] c) | 写一个字符数组 |
write(char[] c,int off,int len) | 写一个字符数组的一部分 |
write(String s) | 写一个字符串 |
write(String s,int off,int len) | 写一个字符串的一部分· |
flush() | 刷新该流的缓冲 |
close() | 释放资源,先刷新 |
FileWriter类
构造方法:
FileWriter(File file) | 创建一个新的 FileWriter,给定要读取的File对象。 |
FileWriter(String fileName) | 创建一个新的 FileWriter,给定要读取的文件的名称 |
写数据方法:
案例:
public class FwTest {
public static void main(String[] args) throws IOException {
//创建字符输出流对象
FileWriter fw = new FileWriter("D:\mytemp\a.txt");
//续写
//FileWriter fw = new FileWriter("D:\mytemp\a.txt",true);
//写数据
fw.write(97);
fw.write("rn");//换行操作
fw.write("hello");
//释放资源
fw.close();
}
}
注:FileWiter中的换行是书写"rn", 续写则是在创建对象时加上true。
案例:使用FileWiter和FileReader实现对文本文件的复制
这里只使用了一种方式,其他方式请各位观众老爷自己动动小手,尝试一下。
public class FwTest {
public static void main(String[] args) throws IOException {
//创建字符输出流对象
FileWriter fw = new FileWriter("path08\mytemp\read.txt",true);
FileReader fr = new FileReader("D:\mytemp\read.txt");
//循环读写文件
int len;
char[] ch = new char[1024];
while ((len = fr.read(ch))!=-1){
fw.write(ch,0,len);
}
fw.flush();
//释放资源
fw.close();
fr.close();
}
}
四、缓冲流
缓冲流也叫高效流,是一个增强流。
4.1字节缓冲流
构造方法:
public BufferedInputStream(InputStream in) | 创建一个新的缓冲输入流,参数是InputStream |
public BufferedOutputStream(OutputStream out) | 创建一个新的缓冲输出流,参数是OutputStream |
举例:
public class BufferTest {
public static void main(String[] args) throws IOException {
//创建一个字节缓冲输入流对象
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("path08\mytemp\read.txt"));
//创建一个字节缓冲输出流对象
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\mytemp\read.txt"));
}
}
4.2字符缓冲流
构造方法:
public BufferedReader(Reader in) | 创建一个缓冲输入流对象,参数是Reader |
public BufferedWriter(Writer out) | 创建一个缓冲输出流对象,参数是Writer |
举例:
public class BufferTest {
public static void main(String[] args) throws IOException {
//创建一个字符缓冲输入流对象
BufferedReader br = new BufferedReader(new FileReader("D:\mytemp\read.txt"));
//创建一个字符缓冲输出流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("path08\mytemp\read.txt"));
}
}
字符缓冲流特有方法 :
BufferedReader: readLine(): 读取一行数据。读到最后返回空值。
BufferedWriter: newLine():换行。
总结:
缓冲流的作用,本人的理解就是高效,他的读写速度比基本流要快。至于验证,就交给各位观众老爷了。这里提供一个验证思路,先使用基础流读写一个文件,在读之前我们使用System.currentTimeMillis()方法,再写完文件之后,我们再次使用此方法获取时间,然后两者相减,我们就能得到其中的运行时间了。同理,我们使用缓冲流再次读取文件,比较时间。我们就可以看出两者时间的差距了。