java-IO流学习

文件

文件是保存数据的地方

  • 文件流
    文件在程序中是以流的形式来操作
    流:数据在数据源(文件)和程序(内存)之间经历的路径
    输入流: 数据从数据源(文件)到程序(内存)的路径
    输出流:数据从程序(内存)到数据源(文件)的路径
    在这里插入图片描述

常用文件操作

  • 创建文件对象的相关构造器和方法
    new File(String pathname) //根据路径构建一个File对象
    new File(File parent,String child)//根据父目录文件+子路径构建
    new File(String parent,String child) //根据父目录+子路径构建

    public class CreateNewFile {
    public static void main(String[] args) throws IOException {
        File file = new File("D:\\个人数据\\text.txt");
        File fileP = new File("D:\\个人数据");
        File file1 = new File(fileP,"\\text.txt");
        File file2 = new File("D:\\个人数据","\\text.txt");
    
        //创建文件方法: createNewFile()
        if (file.createNewFile()){
            System.out.println("文件创建成功");
            if (file.delete()){
                System.out.println("文件删除成功");
            }
        }
    }
    

构造File对象时,既可以传入绝对路径,也可以传入相对路径。绝对路径是以根目录开头的完整路径,如:

    // 假设当前目录是C:\Docs
    File f1 = new File("sub\\javac"); // 绝对路径是C:\Docs\sub\javac
    //可以用.表示当前目录,..表示上级目录
    File f3 = new File(".\\sub\\javac"); // 绝对路径是C:\Docs\sub\javac
    File f3 = new File("..\\sub\\javac"); // 绝对路径是C:\sub\javac
  • 获取文件信息

    //先创建文件对象
    File file = new File("e:\\news1.txt");
    //调用相应的方法,得到对应信息
    System.out.println("文件名字= "+ file.getName());
    System.out.println("文件绝对路径="+ file.getAbsolutePath());
    System.out.println("文件父级目录=" + file.getParent());
    System.out.println("文件大小(字节)=" + file.Length());
    System.out.println("文件是否存在=" + file.exists());//T
    System.out.println("是不是一个文件=" + file.isFile());//T
    System.out.println("是不是一个目录=" + file.isDirectory());//F
    
  • 文件目录操作
    mkdir创建一级目录、mkdirs创建多级目录、delete删除空目录或文件

    File file = new File("e:\\demo");
    File file2 = new File("e:\\demo\\a\\b");
    
    file.mkdir();//创建一级目录
    file2.mkdirs();//创建多级目录
    file.delete();
    

IO流原理及 流的分类

  • l/O是Input/Output的缩写l/O技术是非常实用的技术,用于处理数据传输如读/写文件,网络通讯等。

  • Java程序中,对于数据的输入/输出操作以”流(stream)” 的方式进行; java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过方法输入或输出数据

  • 流的分类
    操作数据单位不同分为: 字节流(8 bit) 二进制文件,字符流(按字符)文本文件
    数据流的流向不同分为:输入流,输出流
    流的角色的不同分为:节点流,处理流/包装流
    在这里插入图片描述

文件字节流

  • InputStream/OutputStream
    OutputStream提供了一个flush()方法,它的目的是将缓冲区的内容真正输出到目的地。向磁盘、网络写入数据的时候,出于效率的考虑,操作系统并不是输出一个字节就立刻写入到文件或者发送到网络,而是把输出的字节先放到内存的一个缓冲区里(本质上就是一个byte[]数组),等到缓冲区写满了,再一次性写入文件或者网络。对于很多IO设备来说,一次写一个字节和一次写1000个字节,花费的时间几乎是完全一样的,所以OutputStream有个flush()方法,能强制把缓冲区内容输出。

    在这里插入图片描述

FileInputStream/FileOutputStream

	    public static void main(String[] args) throws IOException {
        String filePath = "d:\\xxx.txt";

        //new FileOutputStream(filePath) 写入方式 会覆盖文件之前内容,如果文件不存在,FileOutputStream会创建文件
        //FileOutputStream fileOutputStream = new FileOutputStream(filePath);

        //new FileOutputStream(filePath,true) 写入方式 不会覆盖文件之前内容,追加到文件末尾
        FileOutputStream fileOutputStream = new FileOutputStream(filePath,true);
        String str = "wow";

        fileOutputStream.write(str.getBytes());

        int readDate;
        FileInputStream fileInputStream = new FileInputStream(filePath);

        //读取文件
        //fileInputStream.read()方法从该输入流读取一个字节的(ASCII)数据。如果没有输入可用,此方法将阻止。如果返回-1 ,表示读取完毕
        while ((readDate = fileInputStream.read()) != -1){
            System.out.print((char) readDate);
        }
        
        //释放资源
        fileInputStream.close();
        fileOutputStream.close();
    }

文件拷贝

        //文件拷贝
        //读取文件--指定位置写入文件
        String path = "D:\\wow.txt";//原目录
        String desPath = "D:\\demo\\wow.txt";//目标目录

        FileInputStream fileInputStream = new FileInputStream(path);
        FileOutputStream fileOutputStream = new FileOutputStream(desPath);

        byte[] bytes = new byte[1024];
        int bytesLen = 0;
        //读取文件数据
        while ((bytesLen = fileInputStream.read(bytes)) !=-1){
            //写入文件数据
            fileOutputStream.write(bytes,0,bytesLen);
        }

        //关闭资源
        fileInputStream.close();
        fileOutputStream.close();

文件字符流FileReader/FileWriter

  • FileReader相关方法

    1. new FileReader(File/String)
    2. read:每次读取单个字符,返回该字符,如果到文件未尾返回-1
    3. read(char): 批量读取多个字符到数组,返回读取到的字符数,如果到文件未尾返回-1
      相关API:
    4. new String(char[):将char[]转换成String
    5. new String(char[l],off;len):将charl]的指定部分转换成String
  • FileWriter
    1)new FileWriter(File/String): 覆盖模式,相当于流的指针在首端
    2)new FileWriter(File/String,true): 追加模式,相当于流的指针在尾端
    3)write(int):写入单个字符
    4)write(charl]):写入指定数组
    5)write(charll,off,len):写入指定数组的指定部分
    6)write (string):写入整个字符串
    7)write(string,offlen):写入字符串的指定部分
    相关API: String类: toCharArray:将String转换成char[]
    注意:
    FileWriter使用后,必须要关闭(close)或刷新(flush),否则写入不到指定的文件!

    
        //文件字符流操作
        String path = "d:\\wow.txt";
    
        FileReader fileReader = new FileReader(path);
        FileWriter fileWriter = new FileWriter(path);
    
        //写入
        fileWriter.write("哈哈我哈");
        fileWriter.flush();
    
        //单个字符读取
        /*int data;
        while ((data = fileReader.read()) != -1){
            System.out.println((char) data);
        }*/
    
        //多个字符读取
        char[] chars = new char[2];
        int dataLen;
        while ((dataLen = fileReader.read(chars)) != -1){
            System.out.println(new String(chars,0,dataLen));
        }
        
        fileReader.close();
        fileWriter.close();
    

