File类
1.静态属性
文件路径分隔符
static String pathSeparator 与系统相关的路径分隔符字符,为方便起见,表示为字符串。
static char pathSeparatorChar 与系统相关的路径分隔符。
static String separator 文件分隔符,以方便的方式表示为字符串。
static char separatorChar 文件分隔符。
2.构造方法
创建路径对象
File(File parent, String child) 从父抽象路径名和子路径名字符串创建新的 File实例。
File(String pathname) 通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。
File(String parent, String child) 从父路径名字符串和子路径名字符串创建新的 File实例。
3.常用成员方法
-创建功能
boolean createNewFile() 创建文件
boolean mkdir() 创建单级文件夹
boolean mkdirs() 创建多级文件夹
-删除功能
boolean delete()
-重命名
boolean renameTo(File dest)
-判断功能
boolean canRead()
boolean canWrite()
boolean exists()
boolean isDirectory()
boolean isFile()
boolean isHidden()
-基本获取
String getAbsolutePath()
String getCanonicalPath()
String getName() 路径名表示的文件或目录的名称
String getPath()
long length() 路径名表示的文件的长度,文件夹或者不存在的,返回0
long lastModified() 返回此抽象路径名表示的文件上次修改的时间。
-高级获取
String[] list() 获取指定路径下所有文件和文件夹名称的数组
String[] list(FilenameFilter filter) 返回一个字符串数组,命名由此抽象路径名表示的目录中满足指定过滤器的文件和目录。
File[] listFiles() 获取指定路径下所有文件和文件夹File数组
File[] listFiles(FileFilter filter) 返回一个抽象路径名数组,表示由此抽象路径名表示的满足指定过滤器的目录中的文件和目录。
File[] listFiles(FilenameFilter filter) 返回一个抽象路径名数组,表示由此抽象路径名表示的满足指定过滤器的目录中的文件和目录。
注意:FileFilter和FilenameFilter文件过滤器,是没有实现类的俩个接口,需要重写accept()方法。
4.过滤器FileFilter和FilenameFilter
FileFilter和FilenameFilter文件过滤器,是没有实现类的俩个接口,需要重写accept()方法。
原理:
1.listFile会对构造方法中传递路径进行遍历
2.listFile会将遍历的传递给过滤器的方法accept
3.accept:true:就会把传递过来的file对象保存在数组中;false:不保存
// 文件过滤器FileFilter
private static void findDir2(File file) {
File[] files = file.listFiles((File pathname) -> {
if (pathname.isDirectory()) {
// findDir2(pathname);
return true;
}
return pathname.getName().toLowerCase().endsWith(".txt");
// 文件过滤器FilenameFilter(相当于把路径和最后的name分开了)
private static void findDir3(File file) {
File[] files = file.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return new File(dir, name).isDirectory() || name.toLowerCase().endsWith(".txt");
}
});
for (File file1 : files) {
System.out.println(file1);
}
}
递归
- 概述:递归指在当前方法内调用自己的这种现象
- 分类:直接递归和间接递归
直接递归:方法自身调用自己
间接递归:A调用B方法,B调用C方法 - 注意事项:递归要有条件设置,保证递归可以停下来,也不能递归的次数太多
- 代码:
// 递归遍历文件和文件夹
private static void bianLi(File f) {
System.out.println(f);
File[] files = f.listFiles();
for (File file : files) {
if (file.isDirectory()) {
// System.out.println(file);
bianLi(file);
} else {
System.out.println(file);
}
}
}
IO流
- io流常用的基类
-字节流常用的基类
InputStream
OutputStream
-字符流常用的基类
Reader
Writer - 字节流
OutputStream抽象类 FileOutputStream 子类 -构造方法 FileOutputStream(File file) FileOutputStream(String name) -常用的方法 void close() 关闭此输出流并释放与此流相关联的任何系统资源。 void flush() 刷新此输出流并强制任何缓冲的输出字节被写出。 void write(byte[] b) //字节数组中如果有负数,那么这个数会和后面的数组合在一起,转换城汉字 void write(byte[] b, int off, int len) void write(int b) -构造方法的作用 1.创建对象 2.创建文件或者文件夹 3.将对象指向创建好的文件 -如何写入数据 1.Java程序->jvm->os->os调用写数据 -使用步骤: 1.创建对象 2.调用方法写入数据 3.释放资源 -如何实现追加写入和对数据进行换行 用带2个参数的构造方法,第二个参数给true FileOutputStream(File file, boolean append) FileOutputStream(String name, boolean append) 代码: FileOutputStream fos = new FileOutputStream("F:\\a\\a.2\\456.txt", true);//追加 for (int i = 0; i < 10; i++) { fos.write("你好".getBytes());//将字符转化为字节 fos.write("\r\n".getBytes()); //换行 } fos.close();
InputStream抽象类 FileInputStream子类 -构造方法 FileInputStream(File file) FileInputStream(String name) -成员方法 void close() int read() 每次读取文件的一个字符,读取完毕返回-1,utf-8汉字占三个字节,gbk和ASCII汉字占2个字节 ~~~ int len = 0; while ((len = fis.read()) != -1) { System.out.println(len); } ~~~ int read(byte[] b) //byte大小一般为1024的整数倍 int read(byte[] b, int off, int len ) -字节输入流读取数据的步骤 1.创建对象 2.调用方法读取数据 3.释放资源
- 字符流
close()和flush()的区别:flush:刷新缓冲区,流对象可以继续使用,close:刷新缓冲区,流对象关闭1,字符输出流 Writer OutputstreamWriter FileWriter -构造方法 FileWriter(File file) FileWriter(String fileName) FileWriter(File file, boolean append) FileWriter(String fileName, boolean append) -成员方法 void close() 关闭流,先刷新。 void flush() 将写入到内存缓冲区的字节,刷新流。 String getEncoding() 返回此流使用的字符编码的名称。 void write(char[] cbuf, int off, int len) 写入字符数组的一部分。 void write(int c) 写一个字符 void write(String str, int off, int len) 写一个字符串的一部分。
2,字符输入流 Reader InputstreamReader FileReader -构造方法 FileReader(File file) FileReader(String fileName) -成员方法 void close() 关闭流并释放与之相关联的任何系统资源 String getEncoding() 返回此流使用的字符编码的名称 int read() 读一个字符 int read(char[] cbuf, int offset, int length) 将字符读入数组的一部分。
- IO异常处理
- 在jdk1.7之前使用try catch finally处理异常
- 变量的作用域是俩个大括号”{}“,变量初始可以没有值但在使用的时候必须给值。
- 在jdk7中,可以在try的后边增加一个(),在括号中可以定义流对象,那么这个流对象的作用域就在try中有效,当try中的代码执行完毕,会自动把流对象释放,不需要写finally
格式:
try(定义流对象){
可能产生的代码
}catch(异常类 异常名){
异常的处理逻辑
} - 在jdk1.9,try的前边可以定义流对象,在try后的括号中直接写入流对象的引用名,当try中的代码执行完毕,会自动把流对象释放,不需要写finally
格式:
A a = new A();
B b = new B();
try(a, b){
可能产生的代码
}catch(异常类 异常名){
异常的处理逻辑
}
Properties属性类
1. 他是Hashtable的子类,属性列表中的每个键及其对应的值都是一个字符串,是一个双链的集合。
2. Properties可以保存到流中或从流中加载。
3. 常用方法
~~~
// 加载
void load(InputStream inStream) //不能读取含有有中文的内容
void load(Reader reader)
---------------------------------------
/*使用load方法
* 1.创建properties对象
* 2.使用load方法
* 3.遍历properties集合
* */
public static void main(String[] args) throws IOException {
Properties prop = new Properties();
prop.load(new FileReader("F:\\a\\a2\\456.txt"));
Set<String> set = prop.stringPropertyNames();
for (String s : set) {
System.out.println(s + "=" + prop.getProperty(s));
}
// Iterator<String> iterator = set.iterator();
// while (iterator.hasNext()) {
// System.out.println(iterator.next() + "=" + prop.getProperty(iterator.next()));
// }
}
---------------------------------------
//把集合中的临时数据,持久化写入到硬盘中
void store(OutputStream out, String comments) 不能使用中文,comments是注释,表示这是干什么的,将此 Properties表中的此属性列表(键和元素对)以适合于使用 load(InputStream)方法加载到 Properties表格的格式写入输出流。
void store(Writer writer, String comments) 将此属性列表(键和元素对)写入此 Properties表中,以适合使用 load(Reader)方法的格式输出到输出字符流。
---------------------------------------
public static void main(String[] args) throws IOException {
//创建properties对象
Properties prop = new Properties();
//添加内容
prop.setProperty("迪丽热巴", "10");
prop.setProperty("古力娜扎", "11");
prop.setProperty("稀里哗啦", "12");
//创建输出流对象
FileWriter fw = new FileWriter("F:\\a\\a2\\456.txt");
//调用store方法将properties的内容作为输出的内容
prop.store(fw,"save data");
fw.close();
prop.store(new FileOutputStream("F:\\a\\a2\\789.txt"), "sava data");
}
---------------------------------------
//设置内容
Object setProperty(String key, String value) 调用 Hashtable方法 put 。
// 根据键获取值
String getProperty(String key) 使用此属性列表中指定的键搜索属性。
// 返回键的set集合
Set<String> stringPropertyNames() 从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串,相当于keyset()方法。
~~~
缓冲流
字节缓冲流
- BufferedInputStream
- BufferedOutputStream
字符缓冲流(其他缓冲流同理),提高效率
-
BufferedWriter 字符缓冲输出流 写数据
-
BufferedReader 字符缓冲输入流 读数据
-
BufferedWriter
将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入。
可以指定缓冲区大小,或者可以接受默认大小。 默认值足够大,可用于大多数用途。-构造方法 BufferedWriter(Writer out) BufferedWriter(Writer out, int sz) -特有方法 void newLine() 根据当前系统自动决定换行符,println就是调用newLine()方法
-
BufferedReader
从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取。
可以指定缓冲区大小,或者可以使用默认大小。 默认值足够大,可用于大多数用途。-构造方法 BufferedReader(Reader in) BufferedReader(Reader in, int sz ) -特有方法 String readLine() 一次读取一行,读完就是null -------------------------------- BufferedReader br = new BufferedReader(new FileReader("F:\\a\\a2\\456.txt")); String s; while ((s = br.readLine()) != null) { System.out.println(s); } --------------------------------
有序号的文本排序的练习
public class WenBenPaixu { public static void main(String[] args) throws IOException { // 创建一个map集合,键可以排序,用来存储序号;值用来存储内容 HashMap<String, String> map = new HashMap<>(); // 创建一个输入缓冲流 BufferedReader br = new BufferedReader(new FileReader("F:\\a\\a2\\741.txt")); // 创建一个输出缓冲流 BufferedWriter bw = new BufferedWriter(new FileWriter("F:\\a\\a2\\742.txt")); // line用来接受每次读取的行 String line; // 每次读取一行,并将其分割,存入map集合中 while ((line = br.readLine()) != null) { // 分割返回一个string数组 String[] arr = line.split("\\."); map.put(arr[0], arr[1]); } // 返回一个map的set集合 Set<Map.Entry<String, String>> entrySet = map.entrySet(); // 遍历set集合 Iterator<Map.Entry<String, String>> iterator = entrySet.iterator(); while (iterator.hasNext()) { // 获取map的对象entry Map.Entry<String, String> entry = iterator.next(); // 获取map集合的键和值,同时写入到文件中 bw.write(entry.getKey() + "." + entry.getValue()); // 写入一行后换行 bw.newLine(); } bw.flush(); bw.close(); br.close(); }
转换流
根据不同的编码,读写文件
OutputStreamWriter 字符输出流,继承了Writer
OutputStreamWriter(OutputStream out) 根据默认编码把字节流转成字符流
OutputStreamWriter(OutputStream out, String charsetName)根据指定编码把字节流转成字符流
写数据的方法
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, int len)
flush()
close()
InputStreamReader 字符输入流,继承了Reader
InputStreamReader(InputStream in)根据默认编码把字节流转成字符流
InputStreamReader(InputStream in, String charsetName)根据指定编码把字节流转成字符流
读数据的方法
int read()
int read(char[] cbuf)
int read(char[] cbuf, int off, int len)
void close()
序列化与反序列化
概念
- 序列化:把对象以流的形式保存到文件中,也可以理解为把对象转换为字节序列的过程称为对象的序列化。
ObjectOutputStream - 反序列化:把字节序列恢复为对象的过程称为对象的反序列化。
ObjectInputStream
序列化和反序列化的实现
- 序列化和反序列化的时候会抛出NotSerializableException没有序列化异常。因此类需要实现java.io.Serializable接口以启用其序列化功能。未实现此接口的无法实现序列化,Serializable接口也叫标记型接口,接口里什么也没有。
- 代码
ObjectOutputStream // 特有方法 void writeObject(Object obj) 将指定的对象写入ObjectOutputStream。 -------------------------------------- public class DemoXuliehua { public static void main(String[] args) throws IOException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("F:\\a\\a2\\222.txt")); oos.writeObject(new Person("你好", 20)); oos.close(); } } --------------------------------------
ObjectInputStream // 特有方法 Object readObject() 从ObjectInputStream读取一个对象。 -------------------------------------- public static void main(String[] args) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream(new FileInputStream("F:\\a\\a2\\222.txt")); Object o = ois.readObject(); ois.close(); // 可以输出一下这个对象 System.out.println(o); } --------------------------------------
- transient关键字:瞬态关键字
- 序列化和反序列化值针对对象的,所以被static修饰的类成员不可以被序列化,以及被transient关键字修饰的也不可以被序列化。
- serialVersionUID字段
当对象被改变的时候反序列化也会失败,解决的方法:- 反序列化的原理是存在一个serialVersionUID的版本号,他的作用是在反序列化的过程中用于验证序列化对象的接受者和发送者是否是相兼容的类。
- 因此只需要在被序列化的对象中加入serialVersionUID,该字段必须是静态的(static),最终的(final),long类型的字段。
static final long serialVersionUID = 1L;
序列化集合练习
当需要存储多个对象的时候,可以将对象存如集合中,对集合进行序列化,需要的时候反序列化集合对象,在遍历集合
public static void main(String[] args) throws IOException, ClassNotFoundException {
// 创建个集合用来存储对象
ArrayList<Person> al = new ArrayList<>();
// 在集合中添加对象
al.add(new Person("范冰冰", 20));
al.add(new Person("杨幂", 30));
al.add(new Person("杨紫", 10));
// 创建序列化对象
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("F:\\a\\a2\\123.txt"));
// 写进去
oos.writeObject(al);
// 关闭资源
oos.close();
// 创建反序列化对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("F:\\a\\a2\\123.txt"));
// 读取
Object o = ois.readObject();
// 将object转换为list
// List list = (List) o;
// 强转arraylist
ArrayList<Person> list = (ArrayList) o;
// 遍历集合
for (Object o1 : list) {
System.out.println(o1);
}
// 关闭资源
ois.close();
}
打印流
java.io.PrintStream:打印流,继承了OutputStream
特点:
1.只负责数据的读出,不负责数据的读取
2. 不会抛出IOException
3. 有特有的方法print(任意类型),println(任意类型)
OutputStream中的方法
在使用write()方法的时候,直接可以实现追加写入
---------------------------------------------------
构造方法
PrintStream(File file) 使用指定的文件创建一个新的打印流,而不需要自动换行。
PrintStream(OutputStream out) 创建一个新的打印流。
PrintStream(String fileName) 使用指定的文件名创建新的打印流,无需自动换行。
成员方法
void print(任意类型) 打印
void println(任意类型) 打印
在system中有一个方法可以改变输出的目的
static void setOut(PrintStream out) 重新分配“标准”输出流。
注意:
- 如果使用继承自父类的write方法写数据的时候,那么查看数据的时候会查询编码表 97->a
- 如果使用自己特有的方法的时候,数据原样输出 97->97
代码:
public static void main(String[] args) throws FileNotFoundException {
System.out.println(97); // 输入在控制台
PrintStream ps = new PrintStream("F:\\a\\a2\\741.txt");
ps.write(97); // 追加写入,查询编码
ps.write(98); // 追加写入,查询编码
ps.println(97); // 直接写入内容
System.setOut(ps); // 改变输入的目的
System.out.println("你好"); // 在文件中输入你好
}