目标:
input,output,在java中主要操作数据的输入输出,数据的流动,可以通过学习输入输出的方法把一段数据从内存里放到硬盘上永久的存起来,也可以从硬盘上读取一个文件加载到内存。
1.能够通过File类对文件熟练操作(熟练)
2.理解相对路径和绝对路径的区别(了解)
3.掌握常见的字节输入输出和字符输入输出(熟练)
4.了解序列化和反序列化(熟悉)
File类(文件类):
是java中的文件/文件夹的抽象表示形式,一个File类的对象,在java中就表示一个文件或文件夹。
File类常用的构造方法:
1.File(String pathName)
参数1:文件的路径。例如:c://x.txt
如果c盘下没有这个文件也可以创建对象,但是创建之后是操作不了的,因为没有这个文件一操作就会报错。
2.File(String pathName, String fileName)
参数1:文件夹的路径。
参数2:文件的名称
例如:描述c盘中的a文件夹的x.txt
new File("c://a", "x.txt")
3.File(File paraent, String fileName)
参数1:父文件夹的File对象
参数2:文件的名称
例如:描述c盘中的a文件夹的x.txt
new File(new File(""), "x.txt")
File类常用的方法:
File file = new File("E:\\kaikeba\\IO\\苹果.txt");
file.delete();
// File file = new File("E:\\kaikeba\\IO\\a");
//只有a文件夹存在时才会创建b文件夹,如果没有a文件夹则不会创建b
File file = new File("E:\\kaikeba\\IO\\a\\b");
file.mkdir();
//创建a文件夹再创建b文件夹
File file = new File("E:\\kaikeba\\IO\\a\\b");
file.mkdirs();
//在a文件夹中创建b.txt文件
File file1 = new File("E:\\kaikeba\\IO\\a\\b.txt");
File file2 = new File("E:\\kaikeba\\IO\\a");
System.out.println(file1.createNewFile());//false b.txt文件已经存在
System.out.println(file1.exists());//true 判断b.txt文件是否存在
System.out.println(file2.exists());//true 判断a文件夹是否存在
file.exists();
//在a文件夹下创建abc3个文件
File file1 = new File("E:\\kaikeba\\IO\\a\\a.txt");
file1.createNewFile();
File file2 = new File("E:\\kaikeba\\IO\\a\\b.txt");
file2.createNewFile();
File file3 = new File("E:\\kaikeba\\IO\\a\\c.txt");
file3.createNewFile();
//创建目标文件夹
File dir1 = new File("E:\\kaikeba\\IO\\移动目标文件夹");
if (!dir1.exists()) {
dir1.mkdirs();
}
//原文件夹
File dir2 = new File("E:\\kaikeba\\IO\\a");
//需要移动的文件地址
File file6 = new File(dir2, "a.txt");
file6.renameTo(new File(dir1, "aa.txt"));
/*File file=new File(dir1,"aa.txt");
file6.renameTo(file);*/
File file7 = new File(dir2, "b.txt");
file7.renameTo(new File(dir1, "bb.txt"));
File file8 = new File(dir2, "c.txt");
file8.renameTo(new File(dir1, "cc.txt"));
file.renameTo();
File类获取文件信息的方法:
String getAbsolutePath();获取文件的绝对路径。
String getName();获取文件的名称,名称带有后缀名。
String getPath();获取文件的路径。
long length();获取文件的字节数。
long lastModified();获取文件最后一次修改的时间。
boolean isFile();获取file对象是否为文件。
boolean isDirctory();获取file对象是否为文件夹。
boolean isHidden();获取此文件是否为隐藏文件。
String getParent();通过一个file对象获取其父文件夹的路径。
File getParentFile();通过一个file对象获取其父文件夹的file对象。
String[] list();只有file对象为文件夹时才可用,可以得到文件夹里所有的路径。
File[] listFiles();只有file对象为文件夹时才可用,可以得到文件夹里所有的对象。
综合案例:
static int count = 0;
public static void main(String[] args) {
File f = new File("E:\\");
list(f);
System.out.println("共发现" + count + "个.java文件");
}
/**
* 此方法用于找出文件夹中所有java文件包含子目录
*
* @param dir
*/
public static void list(File dir) {
//如果传进来的文件夹不可以访问则结束整个方法
//如果传入的文件夹可以访问则往下执行
if (dir == null)
return;
//获取文件夹里所有file对象得到一个files数组
File[] files = dir.listFiles();
//如果得到的files数组不等于空则循环遍历整个files数组
if (files != null)
for (int i = 0; i < files.length; i++) {
//判断数组里的每一个file对象是否是文件
if (files[i].isFile()) {
System.out.println("正在扫描文件" + files[i].getAbsolutePath());
//得到文件的名称带有后缀名
String name = files[i].getName();
//如果文件的名称是以.java结尾的
if (name.endsWith(".java") || name.endsWith(".JAVA")) {
count++;
//打印这个文件的绝对路径
System.out.println("发现" + count + "个.java文件" + files[i].getAbsolutePath());
}
} else {
//如果是文件夹则递归调用list方法
list(files[i]);
}
}
FileFilter(文件过滤器):
FileFilter接口用于获取文件时筛选文件。
public class JavaFilter implements FileFilter {
@Override
public boolean accept(File pathname) {
if (pathname.getName().endsWith(".txt")||pathname.getName().endsWith(".TXT")){
return true;
}
return false;
}
}
public class DirFilter implements FileFilter {
@Override
public boolean accept(File pathname) {
if (pathname.isDirectory()){
return true;
}
return false;
}
}
public static void list(File dir) {
if (dir == null)
return;
//过滤得到所有的.txt文件
JavaFilter javaFilter = new JavaFilter();
File[] files = dir.listFiles(javaFilter);
for (int i = 0; i < files.length; i++) {
count++;
System.out.println(files[i].getAbsolutePath());
}
//过滤得到所有的文件夹
DirFilter dirFilter = new DirFilter();
File[] dirs = dir.listFiles(dirFilter);
for (int i = 0; i < dirs.length; i++) {
list(dirs[i]);
}
IO流:
IO流的概念:
1. input 输入
2. output 输出
输入与输出:
在我们程序中是一种相对的概念 .
例如:
我们的程序, 从硬盘中读取一个文件 !
这种操作 相对于我们的程序而言, 是在进行输入操作 .
这种操作 相对于我们的硬盘而言, 是在进行输出操作 .
例如:
我们的程序, 在硬盘中创建一个文件 !
这种操作 相对于我们的程序而言, 是在进行输出操作 .
这种操作 相对与我们的硬盘而言, 是在进行输入操作 .
Java中流的分类:
从操作上来说, 分为两种流:
1. 输入流
2. 输出流
但是通常情况, 我们指的流的分类是:
1. 字节byte流
相对于我们的内存(代码)往外走是出,往里走是入
- 输出流顶级父 : OutputStream 从代码里往其他文件里传基于我们讲是输出
- 输入流顶级父 : InputStream 从其他地方将数据传入软件里,基于我们讲是输入
2. 字符char流,操作文字的,字符流里边就是字节流
- 输出流顶级父 : Writer
- 输入流顶级父 : Reader
整个Java的io体系, 使用了大量的装饰者设计模式.
字符的组成,依赖编码表:UTF-8,GBK
字节byte流:
字节输出流 OutputStream抽象类:
有很多子类,操作文件,内存,网络的输出
常用方法:
- void write(int b);
向输出流指向的位置 , 输出一个字节.
- void write(byte[] bytes); *
向输出流指向的位置 , 输出一个字节数组 .
- void write(byte[] bytes,int offset,int len); ***
向输出流指向的位置 , 输出一个字节数组的一部分 (从offset开始, 输出len个字节)
操作流会占用硬件资源,当操作完数据关掉链接
- void close() ***
关闭流, 释放占用的硬件资源.
FileOutputStream类 文件字节输出流:
FileOutputStream 是 OuputStream 的实现类 , 是用于将字节 输出到文件中的 类.
文件输出流 输出时, 指向的文件可以不存在, 会创建文件并输出 .
构造方法:
如果创建的文件里边有内容,这个构造方法会把文件里的内容清空重新写入
- FileOutputStream(String filePath); ***
通过文件的绝对路径 , 创建一个指向文件的输出流.
- FileOutputStream(String filePath,boolean append); ***
参数1. filePath: 创建的流 , 指向的文件路径
参数2. append : 设置流是否为追加模式 .
(当值为false时, 会将之前的数据清空)
(当值为true时, 会接着之前的文件 继续存储)
- FileOutputStream(File file); ***
通过文件的file对象 , 创建一个指向文件的输出流.
- FileOutputStream(File file,boolean append); ***
参数1. file : 创建的流 , 指向的文件
参数2. append : 设置流是否为追加模式 .
(当值为false时, 会将之前的数据清空)
(当值为true时, 会接着之前的文件 继续存储)
文件字节输出流案例:
//创建一个文件的输出流
//文件输出流时, 指向的文件可以不存在, 会创建文件并输出
//FileOutputStream fos = new FileOutputStream("E:\\kaikeba\\IO\\a.txt");//不追加,文件原有内容删除
FileOutputStream fos = new FileOutputStream("E:\\kaikeba\\IO\\a.txt",true);//追加,文件原有内容不删除
//fos.write(65);//A//字节输出流//向文件中输出1个字节
byte[] bytes = {65, 66, 67, 68, 69, 70};
//fos.write(bytes);//ABCDEF//输出一个字节数组
fos.write(bytes,1,4);//BCDE//输出一个字节数组的一部分 (从offset开始, 输出len个字节)
fos.close();
System.out.println("输入完毕");
字节输入流InputStream抽象类:
常用方法:
- int read()
依次读取字节
一次读取一个字节,(这个字节 使用0-255的int值来表示) 并返回 , 如果读取到流的尾部则返回-1
- int read(byte[] bytes); ***
一次读取一个字节数组 , 并将读取的内容存储到bytes中 , 返回的是读取的字节个数 , 当读取到流尾部时返回-1
- int read(byte[] bytes,int offIndex,int length)
bytes: 读取的字节数组, 存储的位置
offIndex: 读取的一组字节, 存储在bytes中的起始位置
length: 读取的一组字节的长度
这个方法读取完毕后, 新的数据存储在 bytes数组的 offIndex下标 到 offIndex+length下标
- void close();
关闭流, 释放资源.
FileInputStream 文件输入流:
构造方法:
- FileInputStream(String filePath);
根据一个文件的路径, 创建一个指向此文件的输入流
- FileInputStream(File file);
根据一个file对象, 创建一个指向file表示文件的输入流.
文件字节输入流案例:
FileInputStream fis = new FileInputStream("E:\\kaikeba\\IO\\a.txt");
//int read = fis.read();//一次读取一个字节
//System.out.println((char) read);
byte[] bytes = new byte[201];//一次读取一个字节数组,数组长度自己定义
int len = fis.read(bytes);//一次读取一个字节数组,并将读取的内容存储到bytes中,返回的是读取的字节个数
System.out.println("读取字节数量为" + len);//201
System.out.println("读取结果:" + new String(bytes));//String类可以传入一个字节数组
//刚上来定义数组可以存放201个字节,第一次读取已经存满了。第二次读取只往数组里存放50个字节就读完了a.txt里的内容
//剩下的151个字节是第一次读取的结果没有被第二次读取的结果占用,都在数组里了
System.out.println("_______________________________________");
len = fis.read(bytes);//一次读取一个字节数组,并将读取的内容存储到bytes中,返回的是读取的字节个数
System.out.println("读取字节数量为" + len);//50
//给定数组的起止值就不会把第一次读取的旧数据打印出来
System.out.println("读取结果:" + new String(bytes,0,len));//String类可以传入一个字节数组
输入输出流综合案例:
文件的复制:
package com.kkb.IO2;
import java.io.*;
public class Demo3 {
public static void main(String[] args) throws Exception {
//源文件
File file = new File("E:\\kaikeba\\作业\\第二章.rar");
//创建输入流读取源文件
FileInputStream fileInputStream = new FileInputStream(file);
//目标文件
//创建文件输出流 输出时, 指向的文件可以不存在, 会创建文件并输出
FileOutputStream fileOutputStream = new FileOutputStream("E:\\kaikeba\\IO\\第二章.rar");
//准备一个字节数组存储读取的源文件数据
byte[] bytes = new byte[1024 * 1024];//1MB
//获取源文件的大小
long length = file.length();
//用于存储每次读取的字节数
int len = 0;
//用于存储累计读取的字节数
long count = 0;
//读到字节数组中
//判断是否读取完毕
while ((len = fileInputStream.read(bytes)) != -1) {
//如果读取3次,前2次读取的字节数占满了数组,第三次读取的字节数只占到数组20的长度,那么20后边的字节是第二次读取的内容
//写到目标文件里
//所以输出的时候就要从下边0开始到读取的数组字节长度结束
fileOutputStream.write(bytes, 0, len);
// count = count + len;
count += len;
//计算百分比 文件总大小/100算出文件的1%有多大,目前读取的大小/总文件的1%的大小算出有几个1%,算出目前的百分比
System.out.println("复制中,已完成" + count / (length / 100) + "%");
}
fileInputStream.close();
fileOutputStream.close();
System.out.println("一共读取:" + (count / 1024 / 1024) + "MB");
}
}
字符char流:
字符流是操作生活中的文字的。当操作字符流的时候,字符流的内部放了一个字节流,字符流通过编码表,将文字组装完成,交由字节流存储,文字组装是在字符流里的变量里进行组装,称为缓存。
字符输出流 Writer:
字符流进行输出操作时, 都是在操作缓冲管道. 当管道缓冲满时, 才会一次性 写出到文件中.
常用方法:
- void write(int ch);
一次写出一个字符
- void write(char[] chars);
一次写出一个字符数组
- void write(char[] chars,int start,int end);
一次写出一个字符数组的一部分. 从start开始 到end结束, 含start 不含end
- void write(String text); ****
一次写出一个字符串 到流指向的位置
- void flush() ***
刷新缓冲管道 : 强制将管道中的缓存数据 输出到流指向的位置, 并清空管道 !
- void close(); ***
释放资源, 字符输出流在关闭时 , 会自动执行flush操作.
FileWriter 文件字符输出流:
构造方法:
- FileWriter(String filePath); ***
通过文件的绝对路径 , 创建一个指向文件的输出流.
- FileWriter(String filePath,boolean append); ***
参数1. filePath: 创建的流 , 指向的文件路径
参数2. append : 设置流是否为追加模式 .
(当值为false时, 会将之前的数据清空)
(当值为true时, 会接着之前的文件 继续存储)
- FileWriter(File file); ***
通过文件的file对象 , 创建一个指向文件的输出流.
- FileWriter(File file,boolean append); ***
参数1. file : 创建的流 , 指向的文件
参数2. append : 设置流是否为追加模式 .
(当值为false时, 会将之前的数据清空)
(当值为true时, 会接着之前的文件 继续存储)
字符输入流 Reader :
常用方法:
int read();
一次读取一个字符, 并按照int的方式返回! 当读取到流尾部时 返回-1
int read(char[] chars);
一次读取一个字符数组, 并将读取到的数据存储到chars中, 返回读取的字符个数, 当读取到流的尾部时返回-1;
int read(char[] chars,int offset ,int length);
一次读取一个字符数组的一部分 , 读取的数据存储在chars中的 offset到length下标中 .
返回读取的字符个数, 当读取到流的尾部时返回-1
void close();
关闭流 ,释放资源
FileReader 文件字符输入流 :
构造方法:
- FileReader(String filePath);
根据一个文件的路径, 创建一个指向此文件的输入流
- FileReader(File file);
根据一个file对象, 创建一个指向file表示文件的输入流.
文件字符输入流案例:
package com.kkb.IO3;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
public class Demo2 {
public static void main(String[] args) throws Exception {
//目标文件
File file = new File("E:\\kaikeba\\IO\\a.txt");
//创建字符输入流
FileReader fileReader = new FileReader(file);
//准备一个字符数组
char[] chars = new char[10];
//返回的是一次读取的字符长度
int len = fileReader.read(chars);
System.out.println("本次读取字符数量:" + len);
System.out.println(new String(chars,0 ,len));
fileReader.close();
}
}
标准trycatch格式:
package com.kkb.IO3;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class Demo2 {
public static void main(String[] args) {
//目标文件
File file = new File("E:\\kaikeba\\IO\\a.txt");
//创建字符输入流
FileReader fileReader = null;
try {
fileReader = new FileReader(file);
//准备一个字符数组
char[] chars = new char[10];
//返回的是一次读取的字符长度
int len = fileReader.read(chars);
System.out.println("本次读取字符数量:" + len);
System.out.println(new String(chars, 0, len));
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileReader != null) {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}