节点流和处理流

1.节点流可以从一个特定的数据源读写数据 ,如FileReader、FileWriter
2.处理流(也叫包装流)是“连接”在已存在的流(节点流或处理流之上,为程序提供
更为强大的读写功能,如BufferedReader、BufferedWriter

在这里插入图片描述

BufferedReader一般读取文本文件

	
	        String filePath = "D:\\wow.txt";
	
	        /*演示BufferedReader*/
	        BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
	        //读取
	        //bufferedReader.readLine();//按行读取文件,当返回null时,表示读取完毕
	        String line;
	        while ((line=bufferedReader.readLine()) != null) {
	            System.out.println(line);
	        }
	
	        //关闭流
	        bufferedReader.close();

演示BufferedWriter

	BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath,true));
	
	        bufferedWriter.write("hello");
	        bufferedWriter.newLine();//换行
	        bufferedWriter.write("hello2");
	        bufferedWriter.write("hello3");
	        
	        bufferedWriter.close();

BufferedInputStream、BufferedOutputStream(字节)

	        /*演示BufferedInputStream、BufferedOutputStream*/
	        String srcFiletPath = "C:\\Users\\x'l'f\\Pictures\\Saved Pictures\\壁纸库\\child_river_dreams.jpg";
	        String desFiletPath = "D:\\xxx.jpg";
	
	        BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(srcFiletPath));
	        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(desFiletPath));
	
	        byte[] bytes = new byte[1024];
	        int readLen = 0;
	        while ((readLen = bufferedInputStream.read(bytes)) != -1){
	            bufferedOutputStream.write(bytes,0,readLen);
	        }
	
	        bufferedInputStream.close();
	        bufferedOutputStream.close();
	

