文件与IO

常用的文件操作

创建文件

  • createNewFile() + 三种构造方法
1、直接全部路径
File parentFile = new File("D:\\FileTest");
File file = new File(filePath);
file.createNewFile();

2、目录 + 文件名
String parentPath = "D:\\FileTest";
String fileName = "news03.txt";
File file = new File(parentPath, fileName);
System.out.println("创建成功");

3、目录对象 + 文件名
File parentFile = new File("D:\\FileTest");
String fileName = "news02.txt";
File file = new File(parentFile, fileName);
file.createNewFile();

文件已经存在? 不会报错,也不会再创建该文件,不会进行覆盖之类的操作

获取文件相关信息

  • file.getName():获取文件名字
  • file.getAbsolutePath():获取绝对路径
  • file.getParent():获取父级目录
  • file.length():获取文件大小(字节)
  • file.exists():判断文件是否存在
  • file.isFile():判断是不是一个文件
  • file.isDirectory():判断是不是一个目录

目录操作和文件删除

  • 文件删除: file.delete() 文件存在删除并返回true,不存在返回false
String filePath = "D:\\FileTest1";
File file = new File(filePath);
if (file.exists()) {
    if (file.delete()) 
        System.out.println("删除成功");
    else
        System.out.println("删除失败");
} else {
    System.out.println("该目录不存在");
}
  • 目录删除,与文件删除同理,因为在java中,目录也被当作文件
String filePath = "D:\\FileTest1";
File file = new File(filePath);
if (file.exists()) {
    if (file.delete())
        System.out.println("删除成功");
    else
        System.out.println("删除失败");
} else {
    System.out.println("该目录不存在");
}
  • 目录创建,若存在,则不再创建,并返回false,若不存在,则创建且返回true
  • 创建单级目录:mkdir() 在已经存在的基础上,只能创建一级,若创建多级则返回false
  • 创建多级目录:mkdirs() 在已经存在的基础上,可以创建多级,也可以创建一级
String directoryPath = "D:\\FileTest\\test01"
File file = new File(directoryPath);
if (file.exists()) {
    System.out.println("该目录存在");
} else {
    if (file.mkdirs()) {
        System.out.println("该目录创建成功");
    } else {
        System.out.println("该目录创建失败");
    }
}

IO流原理与分类

IO流原理

1、对数据的输入和输出操作以”流(stream)“的方式进行
2、java.io包下提供了各种"流"类和接口,用以获取不同种类的数据,并通过方法输入或者输出数据
3、input:读取外部数据(磁盘,光盘等存储设备的数据)到程序(内存)中
4、output:将程序(内存)数据输出到磁盘,光盘等存储设备中

分类

在这里插入图片描述

在这里插入图片描述

字节流和字符流

基本介绍

节点流:可以从一个特定的数据源(如文件、数组、管道)读取数据,如FileReader、FileWriter
处理流:也叫做包装流,是"连接"在已存在的流(节点流或者处理流)之上,为程序提供跟各位i强大的读写功能,如BufferedReader,BufferedWriter

区别与联系

1、节点流是底层流/低级流,直接跟数据源连接
2、处理流(包装流)包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出。
3、处理流对节点流进行包装,使用了修饰器模式,不会直接与数据源相连接

分类图

分类作用字节流输入字节流输出字符流输入字符流输出
抽象基类InputStreamOutputStreamReaderWriter
节点流访问文件FileInputStreamFileOutputStreamFileReaderFileWriter
……访问数组ByteArrayInputStreamByteArrayOutputStreamCharArrayReaderCharArrayWriter
……访问管道PipedInputStreamPipedOutputStreamPipedReaderPipedWriter
……访问字符串StringReaderStringWriter
处理流缓冲流BufferedInputStreamBufferedOutputStreamBufferedReaderBufferedWriter
……转换流InputStreamReaderOutputStreamWriter
……对象流ObjectInputStreamObjectOutputStream
……抽象基类FilterInputStreamFilterOutputStreamFilterReaderFilterwriter
……打印流PrintStreamPrintWriter

处理流的主要功能

性能的提高:主要以增加缓冲的方式来提高输入输出的效率
操作的便捷:处理流可能提供了一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便

案例

节点流 FileInputStream 和 FileOutputStream
  • FileInputStream
