// 3中构造函数,File可以传入文件,也可以传入文件夹
File file=new File("E:\bb\qq.txt");
File file=new File("E:\bb","qq.txt");
File parentFile=new File("E:\bb");
File file=new File(parentFile,"qq.txt");
1.2 File类的功能方法
创建、删除、重命名功能
-
createNewFile():创建新的文件,返回true表示创建成功,如果文件存在,则创建失败;
如果路径不存在则报错 IOException:系统找不到指定的路径。 -
mkdir():创建一层文件夹,如果上一层文件夹不存在,则返回false,创建失败
-
mkdirs():创建多层文件夹
-
delete():如果关联的路径是一个文件,则直接删除,如果关联的路径是一个文件夹,如果文件夹为空,可以删除,不为空,则无法删除
-
renameTo(File dest):重命名功能,如果目标路径一致,则直接修改文件名,如果不一致,则将文件剪切到目标文件夹中,再修改文件名
判断功能
System.out.println("是否是一个路径(文件夹):"+file.isDirectory());
System.out.println("是否是一个文件:"+file.isFile());
System.out.println("文件或路径是否存在:"+file.exists());
System.out.println("文件是否可读:"+file.canRead());
System.out.println("文件是否可写:"+file.canWrite());
System.out.println("文件是否隐藏:"+file.isHidden());
基本获取功能
System.out.println("获取绝对路径:"+file.getAbsolutePath());
System.out.println("获取本身路径:"+file.getPath());
System.out.println("获取文件名:"+file.getName());
System.out.println("获取文件长度:"+file.length());
System.out.println("获取最后修改时间:"+file.lastModified());
file.list(); 获取当前路径下的所有文件的名字放到数组中
file.listFiles(); 把当前路径下的所有文件封装成一个file对象
file.list()过滤功能
//过滤,自定义过滤器MyFilter
String[] names=file.list(new MyFilter());
for(String s:names) {
System.out.println(s);
}
// 自定义过滤器
public class MyFilter implements FilenameFilter {
//自动调用accept方法,路径里面有多少个文件,那么就调用多少次,并且把每一个文件或文件夹的父路径和名字传入参数
@Override
public boolean accept(File dir, String name) {
//dir : 当前文件的父路径,name:当前文件的名字
File f=new File(dir,name);
if(name.endsWith(".txt")&&f.isFile()) {
return true;
}
return false;
}
}
二、IO流
Java对外部数据的操作都是通过流的方式
- InoutStream(抽象类) :所有字节输入流的父类
- OutputStream(抽象类) :所有字节输出流的父类
文件字节输出流
输出流的构造方法:如果文件不存在,则会自动创建,如果路径不存在,则报错
- FileOutputStream(File file)
- FileOutputStream(String name)
File file=new File("F:\自学\Java\test\bb\qq.txt");
FileOutputStream fos=null;
try {
//FileOutputStream()后面可以添加第二个参数,为布尔值(boolean append),为true时表示追加内容
fos=new FileOutputStream(file);
//输出流输出数据
//一次写一个字节
fos.write('a');
//一次写一个字节数组
fos.write("河南科技大学".getBytes());
//一次写一个字节数组部分
fos.write("河南科技大学".getBytes(), 0, 6);
// 当需要在添加换行符时,因为不同系统换行符不一样,可使用以下方法:
fos.write("张三".getBytes());
String str=System.getProperty("line.separator"); // 动态获取系统换行符
fos.write(str.getBytes());
fos.write("李四".getBytes());
//close()方法必须得执行,关闭物理资源,让当前对象变成一个纯内存资源
fos.close();
} catch {}
2.2 FileInputStream
文件字节输入流
// FileInputStream使用:read()一次读取一个字节,连续使用read()会往后读取,而不是每次从头读取
FileInputStream fis=new FileInputStream("aa.txt");
int ch1=fis.read(); //第一次读取
System.out.println((char)ch1);
int ch2=fis.read(); //第二次读取
System.out.println((char)ch2);
int ch3=fis.read(); //第三次读取
System.out.println((char)ch3);
//读到末尾返回-1,字符表示为'?'
fis.close();
// 使用while循环读取所有内容
int ch=0;
while((ch=fis.read())!=-1) {
System.out.println((char)ch);
}
注:对于文件字节输入输出流,向write()/read()传入字节数组参数(byte[] bs),可以一次性输出/输入传入字节数组的内容,如下:
FileInputStream fis=new FileInputStream("F:\自学\Java\test\bb\Demo_1.java");
byte[] bs=new byte[1000];
//一次读取一个字节数组,返回值是读取到的字节数
int total=fis.read(bs);
System.out.println("读取字节数:"+total);
System.out.println(new String(bs,0,total));
2.3 字节缓冲流–BufferedInputStream/BufferedOutputStream
- 缓冲字节流(高效)和文件字节流(低效)的区别:
- 相同:关闭流以后不能再进行任何读写操作
- 区别:当两者都不执行close方法时会产生差别,文件字节流会创建文件,并且把数据写进去;缓冲字节流会创建文件,但不会写入数据
- 原因:如果没有进行关闭流的操作或者刷新缓冲区操作,那么该流不会写出去,减少了和本地文件的IO操作,提高效率
-
缓冲流在关闭流的时候会默认刷新一次缓冲区
-
如果缓冲区满了,也会默认刷新一次,缓冲区大小默认8192字节,即8kb
//可以传入第二个参数,指定缓冲区大小,单位是字节
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("C:\a.txt"));
bos.write("陈独秀".getBytes());
//刷新缓冲区,把缓冲区里的数据写出去
bos.flush();
//bos.close();
2.4 转换流
字节流处理中文不是很方便,所以推出了 字符流,是由转换流转换而来
转换公式: 转换流=字节流+编码表
Reader 所有字符输入流的超类
Writer 所有字符输出流的超类
转换流:是字符流和字节流之间的桥梁,可以将字节流转换为字符流,并且能为字节流指定字符集,可以处理一个个的字符。
InputStreamReader
OutputStreamWriter
OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("aa.txt"));
osw.write("abcd");
osw.close();
简化写法:
FileReader
FileWriter
**注:**字符流只能用来操作文本(不能写图片 音频 视频)
2.5 字符缓冲流BufferedWriter 字符缓冲输出流
BufferedReader 字符缓冲输入流
- 字符缓冲输入流:多了一个 readLine方法,每次读取一行
- 字符缓冲输出流:多了一个 newline方法,可以动态输出换行符
BufferedReader br=new BufferedReader(new FileReader("bb.txt"));
//字符缓冲输入流的特有的方法
String str=null;
while((str=br.readLine())!=null) {
System.out.println(str);
}
br.close();
2.6 数据操作流
DataInputStream
DataOutputStream
可以向文件中输入/输出基本数据类型
//DataOutputStream
DataOutputStream dos=new DataOutputStream(new FileOutputStream("aa.txt"));
dos.writeInt(25);
dos.writeBoolean(true);
dos.close();
//DataInputStream
DataInputStream dis=new DataInputStream(new FileInputStream("aa.txt"));
//读取相应的内容时,需按照文件中内容的顺序读取
int readInt=dis.readInt();
boolean readBool=dis.readBoolean();
System.out.println(readInt);
System.out.println(readBool);
dis.close();
2.7 打印流
PringStream 字节打印流
PrintWriter 字符打印流
两者区别:
-
一个操作字节,一个操作字符
-
字节打印流如果没有刷新缓冲区,没有close也会直接写出去,字符打印流则不会
-
字符打印流的构造方法的自动刷新布尔值,表示如果调用了println或者printf或者format方法,才会自动刷新
字符打印流要想刷新缓冲区:
-
构造器传入true,输出时,调用println()方法
-
调用flush方法
-
调用close方法
字节打印流要想刷新缓冲区:
-
无论构造器的布尔值是否传入,是否使用,都会默认自动刷新
**注:**PrintStream 是用来装饰其它输出流。它能为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。与其他输出流不同,PrintStream 永远不会抛出 IOException;它产生的IOException会被自身的函数所捕获并设置错误标记, 用户可以通过 checkError() 返回错误标记,从而查看PrintStream内部是否产生了IOException。
2.8 内存操作流一般用于处理临时信息,因为临时信息不需要保存,使用后就可以删除
ByteArrayInputStream
ByteArrayOutputStream
CharArrayReader
CharArrayWriter
StringReader
StringWriter
对应方法为:write()、read()
2.9 标椎输入输出System.in 系统标准输入
-
读取控制台的数据
System.out 系统标准输出
-
输出到控制台
修改标准输入输出
- System.setOut 修改System.out的默认输出方向
- System.steIn 修改System.in的默认输入方向
// System.in 使用
// 1.
InputStream input=System.in;
byte[] bs=new byte[100];
System.out.print("请输入:");
int total=input.read(bs);
System.out.println(new String(bs,0,total));
//2.使用BufferedReader
InputStream input=System.in;
BufferedReader br=new BufferedReader(new InputStreamReader(input));
System.out.print("请输入:");
String str=br.readLine();
System.out.println(str);
// System.out使用
PrintStream ps=System.out;
ps.println("呵呵");
2.10 RandomAccessFile 随机访问流
-
随机访问流:可读可写,任意位置读写
-
BufferedReader 可以打标记,打书签
- mark(int ) 打标记,以后可以回来从这再重读
-
参数:
-
官方解释:在当前标签之后多少个字符以后,标签失效
-
实际效果:标签之后读取到的容量超过了缓冲区最大容量,则标签失效
-
- skip reset
// 使用1
BufferedReader br=new BufferedReader(new FileReader("aa.txt"),10);
String str=null;
int i=0;
while((str=br.readLine())!=null) {
if(i==10) {
//打标记
br.mark(20);
}
if(i==20) {
//回到标记处重新读
br.reset();
}
System.out.println(str);
i++;
}
br.close();
//使用2
RandomAccessFile raf=new RandomAccessFile("qq.txt", "r");
//raf.skipBytes(3); //跳过几个字节
//String str=raf.readLine();
//System.out.println(str);
raf.skipBytes(5);
int ch1=raf.read();
System.out.println((char)ch1);
//设置指针为任意位置
raf.seek(1);
int ch2=raf.read();
System.out.println((char)ch2);
raf.close();
// 使用3
RandomAccessFile raf=new RandomAccessFile("qq.txt", "rw");
raf.skipBytes(4);
//不会清空之前的数据,会替换等长的数据
raf.write("软件学院".getBytes());
raf.close();
2.11 对象序列化流
- 将对象以文本的形式保存到文件 ---->对象序列化
- 将文本中保存过的对象读取出来放到程序里面 ---->对象反序列化
ObjectInputStream
ObjectOutputStream
Serializable 序列化接口,标记接口,如果一个对象要想被序列化,那么该对象的类必须要实现序列化接口
- private修饰属性无法做到让对象的某一个属性不被序列化出去
- static修饰的属性无法被序列化
- transient修饰的属性也无法被序列化,transient的作用:就是阻止序列化,没有其他作用
对象序列化流 是指序列化跟对象有关的数据,也就是只能序列化对象堆内存的数据
对象序列化后,如果类发生了改变,那么在改变后反序列化会报错
-
原因:
将对象序列化出去的时候会有一个ID,在反序列化回来之前,类发生了改动,
那么这个ID发生了改变,但是本地文件记录的ID 还是原来的ID,所以两个ID不一致,
那么反序列化回来的这个就找不到原来的类,就会报错
-
解决:在序列化之前,根据类名下出现的黄色警告线,自动生成serialVersionUID
-
序列化和反序列化属性变动问题:
对象保存到文件后,如果属性减少了,那么取出来时,只能取类中现有的属性的值,不存在的属性,无法取出
如果属性增加了,那么取回来时,增加的属性相当于没有赋值,直接取默认值即可
//对象序列化
Person p1=new Person("(●—●", 12);
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("per.txt"));
oos.writeObject(p1);
oos.close();
//对象反序列化
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("per.txt"));
//多态性
Object obj=ois.readObject();
System.out.println(obj);
ois.close();