ObjectInputStream、ObjectOutputStream(对象流,提供序列化和反序列化)

  • 序列化和反序列化
    序列化:就是在保存数据时,保存数据的值和数据类型
    反序列化:就是在恢复数据时,恢复数据的值和数据类型
    需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一:

    Serializable // 这是一个标记接口
    Externalizable

    public static void main(String[] args) throws Exception {

        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filePath));
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(filePath));

        //序列化数据保存到文件
        objectOutputStream.write(100);
        objectOutputStream.writeBoolean(true);
        objectOutputStream.writeUTF("哈哈哈哈");

        //保存对象
        objectOutputStream.writeObject(new Dog("旺旺",3));

        //反序列化-读取顺序和写入一致,不一致会报错
        System.out.println(objectInputStream.read());
        System.out.println(objectInputStream.readBoolean());
        System.out.println(objectInputStream.readUTF());
        System.out.println(objectInputStream.readObject().toString());

        objectOutputStream.close();
        objectInputStream.close();
}
//实现Serializable接口,标记该类可序列化
class Dog implements Serializable{...}

注意事项和细节说明
1)读写顺序要一致。
2)要求实现序列化或反序列化对象 ,需要实现 Serializable。
3)序列化的类中建议添加SerialVersionUID.为了提高版本的兼容性。

private static final long serialVersionUID = 1L;

4)序列化对象时,默认将里面所有属性都进行序列化,但除了static或transient修饰的成员。
5)序列化对象时,要求里面属性的类型也需要实现序列化接口。
6)序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也已经默认实现了序列化。

System.in 、System.out(标准输入输出流)

  • System.in 标准输入流:编译类型是InputStream,运行类型是BufferedInputStream,标准输入设备是键盘

  • OutputStream 标准输出流:编译类型是PrintStream,运行类型也是PrintStream,标准输出设备是显示器

InPutStreamReader、OutputStreamWriter(转换流)可以处理因数据编码不同时产生乱码问题

  • InputStreamReader:Reader的子类,可以将InputStream(字节流)包装成(转换)Reader(字符流);

  • OutputStreamWriter:Writer的子类,实现将OutputStream(字节流包装成Writer(字符流);
    在这里插入图片描述

  • 当处理纯文本数据时,如果使用字符流效率更高,并且可以有效解决中文问题,所以建议将字节流转换成字符流;

  • 可以在使用时指定编码格式(比如 utf-8,gbk,gb2312,ISO8859-1 等)

    //字节流、字符流转换
            //1.FileInputStream转换为InputStreamReader(字节流-->转换流)
            InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath),"UTF-8");//UTF-8传入不同charset
            //2.InputStreamReader传入BufferedReader(转换流-->字符流)
            BufferedReader br = new BufferedReader(isr);
    
            System.out.println(br.readLine());
            br.close();
    

PrintStream、PrintWiter(打印流)

  • 打印只有输出流,没有输入流
        //字节打印流PrintStream,默认情况下输出数据的位置是标准输出(显示器),可以进行修改
        PrintStream out = System.out;
        out.println("QAQ");
        //print底层是write,所以可以直接调用write进行打印/输出
        out.write("0.o".getBytes());

        out.close();

        //修改打印输出位置到文件filePath位置
        System.setOut(new PrintStream(filePath));
        System.out.println("o.0,0.o");//此时将输出到文件

//字符打印流PrintWrite
        PrintWriter pr = new PrintWriter(System.out);//输出到屏幕
        PrintWriter pr2 = new PrintWriter(new FileWriter(filePath));//输出到文件

        pr.close();
        pr2.close();

配置文件properties类

  • 专门用于读写配置文件的集合类

  • 配置文件的格式是键值对( 键=值),键值对不需要有空格,值不需要引号。默认类型是String

    Properties的常见方法
    load: 加载配置文件的键值对到Properties对象
    list:将数据显示到指定设备
    getProperty(key):根据键获取值
    setProperty(key;value):设置键值对到Properties对象
    store:将Properties中的键值对存储到配置文件,在idea 中,保存信息到配置文件,如果含有中文,会存储为unicode码

//创建Properties对象
        Properties ppt = new Properties();
        //加载配置文件
        ppt.load(new FileReader("src\\main\\resources\\test.properties"));
        //显示
        ppt.list(System.out);


        //写入数据到properties文件
        //创建 k-v,如果k存在则是修改值
        ppt.setProperty("user","Tom");
        ppt.setProperty("user2","舟山");
        //保存数据,如果文件存在就是修改,不存在会创建新文件写入,comments内容为注释
        ppt.store(Files.newOutputStream(Paths.get("src\\main\\resources\\test.properties")),null);
        System.out.println("保存配置成功");

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值