目录
一、File类
File类的对象代表系统中的文件、目录等。
使用File类 可以 创建文件夹,文件,获取文件信息,删除文件等。
- 分隔符
String pathSeparator = File.pathSeparator; // windows';' Linux ':' 路径分割符
System.out.println(pathSeparator);
String fileSeparator = File.separator; // / 目录的分割名称
System.out.println(fileSeparator);;
-
构造方法
File(String pathName) -
绝对路径
在系统中具有唯一性 如:c:\users\baidawei\downloads -
相对路径
表示的是路径之间的相对关系 如: /downloads/ 不需要考虑根级目录具体盘符 -
创建文件
//windows
File file = new File("c:\\Users\\baidawei\\Downloads\\o.txt");
if(!file.exists()){
boolean result = file.createNewFile();
System.out.println(result);
}
//mac
File file = new File("/Users/baidawei/Desktop/test.txt");
boolean result = file.createNewFile();
System.out.println(result);
- 常用方法
创建目录
boolean result = file.mkdir();
删除
boolean result = file.delete();
获取文件名或文件夹名
String fileName = file.getName(); //test.txt
获取文件路径
file.getPath() // /Users/baidawei/Desktop/test.txt
获取文件字节长度
file.length()
获取绝对路径 返回字符串
file.getAbsolutePath() // /Users/baidawei/Desktop/test.txt
获取绝对路径 返回file类
file.getAbsoluteFile() // /Users/baidawei/Desktop/test.txt
获取父路径 返回字符串
file.getParent() // /Users/baidawei/Desktop
获取父路径 返回File类
file.getParentFile() // /Users/baidawei/Desktop
文件或目录是否存在
file.exists() // boolean
判断是否是目录
file.isDirectory() // boolean
- 遍历文件
//获取路径中的文件和文件夹名 返回String[]
for (String s : file.list()){
System.out.println(s);
}
//获取当前目录下所有的"一级文件对象"到一个文件对象数组中去返回
for(File f : file.listFiles()){
System.out.println(f.getName());
}
- 递归
方法自己调用自己。
//n的阶乘 5 的阶乘是 5 x 4 x 3 x 2 x 1 = 120。
public static void main(String[] args) {
System.out.println(f(5));
}
public static int f(int n){
if(n == 1){
return 1;
}else {
return f(n - 1) * n;
}
}
public static void main(String[] args) {
System.out.println(eat(1)); //
System.out.println(eat(10));
}
//10天 剩1个 每天吃一半多1个 总共有多少
//f(10) = 1
//f(n) = (f(n+1) + 1) * 2, n < 10
//当第 10 天只剩下 1 个桃子时,其前一天应该有 (1 + 1) * 2 = 4 个桃子;
// 而其前一天又应该有 (4 + 1) * 2 = 10 个桃子,以此类推,直到第 1 天。
public static int eat(int day){
if(day == 10){
return 1;
}else{
return (eat(day+1)+1) *2;
}
}
- 递归查找文件
public static void main(String[] args) {
//递归查找 一个文件
File file = searchFile("/Users/david/downloads", "房屋租赁合同.docx");
}
public static File searchFile(String source,String fileName){
File file = new File(source);
if(file.exists() && file.isDirectory()){
if(file.listFiles() != null && file.listFiles().length>0){
for(File f : file.listFiles()){
if(f.isFile()){
if(f.getName().contains(fileName)){
System.out.println("找到了,"+f.getName()+";文件路径是:"+f.getAbsolutePath());
return f;
}
}else{
searchFile(f.getAbsolutePath(),fileName);
}
}
}
}else{
System.out.println("输入有误,不是文件夹");
}
return null;
}
二、字符集
多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同,常见字符集有:
- ASCII字符集
- GBK字符集
- UTF-8字符集
-
ASCII字符集
包括了数字、英文、符号。
每一个字节存储一个字符,一个字节是8位,总共可以表示128个字符信息 -
GBK
中国的比码表,包含了几万个汉字等字符,同事也要兼容ASCII编码。
GBK中一个中文字符一般以两个字节的形式存储。
3.Unicode字符集
统一码,也叫万国码,是计算机科学领域里的一项标准。
UTF-8 是Unicode的一种常见编码方式。
UTF-8 编码后一个中文一般以三个字节的形式存储,同时也要兼容ASCII码表。
字符编码时使用的字符集和编码时使用的字符集必须一致,否则会出现乱码。
字符集的编码解码
String编码、解码
//编码
String str= "abc我爱你中国";
//byte[] bytes = str.getBytes(); //默认字符集编码utf-8
byte[] bytes = str.getBytes("GBK"); //指定编码
System.out.println(Arrays.toString(bytes));
//解码
String rs = new String(bytes,"GBK");
System.out.println(rs);
三、IO流
input 把硬盘中的数据读入内存的过程,读数据。
output 把内存中的数据写到硬盘中,写数据。
1. 字节流
字节输入流 FileInputStream InputStream子类
构造器
public FileInputStream(File file);
public FileInputSream(String pathname);
读取字节
FileInputStream fi = new FileInputStream(file);
int len = 0;
while ((len=fi.read()) != -1){ //-1就是没了
System.out.println(len); //输出字节 每read一次 就是读取一次
}
fi.close();
性能较慢,读取中文无法避免乱码问题
读取字节数组(字符串):
FileInputStream fiStr = new FileInputStream(file);
byte[] b = new byte[8];
int lenStr = 0;
while((lenStr=fiStr.read(b)) != -1){
System.out.println(new String(b,0,lenStr)); //String 构造方法 参数是字节数组
}
fiStr.close();
性能得到了提升,但是仍然无法解决中文乱码问题
InputStream is = new FileInputStream(file);
byte [] b = new byte[(int)file.length()]; //定义一个与文件长度相同的字节数组
System.out.println(new String(b,0,is.read(b)));
直接把文件全部读取到一个特别大的字节数组中,解决了乱码问题,字节数组可能造成内存溢出。
写入字节
字节输出流 FileOutputStream OutputStream子类
构造器
public FileOutputStream(File file)
public FileOutputStream(File file,boolean append) 可追加数据
写入字节
File file = new File("/Users/david/downloads/test.txt");
FileOutputStream fo = new FileOutputStream(file);
fo.write((byte)'a');
fo.write((byte)'b');
fo.write((byte)'c');
fo.close();
//没有就创建,有就覆盖
写入字节数组
File file = new File("/Users/david/downloads/test.txt");
String str = "我爱你中国\r\nabcc"; // \r\n换行
FileOutputStream fo = new FileOutputStream(file);
fo.write(str.getBytes());
fo.close();
//没有就创建,有就覆盖
写一部分数据
byte[] bytes = {65,66,67,68,69,70};
fos.write(bytes,1,2);//BC
fos.close();
续写 第二个参数为true 可以追加不覆盖
File file = new File("/Users/david/downloads/test.txt");
String str = "我爱你中国\r\nabcc";
FileOutputStream fo = new FileOutputStream(file,true); //续写 第二个参数为true 可以追加不覆盖
fo.write(str.getBytes());
fo.flush(); //不关闭流 刷新最新数据 再继续写
fo.write('b');
fo.close();
//没有就创建,有就覆盖
复制文件
//将此文件复制一份
File file = new File("/Users/david/downloads/jdk-8u351-windows-x64.exe");
File newFile = new File("/Users/david/downloads/jdk-8u351-windows-x64-1.exe");
if(!newFile.exists()){
newFile.createNewFile();
}
FileInputStream fi = new FileInputStream(file);
FileOutputStream fo = new FileOutputStream(newFile,true);
try{
int len = 0;
byte[] data = new byte[1024];
while ((len = fi.read(data)) != -1){
fo.write(data,0,len);
fo.flush();
}
}catch (Exception e){
e.printStackTrace();
}finally { //是否报错都执行 释放资源
fi.close();
fo.close();
}
finally是一定会执行的
public static int num() {
try {
return 1; //会被覆盖
} catch (Exception e) {
} finally {
return 2; //返回2
}
}
释放资源
将可释放资源 放到try()括号中去 实现自动释放
public static void main(String[] args) throws IOException {
//将此文件复制一份
File file = new File("/Users/david/downloads/jdk-8u351-windows-x64.exe");
File newFile = new File("/Users/david/downloads/jdk-8u351-windows-x64-1.exe");
if (!newFile.exists()) {
newFile.createNewFile();
}
try(
FileInputStream fi = new FileInputStream(file);
FileOutputStream fo = new FileOutputStream(newFile, true);
//int a = 1; //报错 只有可释放的资源可以放到 try()中
){
int len = 0;
byte[] data = new byte[1024];
while ((len = fi.read(data)) != -1) {
fo.write(data, 0, len);
fo.flush();
}
}catch (Exception e){
e.printStackTrace();
}
}
拷贝文件夹
public static void main(String[] args) {
copy(new File("/Users/david/downloads/SuiteScripts"), new File("/Users/david/downloads/SuiteScripts-1"));
}
public static void copy(File src, File dest) {
if (src != null && src.exists() && src.isDirectory()) {
File destOne = new File(dest, src.getName());
destOne.mkdirs();
File[] files = src.listFiles();
if (files != null && files.length > 0) {
for (File file : files) {
if (file.isFile()) {
copyFile(file, new File(destOne, file.getName()));
System.out.println(destOne.getAbsolutePath() +"/" + file.getName());
} else {
copy(file, destOne);
}
}
}
}
}
public static void copyFile(File srcFile, File destFile) {
try (
// 1、创建一个字节输入流管道与原视频接通
InputStream is = new FileInputStream(srcFile);
// 2、创建一个字节输出流管道与目标文件接通
OutputStream os = new FileOutputStream(destFile);
) {
// 3、定义一个字节数组转移数据
byte[] buffer = new byte[1024];
int len; // 记录每次读取的字节数。
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.字符流
字符输入流 FileReader
构造方法
Public FileReader(File file)
public FileReader(String pathname)
读取字符
File file = new File("/Users/david/downloads/test.txt");
FileReader fr = new FileReader(file);
int len = 0;
while((len = fr.read()) != -1){
System.out.println(len); //每次读取一个字符
}
fr.close();
读取中文不会出现乱码 每次读取一个字符,性能较慢
读取字符数组
File file = new File("/Users/david/downloads/test.txt");
FileReader fr = new FileReader(file);
char[] b = new char[1024];
int len = 0;
while((len = fr.read(b)) != -1){
System.out.println(new String(b,0,len)); //每次读取一个字符数组
}
fr.close();
字符输出流 FileWriter
构造方法
public FileWriter(File file)
public FileWriter(File file,boolean append)
写入字符流
File file = new File("/Users/david/downloads/test.txt");
FileWriter fw = new FileWriter(file,true); //追加
fw.write('a'); //输出一个字符
fw.flush();//最好写一次刷一次,释放内存
fw.write(new char[]{'a','b','c'}); //输出一个字符数组
fw.write(new char[]{'a','b','c','d'},1,2); //从第二个到第三个 bc
fw.write("abcdlsle"); //输出一个字符串
fw.close();
字节流适合做一切文件的拷贝,字节流不适合读取中文内容输出。
字符流适合做文本文件的读写操作。
转换流
解决乱码问题
因为写文件时会默认本机编码表,GBK,美国机器打开就会乱码。
使用OutputStreamWriter(OutputStream out) 读取文件可以指定编码类型
//使用转换流指定编码表
FileOutputStream fo = new FileOutputStream(file);
OutputStreamWriter osw = new OutputStreamWriter(fo, "GBK"); //默认GBK可以不写
osw.write("你好");
osw.flush();
osw.close();
//如果编码格式不一致则会乱码
FileInputStream fi = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(fi, "UTF-8"); //不一致会乱码
int len = 0;
while ((len = isr.read()) != -1) {
System.out.println((char) len);
}
isr.close();
fi.close();
3.缓冲流
提高读写速度、效率。
字节缓冲输出流 BufferedOutputStream(OutputStream out)
File file = new File("/Users/david/downloads/test.txt");
FileOutputStream fo = new FileOutputStream(file);
//使用缓冲流
BufferedOutputStream bo = new BufferedOutputStream(fo);
bo.write("啦啦啦".getBytes());
bo.close();
fo.close();
字节缓冲输入流 BufferedInputStream
FileInputStream fi = new FileInputStream(file);
//使用缓冲流
BufferedInputStream bi = new BufferedInputStream(fi);
int len = 0;
byte [] b = new byte[1024];
while((len=bi.read(b)) != -1){
System.out.println(new String(b,0,len));
}
bi.close();
fi.close();
字符输出缓冲流
String url = "/Users/david/downloads/test.txt";
FileWriter fw = new FileWriter(url);
BufferedWriter bfw = new BufferedWriter(fw);
bfw.write("测试bufferedWriter输出流缓冲流");
bfw.flush();
//特有换行方法
bfw.newLine();
bfw.write("newline好使么?");
bfw.flush();
bfw.close();
字符输入缓冲流
String url = "/Users/david/downloads/test.txt";
FileReader fr = new FileReader(url);
BufferedReader br = new BufferedReader(fr);
String line = null;
while ((line = br.readLine()) != null) {
//特有方法 读取一整行 返回字符串 不包含\r\n换行符号
System.out.println(line);
}
字符缓冲流复制
BufferedReader br = new BufferedReader(new FileReader("/Users/david/downloads/test.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("/Users/david/downloads/test-1.txt"));
String line = null;
while((line = br.readLine()) != null){
bw.write(line);
bw.newLine();
}
br.close();
bw.close();
System.out.println("完成");
四、序列化
1.对象序列化
对象中的数据new Person();以流的形式写入到文件中保存的过程称为写出对象。
ObjectOutputStream 写出对象 对象的序列化
import java.io.Serializable;
//类需要实现Serializable接口
public class Person extends Object implements Serializable {
//序列化的版本号与反序列化的版本号必须一致才不会出错!
private static final long serialVersionUID = 2;
private String name;
// transient修饰的成员变量不参与序列化了
private transient int age;
Person(String name){
this.name = name;
}
Person(String name,int age){
this(name);
this.age = age;
}
@Override
public String toString(){
return "Person[name" + name + ", age =" + age +"]";
}
}
Person p = new Person("name",18);
FileOutputStream fos = new FileOutputStream("/Users/david/downloads/test.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(p);
oos.close();
fos.close();
文件内容:
��srPerson��J;~���IageLnametLjava/lang/String;xptname
2.对象反序列化
对象的反序列化 ,把文件中保存的数据反序列化为对象。
ObjectInputStream 读取对象
FileInputStream fi = new FileInputStream(pathname);
ObjectInputStream ois = new ObjectInputStream(fi);
Person o = (Person)ois.readObject();
System.out.println(o);
ois.close();
fi.close();
五、打印流
打印流可以方便、高效的打印数据到文件中去。 写什么就输出什么
1.PrintStream
字节输出流
String pathname = "/Users/david/downloads/test.txt";
// 创建一个打印流对象
// PrintStream ps = new PrintStream(new FileOutputStream(pathname));
// PrintStream ps = new PrintStream(new FileOutputStream(pathname , true)); // 追加数据
// PrintStream ps = new PrintStream(pathname);
PrintWriter ps = new PrintWriter(pathname); // 打印功能上与PrintStream的使用没有区别
ps.println(97);
ps.println('a');
ps.println(23.3);
ps.println(true);
ps.println("我是打印流输出的,我是啥就打印啥");
ps.close();
2.PrintWriter
字符输出流
System.out.println("锦瑟无端五十弦");
System.out.println("一弦一柱思华年");
// 改变输出语句的位置(重定向)
PrintStream ps = new PrintStream(pathname);
System.setOut(ps); // 把系统打印流改成我们自己的打印流
System.out.println("庄生晓梦迷蝴蝶"); //存到文件中 不再打印到控制台
System.out.println("望帝春心托杜鹃");
打印上方便,高效。
六、Properties
属性文件 以.properties结尾,其实就是一个Map集合。内容都是key=value,做系统配置用的。
Properties的方法:
- public Object setProperty(String key, String value) : 保存一对属性。 (put)
- public String getProperty(String key) : 使用此属性列表中指定的键搜索属性值 (get)
- public Set stringPropertyNames() : 所有键的名称的集合 (keySet())
- public void store(OutputStream out, String comments): 保存数据到属性文件中去
- public void store(Writer fw, String comments): 保存数据到属性文件中去
保存文件
String pathname = "/Users/david/downloads/test.txt";
Properties properties = new Properties();
properties.setProperty("username","admin"); //写属性
properties.setProperty("password","123");
System.out.println(properties);
//保存文件
properties.store(new FileWriter(pathname),"config description");
读取文件
Properties getPro = new Properties();
getPro.load(new FileReader(pathname));
System.out.println(getPro.get("username")); //获取指定key信息
for (Object o : getPro.keySet()) { //遍历配置信息
System.out.println(o);
}
七、commons-io
commons-io是apache开源组织提供的一组有关IO操作的类库,可以提高io操作的开发效率。
下载后 在Idea中选择File->Project Structure->Dependencies->加号->JARs or directories->ok->External Libraries中就出现了
1.FilenameUtils
String pathname = "/Users/david/downloads/test.txt";
//获取文件扩展名
String extension = FilenameUtils.getExtension(pathname);
System.out.println(extension);
//获取文件名 包含后缀名
String name = FilenameUtils.getName(pathname);
System.out.println(name);
//判断是否为指定后缀名文件
boolean txt = FilenameUtils.isExtension(pathname, "txt");
System.out.println(txt);
2.FileUtils
String pathname = "/Users/david/downloads/test.txt";
//读取文件 返回String
String s = FileUtils.readFileToString(new File(pathname), "UTF-8");
System.out.println(s);
//写字符串到文件
FileUtils.writeStringToFile(new File(pathname),"写点信息进去","UTF-8");
//复制文件
FileUtils.copyFile(new File(pathname),new File("/Users/david/downloads/test-2.txt"));
//复制文件夹
FileUtils.copyDirectory(new File("/Users/david/downloads/SuiteScripts"),new File("/Users/david/downloads/s-2"));
//复制到目标文件夹中去
FileUtils.copyDirectoryToDirectory(new File("/Users/david/downloads/SuiteScripts"),new File("/Users/david/downloads/s-2"));