1. File类
1.1 File类简介
File 类 就是当前系统中 文件或者文件夹的抽象表示。通俗的讲 就是 使用File对象 才操作我们电脑系统中的文件或者文件夹。学习File类 其实就是学习 如果通过file对象 对系统中的文件/文件夹进行增删改查。
1.2 创建File对象
1 前期准备
在电脑的非系统盘 创建一个 test文件夹 今天所有的操作都在这个文件夹中
2 创建
public void test() {
/* path 路径
Creates a new <code>File</code> instance by converting the given
pathname string into an abstract pathname. If the given string is
the empty string, then the result is the empty abstract pathname
File(String) 参数为String类型的目标文件路径名
*/
File file = new File("D:\\aaa\\123.txt");
/* 路径分割符
* D:\haha\hehe\123.mp4 称之为路径 其中 \ 就是路径分割符 代表的是 下级目录
* 在windows系统中 路径分割符为 \ 在 Linux 和 Mac 中 路径分割符是 /
* 我们写的java代码 需要跨平台 多环境运行 开发环境:windows 生成环境:Linux
* 此时就会出现一个问题 如果我们的路径分隔符 写成 \ 在 windows中好使 到了 Linux就不识别
* 所以我们可以使用以下两种方式解决:
*
* */
/* 方式1 : windows不仅支持 \ 还支持/ */
File file1 = new File("D:/aaa/123.txt");
/* 方式2: 使用动态识别的常量 */
// ;
System.out.println(File.pathSeparator);
// \
System.out.println(File.separator);
File file2 = new File("D:" + File.separator + "aaa" + File.separator + "123.txt");
}
1.3 增加操作
1 创建新的文件 2 创建新的文件夹
public class Test1 {
public static void main(String[] args) throws IOException {
File file = new File("E:/aaa666/a.txt");//创建文件
file.createNewFile();
File file1 = new File("E:/aaa666/aaa");//使根据你调用得方法不同 而创建不同得类型
file1.createNewFile();
File file2 = new File("E:/aaa666/b");//创建目录
file2.mkdir();
File file3 = new File("E:/aaa666/c/cc/ccc");//创建多层目录
file3.mkdirs();
}
}
1.4 删除操作
public class Test {
public static void main(String[] args) throws InterruptedException {
File file = new File("E:/aaa666/a.txt");//删除文件
file.delete();
File file1 = new File("E:/aaa666/b");//当程序退出后 删除
file.deleteOnExit();
Thread.sleep(2000);//让程序休眠2秒
File file2 = new File("E:/aaa666/j");//删除空目录
file2.delete();
}
}
注意:删除目录,必须是空目录的情况下才能使用delete方法进行删除。
1.5 修改操作
public static void main(String[] args) throws IOException {
File file=new File("D:/AAA/c.txt");
file.createNewFile();
file.setReadable(false);//设置该文件得权限为不能读
file.setWritable(false);//设置该文件不能写
file.setReadOnly();//设置只读得权限
file.renameTo(new File("D:/AAA/d.txt"));//重命名
}
1.6 查询操作
public class Test1 {
public static void main(String[] args) {
File file = new File("E:/aaa666/a.txt");
String name = file.getName();//得到文件得名称
System.out.println(name);
String parent = file.getParent();//得到父级路径得名称
System.out.println(parent);
String path = file.getPath();//得到文件得路径名称
System.out.println(path);
boolean directory = file.isDirectory(); //判断该文件对象是否为目录类型
System.out.println(directory);
boolean file1 = file.isFile();//判断该文件对象是否为文件类型
System.out.println(file1);
File file2 = new File("E:/aaa666");
String[] list = file2.list();//列出AAA目录下所有子文件得名称
System.out.println(Arrays.toString(list));//列出AAA目录下所有文件对象
File[] files = file2.listFiles();
//遍历输出
for (File a:files){
System.out.println(a.toString());
}
}
}
下面讲一个经典的面试题:通过递归的方法,输出指定目录下的所有文件。话不多说我们直接上代码:
public class Test1 {
public static void main(String[] args) {
showAllFiles("E:/aaa666");
}
public static void showAllFiles(String path){
File file = new File(path);
if (!file.exists() || !file.isDirectory()){
return;
}
File[] files = file.listFiles();
for (File a:files){
if (a.isDirectory()) {
showAllFiles(a.getPath());
}else {
System.out.println(a.getPath());
}
}
}
}
2. IO流
2.1 IO流概述
IO都是全大写 说明肯定是两个单词的首字母
I inputstream 输入流 O outputstream 输出流
IO 称之为 java的输入输出流
其实学习IO 就是学习 如何通过java代码 对文件内容 进行 读(输入流) 写(输出流)
所以有一话: 读进来 写出去。
Java流的分类
按流向分:
输入流: 程序可以从中读取数据的流。
输出流: 程序能向其中写入数据的流。
按数据传输单位分:
字节流: 以字节为单位传输数据的流
字符流: 以字符为单位传输数据的流
按功能分:
节点流: 用于直接操作目标设备的流 ---- 四大基流
过滤流: 是对一个已存在流的链接和封装,通过对数据进行处理为程序提供功能强大、灵活的读写功能。 ---- 包装流
四大基流: 字节输入流 字节输出流 字符输入流 字符输出流
这里面我们主要学习:FileWriter(文件输出字符流)、FileReader(文件输入字符流)、ObjectOutputStream(对象输出字节流)、FileOutputStream(文件输出字节流)、BufferedOutputStream(缓冲输出字节流)、ObjectInputStream(对象输入字节流)、FileInputStream(文件输入字节流)、BufferedInputStream(缓冲输入字节流)。
2.2 Writer字符输出流
它是所有字符输出流的父类。---FileWriter类
public class Test1 {
public static void main(String[] args) throws IOException {
Writer writer = new FileWriter("E:/aaa666/a.txt");
String str = "今天代码真的多";
writer.write(str);
writer.flush();//刷新流
writer.close();//关闭流资源
//上面每次往文件中写内容时 就会把原来的内容覆盖了。如何追加内容:
//true:表示允许追加内容到文件中
Writer writer1 = new FileWriter("E:/aaa666/a.txt",true);
String str1 = "我也这么觉得";
writer1.write(str1);
writer1.flush();
writer1.close();
}
}
输出结果如下图所示:
2.3 Reader字符输入流
public class Test1 {
public static void main(String[] args) throws Exception {
Reader reader = new FileReader("E:/aaa666/a.txt");
char[] chars = new char[2];
int a = reader.read(chars);
String s = new String(chars,0,a);
System.out.println()
}
}
用这种方式,我们可以一次读取多个字符 并存入一个字符数组中。由此我们可以引出,用while循环来输出文件的所有字符内容:
public class Test1 {
public static void main(String[] args) throws Exception {
Reader reader = new FileReader("E:/aaa666/a.txt");
int count = 0;
char[] cs = new char[5];
while ((count = reader.read(cs)) != -1 ){
String str = new String(cs,0,count);
System.out.print(str);
}
}
}
2.4 字符流中完成文件的复制操作
要求:将我们的E:/aaa666/a.txt的内容复制到E:/AAA/f.txt。
@Test
public void Copy01() throws Exception{
//1.创建一个字符输入流
FileReader fr = new FileReader("E:/aaa666/a.txt");
//2.创建一个字符输出流
FileWriter fw = new FileWriter("E:/AAA/f.txt");
int c = 0;//读取到字符的个数
char[] chars = new char[10];//每次读取的内容放入该数
while ((c = fr.read(chars)) != -1){
fw.write(chars,0,c);
fw.flush();//刷新
}
fw.close();
fr.close();
}
注意:我们的文件目录都是事先存在的,如果文件目录不存在,那么解决方法也很简单,只需加一个判读条件,判断我们的fw是否为exists()或者是否为Directory(),如果不是,则fw.mkdir();即可。
我们的字符流复制的操作,并不能将一个视频文件或者图片文件进行复制,只能对文本进行操作。因为视频和图片格式的文件都属于二进制。那么,想要实现这个功能,就需要我们的字节流来实现了。下面为大家讲述一下字节流。
2.5 字节流
2.5.1 字节输出流——OutputStream
字节输出流可以对任意文件进行写操作,对文件进行输出操作。以字节为单位。 它是所有字节输出流的父类,例如FileOutputStream。接下来我们测试一下字节输出流。
@Test
public void OutputStream01() throws Exception{
OutputStream os = new FileOutputStream("E:/aaa666/zzz.txt");
String str = "abcdefg";
//把字符串转换为字节数组.
byte[] bytes = str.getBytes();
os.write(bytes);
os.flush();
os.close();
}
2.5.2 字节输入流——InputStream
字节输入流可以对任意文件进行读操作以字节为单位,它是所有字节输入流的父类,子类有FileInputStream。读取的方法有两种:
第一种:一次一次的读取:
@Test
public void IntputStream01() throws Exception{
InputStream is = new FileInputStream("E:/aaa666/a.txt");
byte[] bytes = new byte[3];//一次读取三个字节 并把读取的内容放入字节数组中 返回读取到字节的个数
int read = is.read(bytes);
System.out.println(bytes+" 读取个数:"+read);
read = is.read(bytes);
System.out.println(bytes+" 读取个数:"+read);
read = is.read(bytes);
System.out.println(bytes+" 读取个数:"+read);
}
第二种:如果文件内容非常大,使用循环来读取
@Test
public void for01() throws Exception{
InputStream is = new FileInputStream("E:/aaa666/a.txt");
byte[] bytes = new byte[5];
int c = 0;//读取到的个数
while ((c = is.read(bytes)) != -1){
//把byte数组转换为字符串
String str = new String(bytes,0,c);
System.out.println(str);
}
is.close();
}
2.5.3 字节流复制操作
要求:我们复制一张名为1.jpg的图片。在这里把图片给大家,省的大家再去找,当然你可以随便用任何一张图片。
代码如下:原理和字符流的复制相同,这里就不再进行过多累述
@Test
public void Copy01() throws Exception{
InputStream is = new FileInputStream("E:/aaa666/1.jpg");
OutputStream os = new FileOutputStream("E:/AAA/2.jpg");
byte[] bytes = new byte[5];
int c = 0;
while ((c=is.read(bytes)) != -1){
os.write(bytes,0,c);
}
is.close();
os.close();
}
2.6 缓存流
缓存流是在基础流[InputStream OutputStream Reader Writer]之上 添加了一个缓存池功能.
BufferInutStream BufferOutputStream BufferReader BufferWriter 提高IO的效率,降低IO的次数。
我们写的内容,通过缓存流的操作,让内容暂时的放入了缓存池中,并没有直接放入文件中,所以在我们刷新缓存池之前,我们的文件并没有写入内容。我们可以直接通过close方法来实现缓存池的刷新操作。因为close是先刷新后关闭。
@Test
public void Buffer01() throws Exception{
OutputStream os = new FileOutputStream("E:/aaa666/ttt.txt");
BufferedOutputStream bos = new BufferedOutputStream(os);
String str = "今天是阴天";
byte[] bytes = str.getBytes();
bos.write(bytes);
bos.close();
}
@Test
public void Buffer02() throws Exception{
InputStream is = new FileInputStream("E:/aaa666/a.txt");
BufferedInputStream bos = new BufferedInputStream(is);
byte[] bytes =new byte[10];
int c = 0;
while ((c=bos.read(bytes)) != -1){
String str = new String(bytes,0,c);
System.out.println(str);
}
bos.close();
}
2.7 对象流——对Java对象进行IO操作
为什么我们需要用到对象流呢? 我们现在操作IO流的时候 都是将字符串读写操作 可不可以将java对象在文件中进行读写呢?
当然是可以的 例如写入一个 Student st=new Student();对象
将java对象进行读写操作 意义在于持久化信息 例如: 游戏存档。
这里还有一个概念,就是序列化和反序列化。通俗的讲,序列化相当于存档,就是要我们的对象类型的数据,必须实现Serializable接口,才能进行写入操作。反序列化相当于读档,就是让我们文件里的对象内容输出到idea中方便查看。(直接点开文件查看对象内容是乱码)
首先我们创建一个Student类,必须有Serializable接口:
public class Student implements Serializable {
private String name;
private String level;
private int age;
private String jineng;
public Student(String name, String level, int age, String jineng) {
this.name = name;
this.level = level;
this.age = age;
this.jineng = jineng;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLevel() {
return level;
}
public void setLevel(String level) {
this.level = level;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getJineng() {
return jineng;
}
public void setJineng(String jineng) {
this.jineng = jineng;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", level='" + level + '\'' +
", age=" + age +
", jineng='" + jineng + '\'' +
'}';
}
}
序列化:
@Test
public void ObjectOutputStream01() throws Exception{
OutputStream os = new FileOutputStream("E:/aaa666/a111.txt");
ObjectOutputStream oos = new ObjectOutputStream(os);
Student s = new Student("张三","7级",20,"乌鸦坐飞机");
oos.writeObject(s);
oos.close();
}
我们直接点开文档查看时看不懂的
想要查看对象内容,就需要反序列化:
@Test
public void ObjectInputStream01() throws Exception{
InputStream is = new FileInputStream("E:/aaa666/a111.txt");
ObjectInputStream ois = new ObjectInputStream(is);
Object o = ois.readObject();
System.out.println(o);
ois.close();
}
运行以后输出的效果如下图所示: