File类
盘符上的文件—》封装为对象—》对象属于File类的对象–》有了这个对象,我们程序就可以直接操纵这个对象,通过这个对象获取文件的各种信息,还可以对文件进行创建 ,删除。
1.File对文件的操作
文件是否可读:f.canRead()
文件是否可写:f.canWrite()
文件的名字:f.getName()
上级目录: f.getParent()
是否是一个目录:f.isDirectory()
是否是一个文件:f.isFile()
是否隐藏:f.isHidden()
文件的大小:f.length()
是否存在:f.exists()
删除文件:f.delete()
创建文件:f.createNewFile()
绝对路径:f.getAbsolutePath() (完整的路径)
相对路径:f.getPath() (有一个参照物,相对这个参照物的路径)
2.File对目录的操作
包含对文件的操作
创建单层目录:f2.mkdir()
创建多层目录:f2.mkdirs()
删除目录:f2.delete() (只能删除一层并且只有空目录才能删除)
遍历出每个对象来遍历信息
File[] files = f.listFiles();
for(File file:files){
System.out.println(file.getName()+","+file.getAbsolutePath());
}
IO流
1.概念
I/O : Input/Output的缩写,用于处理设备之间的数据的传输
IO流的体系结构
后缀为:Reader和Writer为字符流,后缀为Stream为字节流
注意
文本文件:.txt ,java .c .cpp 等用字符流操作
非文本文件: .jpg .doc .ppt .mp3 .mp4 等用字节流操作
模板(运用处理流)
1.为文件创建一个对象
2.为目标文件创建一个对象
3.创建一个“流”将文件与源文件相连
4.创建一个“流”将源文件与目标文件相连
5.套一根管在输入字符流外面
6.套一根管在输出字符流外面
7.开始动作
8.关闭流(倒着关,若相包裹则只用关闭高级的流)
2.FileReader(字符流)
作用:读取文件中的内容
public static void main(String[] args) throws IOException {
//创建File对象>>>将文件中数据用对象代表
File f=new File("C:\\Users\\lenovo\\Desktop\\IO\\Test.txt");
//创建FileReader对象>>>利用FileReader这个"流"拼接到源文件上(用管子将文件和源文件连接)
FileReader fr=new FileReader(f);
//开始读取文件中的数据到源文件
char[] ch=new char[5];
int len=fr.read(ch);//一次读取五个:返回值是这个数组中 的有效长度
while(len!=-1)//如果到了文件的结尾处,那么读取的内容为-1
{
String s=new String(ch,0,len);
System.out.print(s);
len=fr.read(ch);
}
//关闭流(用完要关闭)
fr.close();
}
ch为缓冲数组可提高效率
3.FileWriter(字符流)
作用:写出数据
public static void main(String[] args) throws IOException {
File f=new File("C:\\Users\\lenovo\\Desktop\\IO\\Test.txt");
FileWriter fw=new FileWriter(f,true);//ture是在后面添加,false是覆盖
String s="kkkkkk";
char[] ch=s.toCharArray();
fw.write(ch);//要写的内容
fw.close();
}
4.用FileReader和FileWriter对文件复制
public static void main(String[] args) throws IOException {
File f1=new File("C:\\Users\\lenovo\\Desktop\\IO\\Test.txt");//要复制的文件
File f2=new File("C:\\Users\\lenovo\\Desktop\\IO\\demo.txt");//目标的文件
FileReader fr=new FileReader(f1);//输入的“管子”
FileWriter fw=new FileWriter(f2,true);//输出的“管子”
//转换到源文件
char[] ch=new char[5];//缓冲数组
int len=fr.read(ch);
while(len!=-1)
{
String s=new String(ch,0,len);//从0到len表示的是有效长度
fw.write(s);//写入f2
len=fr.read(ch);
}
//关闭流(倒着关闭)
fw.close();
fr.close();
}
4.FileInputStream(字节流)
作用:读取文件中的内容
用法与FileReader相同
public static void main(String[] args) throws IOException {
File f=new File("C:\\Users\\lenovo\\Desktop\\IO\\math.png");
FileInputStream fis=new FileInputStream(f);
byte[] by=new byte[1024*6];
int len=fis.read(by);
while(len!=-1)
{
for(int i=0;i<len;i++)
{
System.out.println(by[i]);
}
len=fis.read(by);
}
fis.close();
}
5.FileOutputStream(字节流)
作用:写出数据
用法与FileWriter相同
用FileInputStream和FileOutputStream复制非文本文件
public static void main(String[] args) throws IOException {
File f1=new File("C:\\Users\\lenovo\\Desktop\\IO\\math.png");
File f2=new File("C:\\Users\\lenovo\\Desktop\\IO\\math22.png");
FileInputStream fis=new FileInputStream(f1);
FileOutputStream fos=new FileOutputStream(f2);
byte[] byt=new byte[1024*8];//缓冲数组
int len=fis.read(byt);
while(len!=-1)
{
fos.write(byt,0,len);//输出有效长度
len=fis.read(byt);
}
fos.close();
fis.close();
}
6.缓冲字节流(处理流)BufferedInputStream ,BufferedOutputStream
一开始一个字节一个字节的通过流传输需要访问硬盘的次数太多于是我们引入了缓冲数组可以减少对硬盘的访问次数,但即使这样数据量大的时候对硬盘的访问次数依旧很多,于是我们引入新的流进一步提升效率。
效率的提升过程
方法(1)一个字节一个字节的传输->对硬盘访问n次
方法(2)引入缓冲数组(长度自定义)->对硬盘访问n/m次
方法(2)引入处理流->对硬盘访问1次
public static void main(String[] args) throws IOException {
File f1=new File("C:\\Users\\lenovo\\Desktop\\IO\\math.png");
File f2=new File("C:\\Users\\lenovo\\Desktop\\IO\\math11.png");
FileInputStream fis=new FileInputStream(f1);
FileOutputStream fos=new FileOutputStream(f2);
//5.功能加强,在FileInputStream外面套一个管
BufferedInputStream bis=new BufferedInputStream(fis);
//5.功能加强,在FileOutputStream外面套一个管
BufferedOutputStream bos=new BufferedOutputStream(fos);
//开始动作
byte[] byt=new byte[1024*6];
int len = bis.read(byt);
while(len!=-1)
{
bos.write(byt,0,len);
len = bis.read(byt);
}
//关闭流(如果处理流包裹字节流那么只需要关闭更高级的流(处理流))
bos.close();
bis.close();
}
7.缓冲字符流(处理流)BufferedReader ,BufferedWriter
除了(开始动作外)其余步骤与上述相同
//方式1:读取一个字符,输出一个字符
//方式2: 利用缓冲数组
//方式3:读取String
String str = br.readLine();//每次读取文本文件中一行,返回字符串
while(str!=null)
{
bw.write(str);
//在文本文件中应该再写出一个换行:
bw.newLine();//新起一行
str = br.readLine();
}
8.转换流:InputStreamReader,OutputStreamWriter(字符流)
作用:
InputStreamReader:将输入字节流转换为字符流
OutputStreamWriter:将输出字符流转换为字节流
用法:
InputStreamReader :与输入字节流的“管子”相连
OutputStreamWriter:与输出字符流的“管子“相连
//转换为字符流
InputStreamReader isr = new InputStreamReader(fis);
OutputStreamWriter osw=new OutputStreamWriter(fos);
9.数据流-DataInputStream,DataOutputStream
作用:用来操作基本数据类型和字符串的
DataInputStream:将文件中存储的基本数据类型和字符串 写入 内存的变量中
DataOutputStream: 将内存中的基本数据类型和字符串的变量 写出 文件中
DataOutputStream代码
先要用DataOutputStream向外写出变量
public static void main(String[] args) throws IOException {
DataOutputStream dos=new DataOutputStream(new FileOutputStream(new File("C:\\Users\\lenovo\\Desktop\\IO\\加密文件.txt")));
dos.writeBoolean(true);
dos.writeUTF("你好");
dos.writeDouble(29.3);
dos.writeInt(2134);
dos.close();
}
在 (加密文件.txt)中我们看到
发现这个内容我们看不懂,因为这是给程序看的
我们可以利用DataInputStram来解密
DataInputStram代码
public static void main(String[] args) throws IOException {
DataInputStream dis=new DataInputStream(new FileInputStream(new File("C:\\Users\\lenovo\\Desktop\\IO\\加密文件.txt")));
System.out.println(dis.readBoolean());
System.out.println(dis.readUTF());
System.out.println(dis.readDouble());
System.out.println(dis.readInt());
dis.close();
}
输出结果:
发现和我们DataOutputStream代码中的对应上了
注意:dis.readBoolean()和dos.writeBoolean(true)的顺序要一一对应
10.对象流:序列化和反序列化
作用:可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来
使用方式和数据流-DataInputStream没有区别,比数据流多一个oos.writeObject()方法
序列化和反序列化:
序列化:用ObjectOutputStream类把内存中的Java对象转换成平台无关的二进制数据,从而允许把这种二进制数据持久地保存在磁盘上,或通过网络将这种二进制数据传输到另一个网络节点(加密)
反序列化:用ObjectInputStream类 :当其它程序获取了这种二进制数据,就可以恢复成原来的Java对象(解密)
操作自定义类的对象
Person类必须implements Serializable接口!!!!!
1.错误示范,Person没有接口
自定义Person类
public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person(){
}
public Person(String name,int age){
this.name=name;
this.age=age;
}
Test测试类
public static void main(String[] args) throws IOException {
ObjectOutputStream dos=new ObjectOutputStream(new FileOutputStream(new File("C:\\Users\\lenovo\\Desktop\\IO\\加密2.txt")));
Person p=new Person("xiaownag",18);
dos.writeObject(p);
dos.close();
}
运行后我们发现异常
出现异常的原因:
你想要序列化的那个对象对应的类,必须要实现一个接口:
接口内部,什么都没有,这种接口叫 标识接口。
起到标识作用,只有实现这个接口的类的对象才能序列化,否则不可以。
解决办法:将Person 实现这个标识接口就可以
再运行
发现序列化成功,Person具备了序列化的能力。
反序列化
代码
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(new File("C:\\Users\\lenovo\\Desktop\\IO\\加密2.txt")));
Person p = (Person) (ois.readObject());
System.out.println(p);
}
运行结果:
反序列化成功,但是我们没有重写toString方法所以结果看不懂
重写toString后
输出结果为
在低版本中
重写toString方法需要在Person类中添加表示序列化版本标识符的静态常量: private static final long serialVersionUID;并给他赋值。
11.序列化细节:
1.被序列化的类的内部的所有属性,必须是可序列化的 (基本数据类型都是可序列化的)
2.static,transient修饰的属性 不可以被序列化