IO流
一.File类
想要input和output,用什么写到硬盘上呢?当然要先熟悉文件操作。
1.1 定义
java.io.File类:文件和文件目录路径的抽象表示形式,与平台无关
File 能新建、删除、重命名文件和目录,但 File 不能访问文件内容本身。
如果需要访问文件内容本身,则需要使用输入/输出流。
想要在Java程序中表示一个真实存在的文件或目录,那么必须有一个File对
象,但是Java程序中的一个File对象,可能没有一个真实存在的文件或目录。
File对象可以作为参数传递给流的构造器。
1.2 构造器
public File(String pathname):以pathname为路径创建File对象,可以是 绝对路径或者相对路径,如果pathname是相对路径,则默认的当前路径在系统属性user.dir中存储。
public File(String parent,String child)
public File(File parent,String child)
1.3 常用API
public String getAbsolutePath():获取绝对路径
public String getParent():获取上层文件目录路径。若无,返回null
public String[] list() :获取指定目录下的所有文件或者文件目录的名称数组
public File[] listFiles() :获取指定目录下的所有文件或者文件目录的File数组
public boolean isDirectory():判断是否是文件目录
public boolean isFile() :判断是否是文件
public boolean exists() :判断是否存在
public boolean createNewFile() :创建文件。若文件存在,则不创建,返回false
public boolean mkdir() :创建文件目录。如果此文件目录存在,就不创建了。如果此文件目录的上层目录不存在,也不创建。
public boolean mkdirs() :创建文件目录。如果上层文件目录不存在,一并创建
二.IO流
2.1 this is IO
I/O是Input/Output的缩写, I/O技术是非常实用的技术,用于处理设备之间的数据传输。如读/写文件,网络通讯等。
Java程序中,对于数据的输入/输出操作以 “流(stream)” ” 的方式进行。
java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过 标准的方法输入或输出数据。
2.2 IO流的两种基本分类
根据数据的流向分为:输入流和输出流。
输入流 :把数据从 其他设备 上读取到 内存 中的流。
输出流 :把数据从 内存 中写出到 其他设备 上的流。
格局数据的类型分为:字节流和字符流。
字节流 :以字节为单位,读写数据的流。
字符流 :以字符为单位,读写数据的流。
2.3 四个顶级父类
基本所有的流都得叫一声爸爸,记清楚了你就搞懂了基本的分类
输入输出,相较的是我们,即内存
2.4 字节流和字符流
一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,都一个一个的字节,那么传输时一样如此。所以,字节流可以传输任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底层传输的始终为二进制数据。
字节输出流
java.io.OutputStream 抽象类是表示字节输出流的所有类的超类,将指定的字节信息写出到目的地。它定义了字
节输出流的基本共性功能方法。
public void close() :关闭此输出流并释放与此流相关联的任何系统资源。
public void flush() :刷新此输出流并强制任何缓冲的输出字节被写出。
public void write(byte[] b) :将 b.length字节从指定的字节数组写入此输出流。
public void write(byte[] b, int off, int len) :从指定的字节数组写入 len字节,从偏移量 off开始输
出到此输出流。
public abstract void write(int b) :将指定的字节输出流
字节输入流
java.io.InputStream 抽象类是表示字节输入流的所有类的超类,可以读取字节信息到内存中。它定义了字节输入
流的基本共性功能方法。
public void close() :关闭此输入流并释放与此流相关联的任何系统资源。
public abstract int read() : 从输入流读取数据的下一个字节。
public int read(byte[] b) : 从输入流中读取一些字节数,并将它们存储到字节数组 b中 。
字符输入、输出流
操作类似,不过每次读写的单位从byte数组变成了char数组,聪明的你应该可以类比过来,不再赘述
tips:亲记得使用完后释放内存哦
2.5 节点流和处理流
前面的字符和字节流,都是最基础的流,一般工作中,我们使用性能更快的处理流。何为处理流?流上加流,即为处理流。
2.6 最常用的处理流:缓冲流
为了提高数据读写的速度,Java API提供了带缓冲功能的流类,在使用这些流类时,会创建一个内部缓冲区数组,缺省使用8192个字节(8Kb)的缓冲区。
缓冲流要“套接”在相应的节点流之上,根据数据操作单位可以把缓冲流分为:
BufferedInputStream 和 BufferedOutputStream
BufferedReader 和 BufferedWriter
看到这四个东西,有没有一丝丝的眼熟呢?^ ^
当使用BufferedInputStream读取字节文件时,BufferedInputStream会一次性从文件中读取8192个(8Kb),存在缓冲区中,直到缓冲区装满了,才重新从文件中读取下一个8192个字节数组。这就是他性能更高的小秘密。
2.7 处理流还有什么?
转换流:
实现将字符的输出流按指定字符集转换为字节的输出流。
需要和OutputStream“套接”。
构造器方法:
public OutputStreamWriter(OutputStream out)
public OutputSreamWriter(OutputStream out,String charsetName)
标准输入、输出流:
System.in和System.out分别代表了系统标准的输入和输出设备
默认输入设备是:键盘,输出设备是:显示器
System.in的类型是InputStream
System.out的类型是PrintStream,其是OutputStream的子类
三.案例实现
喜闻乐见,最爱的环节来了。
我们自定义一个需求。要求把指定文件夹内(包括所有子文件夹里的内容)内指定格式的文件复制到指定的地方。
你有思路了吗?
package advancedgrammer.iostream;
import java.io.*;
public class testcopy {
public static void main(String[] args) {
//test it here
}
public static void copyFile(String src,String dis) {
//使用缓冲流实现文件复制操作
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
File old_f = new File(src);
File new_f = new File(dis);
FileInputStream fis = new FileInputStream(old_f);
FileOutputStream fos = new FileOutputStream(new_f);
bis = new BufferedInputStream(fis);
bos = new BufferedOutputStream(fos);
byte[] buf = new byte[10];
int len;
while ((len = bis.read(buf)) != -1) {
bos.write(buf, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void findAndCopy(String from, String to, String required_suffix) {
//使用递归遍历判断是否为文件,如果是文件则判断后缀名,相同则执行复制操作
File target = new File(to);
if (!target.isDirectory()) {
System.out.println("请输入文件夹名!");
return;
}
File file = new File(from);
if (file.isDirectory()) {
File[] children = file.listFiles();
for (File child : children) {
String absolutePath = child.getAbsolutePath();
findAndCopy(absolutePath, to, required_suffix);
}
} else {
if (!target.exists()) {
target.mkdirs();
}
String[] split = from.split("\\\\");
String filename = split[split.length - 1];
String[] period_split = filename.split("\\.");
String suffix = period_split[period_split.length - 1];
if (suffix.equals(suffix)){
String toFullPath = to + filename;
copyFile(from, toFullPath);
}
}
}
}