File文件或目录的抽象
对文件进行操作,首先建文件对象
且文件对象也可以用做字节流的参数
File file=new File(“D:\”);
文件和目录可以通过File封装成对象
对于File,其封装的并不是一个真正的文件,只是文件的路径,可存在可不存在,之后通过具体的操作把这个路径转化为具体的存在
构造:
File(String pathname) 通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。
File(String parent, String child) 从父路径名字符串和子路径名字符串创建新的 File实例。
File(File parent, String child) 从父抽象路径名和子路径名字符串创建新的 File实例。
注意:父路径和子路径就是把一个完整的路径进行了拆分(以目录进行拆分),最终会进行拼接
转义符:
\ 更改当前内容的含义,只能更改转义符后第一个字母
例如:n默认为字母 \n表示换行
例如:""默认表示字符串 \":"表示为字符
例如:\默认表示转义符 \\:前一个转义符把后一个转义符含义为修改为字符
file对象的方法
//当抽象路径所指内容不存在时,创建一个空的文件
//当抽象路径所指内容存在时,不创建
file.createnewFile()
//当抽象路径所指内容不存在时,创建一个空的文件
//当抽象路径所指内容存在时,不创建
//public boolean mkdir()
file.mkdir()
mkdir只能创建单级目录不能创建多级目录
//public boolean mkdirs()
boolean mkdirs=file.mkdirs();
//创建由此抽象路径命名的目录,包括任何必须但不存在父目录
mkdirs可以创建多级目录,也可以创建单级目录
抽象路径是内容,由具体的操作来决定
路径不能通过名称来判断是目录还是文件
IO字节流
IO:输入Input 输出Output
流:抽象的概念,表示数据传输
IO流:设备与设备之间的数据传输
IO流的分类
流向分类:输入流和输出流
数据类型分类
字节流:字节输入输出流
字符流:字符输入输出流
注意:能用记事本打开,并且记事本中的内容可以看懂,使用字节使用字符都可以
如果内容是看不懂的,就使用字节流
如果不知道使用什么流,直接使用字节流
字节输出流FileOutputStream
FileOutputStream fos = new FileOutputStream("");
使用步骤:
1.创建对象(1.调用基层系统创建空文件 2.创建流的对象 3.让对象指向文件)
3.写数据(write())
2.关闭资源(减少底层系统的消耗,避免了在操作当前文件时,还有别的程序操作当前文件)
写数据的三种方法
write(int b) 将指定的字节写入文件,一次写一个字节
write(byte[] b) 将指定的字节数组写入文件,一次写一个字节数组
write(byte[] b,int off,int len) 将指定的字节数组,从偏移量off开始写入文件,一次写len个字节,一次写数组的一部分
注意:字节可以为int可以char
off理解为索引或下标
len从off开始写入几个字节
构造:
FileOutputStream(String name) 调用底层系统创建空文件 默认调用下面一个构造 只不过append默认为false
FileOutputStream(String name,boolean append) append为true表示追加
FileOutputStream(File file)
FileOutputStream(File file,boolean append)
字节输入流FileInputStream
FileInputStream ios = new FileInputStream("");
使用步骤:
1.创建对象(1.抽象路径所指文件必须存在 2.创建流的对象 3.让对象指向文件)
3.写数据(read())
2.关闭资源(减少底层系统的消耗,避免了在操作当前文件时,还有别的程序操作当前文件)
读数据的三种方式
int read() 读取一个字节 得到的返回值是字节
int read(byte[] b) 按照一个字节数组读取数据,返回值为读取的字节个数
注意:如果数组长度大于文件中内容,所得到的返回值为读取的字节个数
int read(byte[] b,int off,int len) 按照一个字节数组的一部分去读取数据,返回值为读取的字节个数
注意:off决定读取得到字节存储位置
如果获取数组中的一部分,通过read的返回值(就是读取的内容个数)
循环读取写法:没有读取导数据时,返回值为-1
int i;
while((i=fis.read())!=-1){
Syste.out.println(new String(bytes,0,i));
}
注意:换行符占两个字节
windows中换行符默认是\r\n
linux中换行符默认是\n
mac中换行符默认是\r
idea能识别所有换行符,windwos中使用idea识别换行符使用\r\n
##编码集
常用编码集:ASCII GBK Uniconde
Uniconde统一的万国码,有UTF-8,-16...常用UTF-8
乱码出现的问题:编码和解码所用的编码集不同
编码:
byte[] getBytes():使用平台的默认字符编码集将String存储字节数组
byte[] getBytes(String chareName):使用指定的编码集String存储字节数组
解码:
String(byte[] bytes):通过默认字符集解码指定的数组来构造新的String
String(byte[] bytes,String chareName):通过指定字符集解码指定的数组来构造新的String
注意:编码和解码所随用的编码集要保持一直,不然会出现乱码问题
UTF-8使用3个字节表示字符
GBK使用两个字节表示字符
windows默认编码格式为GBK
##缓冲流
为什么使用缓冲流?
避免底层系统的多次调用
BufferedOutputStream(OutputStream):
BufferedOutputStream fos=new BufferedOutputStream(new FileOutputStream(""));
字节输出缓冲流
注意:缓冲流默认拥有缓冲区,默认大小为8192
写入数据时,首先先写入缓冲区,在写入到文件
什么情况下缓冲区中的数据会写入到文件?
1.调用了close或flush
2.写入的数据大小超出了缓冲区的大小(缓冲区满了会把写入到文件中,然后把当前缓冲区清空用于接收下面的数据)
BUfferedInputStream(InputStream):
字节输入缓冲流
BufferedInputStream ios=new BufferedInputStream(new FileInputStream(""));
IO字符流
为什么使用字符流?
1.字节流操作中文时,会出现乱码的情况(可能会把中文拆分进行读取)
2.需要关注解码和编码的过程
字符流
Read:这个抽象类表示字符输入流的所有类的父类
Write:这个抽象类表示字符输出流的所有类的父类
OutputStreamWrite:文件字符输出流(具体的字符输出流实现类)
OutputStreamWrite(OutputStream out)创建文件字节输出流写入文件
write(String s)
write(String s,int off,int len)
注意:底层还是字节流
OutputStreamWrite
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(""))
OutputStreamWrite构造:
OutputStreamWriter(OutputStream out) 创建一个使用默认字符编码的OutputStreamWriter。
OutputStreamWriter(OutputStream out, Charset cs) 创建一个使用给定字符集的OutputStreamWriter。
OutputStreamWrite写数据的方法:
void write(int c) 写一个字符
void write(char[] cbuf) 写一个字符数组
void write(char[] cbuf,int off,int len) 写一个字符数组的一部分
void write(String str) 写一个字符串
void write(String str,int off,in len) 写一个字符串的一部分
InputStreamReader
InputStreamReader isr = new InputStreamReader(new FileInputStream(""))
InputStreamReader构造:
InputStreamReader(InputStream in)创建一个使用默认字符集的InputStreamReader。
InputStreamReader(InputStream in, Charset cs)创建一个使用给定字符集的InputStreamReader。
InputStreamReader读取数据的方法:
void read() 读一个字符
void read(char[] cbuf,int offset,int len)将字符读入数组的一部分
字符流的便捷方式
FileWriter fw = new FileWriter("");
FileReader fr = new FileReader("");
使用FileWrite和FIleReader
构造:
FileWrite(String filename);
FileReader(String filename);
注意:FileWrite和FIleReader只能使用平台默认的字符集
字符缓冲输出流""中是字节流目录或对象
BufferedWriter bw = new BufferedWriter(new FileWriter(""))
BufferedWriter bw = new BufferedWriter(new OutputStreamWrite(""))
方法:
newLine():表示换行符(不需要在关心使用的换行符是什么)
字符缓冲输入流""中是字节流目录或对象
BufferedReader br = new BufferedReader(new FileReader(""))
BufferedReader br = new BufferedReader(new InputSteamReader(""))
方法:
readLine():表示读取一行数据,不会读取换行符
对象流:
底层还是字节流
对象序列化:把对象信息持久化到文件之中,或者网络中进行数据传输
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(""))
对象反序列化:把文件中的对象信息持久化到对象
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(""))
序列化接口Serializable:起到了标识的作用,标识当前类可以进行序列化或反序列化没有方法或字段
类中没有自定义UID:序列化之后,如果一个类的结构发生改变,反序列化时,会出现会出现InvalidClassException:
因为当序列化运行时检测到类中的以下问题之一时抛出。
1.类的串行版本与从流中读取的类描述符的类型不匹配
2.该类包含未知的数据类型
3.该类没有可访问的无参数构造函数
UID:序列化时,系统默认分配的相关联的版本号(默认情况下,类的结构发生改变时,UID也会发生改变)
序列化的类可以自定义UID(会把系统默认分配的UID覆盖)
如果序列化的类自定义UID之后,如果UID没有发生改变,类结构发生改变时,不会出现1的问题
成员变量如何不被序列化?
给该成员加上一个transient关键字修饰,标识了该成员不参与序列化,(值为系统分配的默认值)