1、读取一个字节
String filePath = "D:\\FileTest\\hello.txt";
int readData = 0;
// 创建FileInputStream对象,用于读取文件
FileInputStream fileInputStream = new FileInputStream(filePath);
//从该输入流读取一个字节的数据。如果没有输入可用,此方法将停止。
//如果返回-1,表示读取完毕
//read():该方法每次读取一个字节,返回该字节的十进制表示
while ((readData = fileInputStream.read()) != -1 )
	System.out.println((char)readData); //若不转换为char,则输出每一个字节的十进制表示
fileInputStream.close(); //关闭文件流,释放资源

2、一次读取很多字节
String filePath = "D:\\FileTest\\hello.txt";
int readData = 0;
byte[] buf = new byte[8];
int readLen = 0;
FileInputStream fileInputStream = new FileInputStream(filePath);
//从该输入流读取最多buf.length字节的数据到字节数组
//如果读取正常则返回实际读取的字节数
//如果返回-1,表示读取完毕
while ((readLen = fileInputStream.read(buf)) != -1 )
	System.out.println(new String(buf,0,readLen)); //读取buff内容中,从0到readLen-1 位置的数据
fileInputStream.close(); //关闭文件流,释放资源
  • FileOutputStream
String filePath = "D:\\FileTest\\a.txt";
//如果不存在,则创建该文件
//1、new FileOutputStream(filePath)创建方式,当写入内容时,会覆盖
//2、new FileOutputStream(filePath,true)创建方式,当写入内容时,是追加到内容后面
FileOutputStream fileOutputStream = new FileOutputStream(filePath,true);

fileOutputStream.write('H'); //写如一个字节

//写入字符串,因为不能直接写入字符串
String str = "你好";
fileOutputStream.write(str.getBytes());

//从字节数组中,选择0~4的内容写入
String str01 = "hello,world";
fileOutputStream.write(str01.getBytes(),0,5);

fileOutputStream.close();
节点流:FileReader和FileWriter
  • FileReader
