Java学习(6):File、IO


一、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字符集
  1. ASCII字符集
    包括了数字、英文、符号。
    每一个字节存储一个字符,一个字节是8位,总共可以表示128个字符信息

  2. 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"));
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值