1、一次读取一个字符
String filePath = "D:\\FileTest\\a.txt";
int data;
//1、创建一个FileReader对象
FileReader fileReader = null;
try {
    fileReader = new FileReader(filePath);
    //循环读取,读取单个字符
    //read():该方法返回一个一个字符的编码的十进制
    while ((data = fileReader.read()) != -1) {
        System.out.print((char)data);
    }
} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if(fileReader != null) {
        try {
            fileReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2、一次读取多个字符
String filePath = "D:\\FileTest\\a.txt";
int readLen = 0;
char[] buf = new char[8];
//1、创建一个FileReader对象
FileReader fileReader = null;
try {
    fileReader = new FileReader(filePath);
    //循环读取,读取多个字符
    //若读取成功,则返回读取的字符数,若失败,返回-1
    while ((readLen = fileReader.read(buf)) != -1) {
        System.out.println(readLen);
        System.out.println(new String(buf,0,readLen));
    }
} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if(fileReader != null) {
        try {
            fileReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
  • FileWriter
String filePath = "D:\\FileTest\\note.txt";
FileWriter fileWrite = null;
char[] chars = {'韩', '顺', '平'};
try {
	//无true则覆盖
	//有true则添加
    fileWrite = new FileWriter(filePath);
    //write(int):写入单个字符
    fileWrite.write('H');
    //write(char[]):写入指定数组
    fileWrite.write(chars);
    //write(char[],off,len):写入数组的指定部分
    fileWrite.write("韩顺平教育".toCharArray(),0,3);
    //write(String):写入整个字符串
    fileWrite.write(" ,你好中国");
    fileWrite.write("  风雨之后,定见彩虹  ");
    //write(String,off,len):写入字符串的指定部分
    fileWrite.write("上海天津",0,2);
    //数量打的时候,可以使用循环操作
} catch (IOException e) {
    e.printStackTrace();
} finally {
    //对于FileWriter,一定要关闭流,或者flush才能真正的把数据写入到文件
    try {
        fileWrite.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
System.out.println("程序结束");
处理流理解
在这里举一个例子说明
public class BufferedReader_ extends Reader_ {

    private Reader_  reader_; // 属性使Reader_类型

    //可以接受Reader_ 子类对象
    public BufferedReader_(Reader_ reader_) {
        this.reader_ = reader_;
    }

    public void readFiles(int num) {
        for (int i = 0; i < num; i++) {
            reader_.readFile();
        }
    }

    //扩展 readString, 批量处理字符串数据
    public void readStrings(int num) {
        for (int i = 0; i < num; i++) {
            reader_.readString();
        }
    }
}
处理流:BufferedReader和BufferedWriter
  • BufferedReader
String filePath = "D:\\FileTest\\a.txt";
BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
//读取
//1、bufferedReader.readLine() 是按行读取文件
//2、当返回null时,表示文件读取完毕
String line;
while ((line = bufferedReader.readLine()) !=null)
    System.out.println(line);

//关闭流,注意,只需要关闭 BufferedReader,因为底层会自动的去关闭 节点流
bufferedReader.close();
  • BufferedWriter
String filePath = "D:\\FileTest\\b.txt";
//创建BufferedWriter
//1、new FileWrite(filePath,true) 表示以追加的方式写入
//2、new FileWrite(filePath) 表示以覆盖的方式写入
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath,true));
bufferedWriter.write("hello,韩顺平教育!");
bufferedWriter.newLine();
bufferedWriter.write("hello2,韩顺平教育!");
bufferedWriter.newLine();
bufferedWriter.write("hello3,韩顺平教育!");
bufferedWriter.newLine();
//插入一个换行
bufferedWriter.close();

上述两个类属于字符流,是按照字符来读取数据的
关闭处理流时,只需关闭外层流留即可

处理流:BufferedInputStream和BufferedOutputStream
拷贝
byte[] c = new byte[1024];
int readLen = 0;
while ((readLen = bufferedInputStream.read(c)) != -1) {
    bufferedOutputStream.write(c,0,readLen);
}
对象流:ObjectInputStream和ObjectOutputStream

作用:保存值和数据类型
在这里插入图片描述
在这里插入图片描述

序列化要求版本统一,会记住类的具体位置,若修改了类,则反序列化时,jvm会认为这是新的类,不是之前的类,会报错
class Dog implements Serializable {
    private String name;
    private int age;
    //序列的版本号,可以提高兼容性
    //当加入新的属性时,jvm不会认为这是一个新的类,而是认为这是同一个版本的修改
    private static final long serialVersionUID = 1L;

    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

序列化:
//序列化后,保存的文件格式,不是存文本,而是按照他的格式来保存
String filePath = "D:\\FileTest\\data.txt";
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
//序列化数据
oos.writeInt(100); // 底层自动装箱 int -> Integer(实现了Serializable)
oos.writeBoolean(true); // boolean -> Boolean
oos.writeChar('c'); //char -> Character
oos.writeDouble(9.5); //double -> Double
oos.writeUTF("韩顺平教育"); //String
//保存一个dog对象
oos.writeObject(new Dog("旺财",10));
oos.close();

反序列化:
String filePath = "D:\\FileTest\\data.txt";
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));
//读取
//1、读取(反序列化)的顺序需要和保存的数据(序列化)的顺序一致
//2、否则会出现异常
System.out.println(ois.readInt());
System.out.println(ois.readBoolean());
System.out.println(ois.readChar());
System.out.println(ois.readDouble());
System.out.println(ois.readUTF());
System.out.println(ois.readObject()); //底层 Object -> Dog
ois.close();
转换流:InputStreamReader和OutputStreamReader

在这里插入图片描述

  • InputStreamReader
// InputStreamReader 转换流解决中文乱码问题
String filePath = "D:\\FileTest\\a1.txt";
//1、把FileInputStream 转成 InputStreamReader
//2、指定编码gbk
InputStreamReader gbk = new InputStreamReader(new FileInputStream(filePath), "gbk");
//3、把InputStreamReader 传入 BUfferedReader
BufferedReader bufferedReader = new BufferedReader(gbk);
//4、读取
String s = bufferedReader.readLine();
System.out.println("读取内容 = " + s );
bufferedReader.close();
  • OutputStreamWriter
String filePath = "D:\\FileTest\\hsp.txt";
String charSet = "gbk";
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filePath,true), charSet);
osw.write("hi,韩顺平");
osw.close();
配置文件Properties
读取配置文件

Properties properties = new Properties();
// 加载指定配置文件
properties.load(new FileReader("src\\file\\mysql.properties"));
// 根据key获得对应的值
String user = properties.getProperty("user");
String pwd = properties.getProperty("pwd");

写入配置文件
// 使用Properties类来创建配置文件,修改配置文件内容
Properties properties = new Properties();
// 创建
// 如果该文件没有某个key,则添加,若有则修改
/*
    Properties父类是Hashtable,底层就是Hashtable核心方法
 */
properties.setProperty("charset","utf8");
properties.setProperty("user","汤姆"); // 注意保存时,是中文的unicode码值
properties.setProperty("pwd","abc111");
//将K-V存储到文件中
properties.store(new FileOutputStream("src\\file\\mysql02.properties"),"hello,world");
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值