Java学习-第一部分-第二阶段-第八节:IO流

IO流

笔记目录:(https://www.cnblogs.com/wenjie2000/p/16378441.html)

IO流体系图

image

文件

什么是文件

文件.对我们并不陌生,文件是保存数据的地方,比如大家经常使用的word文档,txt文件.excel文件...都是文件。它既可以保存一张图片,也可以保持视频,声音.…

文件流-File()

文件在程序中是以流的形式来操作的

image

流:数据在数据源(文件)和程序(内存)之间经历的路径

输入流:数据从数据源(文件)到程序(内存)的路径

输出流:数据从程序(内存)到数据源(文件)的路径

创建文件对象相关构造器和方法

相关方法

new File(String pathname)//根据路径构建一个File对象

new File(File parent,String child)//根据父目录文件+子路径构建

new File(String parent,String child)//根据父目录+子路径构建

createNewFile 创建新文件

创建文件对象相关构造器和方法

应用案例演示FileCreate.java

请在D盘下,创建文件news1.txt、news2.txt、news3.txt,用三种不同方式创建

//方式1 new File(String pathname)
public void create01() {
    String filePath = "d:\\news1.txt";
    File file = new File(filePath);
    try {
        file.createNewFile();
        System.out.println("文件创建成功");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

//方式2 new File(File parent , String child)//根据父目录文件+子路径构建
// d:\\news2.txt
public void create02() {
    File parentFile = new File("d:\\");
    String fileName = "news2.txt";
    //这里的file对象,在java程序中,只是一个对象
    //只有执行了createNewFile 方法,才会真正的,在磁盘创建该文件
    File file = new File(parentFile, fileName);
    try {
        file.createNewFile();
        System.out.println("创建成功~");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

//方式3 new File(String parent , String child)
// 根据父目录+子路径构建
public void creat03() {
    // String parentPath = "D:\\";
    String parentPath = "D:/";//两种路径方式都行
    String fileName = "news4.txt";
    File file = new File(parentPath, fileName);
    try {
        file.createNewFile();
        System.out.println("创建成功~");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

获取文件的相关信息

getName、getAbsolutePath、getParent、length、exists、isFile、isDirectory

//先创建文件对象
File file = new File("D:\\NEW\\news1.txt");
try {
    file.createNewFile();
    System.out.println("文件创建成功");
} catch (IOException e) {
    e.printStackTrace();
}
//调用相应的方法,得到对应信息
System.out.println("文件名字=" + file.getName());
//getName、getAbsolutePath、getParent、length、exists、isFile、isDirectory
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删除空目录或文件

应用案例演示

  1. 判断d:\\news1.txt是否存在,如果存在就删除

    //判断 d:\\news1.txt是否存在,如果存在就删除
    String filePath = "d:\\news1.txt";
    File file = new File(filePath);
    if (file.exists()) {
        if (file.delete()) {//删除文件
            System.out.println(filePath + "删除成功");
        } else {
            System.out.println(filePath + "删除失败");
        }
    } else {
        System.out.println("该文件不存在...");
    }
    
  2. 判断D:\\demo02是否存在,存在就删除,否则提示不存在.

    //判断D:\\demo02是否存在,存在就删除,否则提示不存在.
    //这里我们需要体会到,在java编程中,目录也被当做一种特殊的文件
    String filePath = "d:\\demo02";
    File file = new File(filePath);
    if (file.exists()) {
        if (file.delete()) {//删除目录
            System.out.println(filePath + "删除成功");
        } else {
            System.out.println(filePath + "删除失败");
        }
    } else {
        System.out.println("该目录不存在...");
    }
    
  3. 判断D:\\demo\\a\\b\\c目录是否存在,如果存在就提示已经存在,否则就创建

    //判断D:\\demo\\a\\b\\c目录是否存在,如果存在就提示已经存在,否则就创建
    String filePath = "D:\\demo\\a\\b\\c";
    File file = new File(filePath);
    if (file.exists()) {
            System.out.println(filePath + "已存在");
    } else {
        if (file.mkdirs()){//创建一级目录使用mkdir(),创建多级目录使用mkdirs()
            System.out.println("目录创建成功");
        }else {
            System.out.println("目录创建失败");
        }
    }
    

IO流原理及流的分类

Java IO流原理

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

  2. Java程序中,对于数据的输入/输出操作以”流(stream)”的方式进行。

  3. java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过方法输入或输出数据

  4. 输入input:读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中。

  5. 输出output:将程序(内存)数据输出到磁盘、光盘等存储设备中

流的分类

√按操作数据单位不同分为:字节流(8 bit)二进制文件,字符流(按字符)文本文件

√按数据流的流向不同分为:输入流,输出流

√按流的角色的不同分为:节点流,处理流/包装流

(抽象基类) 字节流 字符流
输入流 lnputStream Reader
输出流 OutputStream Writer
  1. Java的lO流共涉及40多个类,实际上非常规则,都是从如上4个抽象基类派生的
  2. 由这四个类派生出来的子类名称都是以其父类名作为子类名后缀。

节点流和处理流

●基本介绍

  1. 节点流可以从一个特定的数据源读写数据,如FileReader、 FileWriter [源码]

  2. 处理流(也叫包装流)是“连接”在已存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能,如BufferedReader、BufferedWriter [源码]

img

节点流和处理流的区别和联系

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

处理流的功能主要体现在以下两个方面:

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

标准输入输出流

>介绍

编译类型 运行类型 默认设备
System.in标准输入 InputStream BufferedInputStream 键盘
System.out标准输出 PrintStream PrintStream 显示器

输入流

lnputStream

image

FilelnputStream

构造方法摘要
FileInputStream(File file)通过打开与实际文件的连接创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。
FileInputStream(FileDescriptor fdObj)创建 FileInputStream通过使用文件描述符 fdObj ,其表示在文件系统中的现有连接到一个实际的文件。
FileInputStream(String name)通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。
Modifier and Type 方法摘要 Method and Description
int available()返回从此输入流中可以读取(或跳过)的剩余字节数的估计值,而不会被下一次调用此输入流的方法阻塞。
void close()关闭此文件输入流并释放与流相关联的任何系统资源。
protected void finalize()确保当这个文件输入流的 close方法没有更多的引用时被调用。
FileChannel getChannel()返回与此文件输入流相关联的唯一的FileChannel对象。
FileDescriptor getFD()返回表示与此 FileInputStream正在使用的文件系统中实际文件的连接的 FileDescriptor对象。
int read()从该输入流读取一个字节的数据。
int read(byte[] b)从该输入流读取最多 b.length个字节的数据为字节数组。
int read(byte[] b, int off, int len)从该输入流读取最多 len字节的数据为字节数组。
long skip(long n)跳过并从输入流中丢弃 n字节的数据。

FilelnputStream应用实例

要求:请使用FilelnputStream 读取 hello.txt 文件,并将文件内容显示到控制台.

//单个字节读取,效率比较低

String filePath="d:\\hello.txt";
int readData=0;
FileInputStream fileInputStream=null;
try {
    //创建FileInputstream对象,用于读取文件
    fileInputStream=new FileInputStream(filePath);
    //从该输入流读取一个字节的数据。如果没有输入可用,此方法将阻止。
    // 如果返回-1,表示读取完毕
    while ((readData=fileInputStream.read())!=-1){
        System.out.print((char)readData);//转成char显示
    }
} catch (IOException e) {
    e.printStackTrace();
}finally {
    //关闭文件流释放资源
    try {
        fileInputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
//相对于上面代码,从read()改为read(byte[] b),一次读多个字节,效率提高

String filePath="d:\\hello.txt";
int readLen=0;
//字节数组
byte[] buf = new byte[8];//一次读取8个字节.
        FileInputStream fileInputStream=null;
try {
    //创建FileInputstream对象,用于读取文件
    fileInputStream=new FileInputStream(filePath);
    //从该输入流读取最多b.length字节的数据到字节数组。 此方法将阻塞,直到某些输入可用。
    //如果返回-1 ,表示读取宗华
    //如果读取正常,返回实际读取的字节数
    while ((readLen=fileInputStream.read(buf))!=-1){
        System.out.print(new String(buf,0,readLen));//转成char显示
    }
} catch (IOException e) {
    e.printStackTrace();
}finally {
    //关闭文件流释放资源
    try {
        fileInputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

BufferedInputStream

略,看BufferedOutputStream部分笔记

objectlnputStream

看一个需求

  1. 将int num = 100这个int数据保存到文件中,注意不是100数字,而是int 100,并且,能够从文件中直接恢复int 100
  2. 将Dog dog = new Dog(“小黄”,3)这个dog对象保存到文件中,并且能够从文件恢复.
  3. 上面的要求,就是能够将基本数据类型或者对象进行序列化和反序列化操作

序列化和反序列化

  1. 序列化就是在保存数据时,保存数据的值和数据类型

  2. 反序列化就是在恢复数据时,恢复数据的值和数据类型

  3. 需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的该类必须实现如下两个接口之一:

    >Serializable //这是一个标记接口,没有方法 (推荐使用)

    >Externalizable //该接口有方法需要实现,因此我们一般实现上面的 Serializable接口

基本介绍

  1. 功能:提供了对基本类型或对象类型的序列化和反序列化的方法
  2. ObjectOutputStream提供序列化功能
  3. ObjectlnputStream提供反序列化功能

应用案例

  1. 使用ObjectlnputStream 读取 data.dat并反序列化恢复数据 (如果需要data.dat,可运行下方ObjectOutputStream部分的应用案例1的代码)

    public class Test {
        public static void main(String[] args) throws IOException, ClassNotFoundException {
            //指定反序列化的文件
            String filePath = "d:\\data.dat";
    
            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());
    
            //dog的编译类型是 Object , dog的运行类型是Dog
            Object dog = ois.readObject();
            System.out.println("运行类型=" + dog.getClass());
            System.out.println("dog信息=" + dog);//底层 Object -> Dog
            //这里是特别重要的细节:
            //1.如果我们希望调用Dog的方法,需要向下转型
            //2.需要我们将Dog类的定义,放到可以引用的位置(Dog类保存和读取文件时该类的位置必须一致)
            Dog dog2 = (Dog) dog;
            System.out.println(dog2.getName());//旺财..
            //关闭流,关闭外层流即可,底层会关闭 FileInputStream 流
            ois.close();
        }
    }
    
    class Dog implements Serializable {
        private String name;
        private int age;
    
        public Dog(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public int getAge() {
            return age;
        }
    
        @Override
        public String toString() {
            return "Dog{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    

注意事项和细节说明

  1. 读写顺序要一致
  2. 要求序列化或反序列化对象,需要实现Serializable
  3. 序列化的类中建议添加SerialVersionUID,为了提高版本的兼容性(private static final long erialVersionUID = 1L;//当类发生修改后会序列化与反序列化被认定是类的版本修改,而不会认为是一个新的类)
  4. 序列化对象时,默认将里面所有属性都进行序列化,但除了static或transient修饰的成员
  5. 序列化对象时,要求里面属性的类型也需要实现序列化接口
  6. 序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也已经默认实现了序列化

Reader

FileReader

image

FileReader相关方法:

  1. new FileReader(File/String)
  2. read:每次读取单个字符,返回该字符,如果到文件末尾返回-1
  3. read(char[]):批量读取多个字符到数组,返回读取到的字符数,如果到文件末尾返回-1

相关API:

  1. new String(char[]):将char[]转换成String
  2. new String(char[],off,len):将char[]的指定部分转换成String

应用案例

要求:

  1. 使用FileReader 从 story.txt 读取内容,并显示

    //使用read()
    String filePath="d:\\NEW\\story.txt";
    FileReader fileReader=null;
    int data=0;
    try {
        fileReader=new FileReader(filePath);
        while ((data=fileReader.read())!=-1){
            System.out.print((char)data);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            fileReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    //使用read(char[])
    String filePath="d:\\NEW\\story.txt";
    FileReader fileReader=null;
    char[] buf=new char[8];
    int len=0;
    try {
        fileReader=new FileReader(filePath);
        while ((len=fileReader.read(buf))!=-1){
            System.out.print(new String(buf,0,len));
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            fileReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

BufferedReader

应用案例

  1. 使用BufferedReader读取文本文件,并显示在控制台
public static void main(String[] args) throws IOException {
    String filePath = "D:\\a.txt";
    //创建bufferedReader
    BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
    //读取
    String line;//按行读取,效率高
    // 说明
    //1. bufferedReader.readLine()是按行读取文件
    //2. 当返回null时,表示文件读取完毕
    while ((line = bufferedReader.readLine()) != null) {
        System.out.println(line);
    }
    //关闭流,这里注意,只需要关闭BufferedReader ,因为底层会自动的去关闭节点流FileReader
    bufferedReader.close();
}

InputStreamReader

先看一个文件乱码问题,引出学习转换流必要性

//读取e: l\a.txt文件到程序//思路
//1。创建字符输入流 BufferedReader[处理流]
//2。使用 BufferedReader对象读取a.txt
//3。默认情况下,读取文件是按照utf-8编码
//如果文件使用的其他编码方式很可能出现乱码 例如读取到的内容:Hhello,worldba����涨��
String filePath = "d:\\a.txt";
BufferedReader br = new BufferedReader(new FileReader(filePath));
String s = br.readLine();
System.out.println("读取到的内容:" + s);
br.close();

介绍

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

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

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

应用案例

  1. 编程将字节流FilelnputStream 包装成(转换成)字符流InputStreamReader,对文件进行读取(按照utf-8/gbk格式),进而再包装成BufferedReader

    public static void main(String[] args) throws IOException {
        //演示使用InputStreamReader转换流解决中文乱码问题
        //将字节流FileInputStream转成字符流InputStreamReader,指定编码 gbk/utf-8
        String filePath = "D:\\a.txt";//解读
        //1。把FileInputStream转成InputStreamReader
        //2。指定编码gbk
        InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath), "gbk");
        //3。把InputStreamReader传入 BufferedReader
        BufferedReader br = new BufferedReader(isr);
        //4。读取
        String s = br.readLine();
        System.out.println("读取内容=" + s);
        //5。关闭外层流
        br.close();
    }
    

输出流

OutputStream

FileOutputStream

构造方法摘要
FileOutputStream(File file)创建文件输出流以写入由指定的 File对象表示的文件。
FileOutputStream(File file, boolean append)创建文件输出流以写入由指定的 File对象表示的文件。
FileOutputStream(FileDescriptor fdObj)创建文件输出流以写入指定的文件描述符,表示与文件系统中实际文件的现有连接。
FileOutputStream(String name)创建文件输出流以指定的名称写入文件。
FileOutputStream(String name, boolean append)创建文件输出流以指定的名称写入文件。
Modifier and Type 方法摘要 Method and Description
void close()关闭此文件输出流并释放与此流相关联的任何系统资源。
protected void finalize()清理与文件的连接,并确保当没有更多的引用此流时,将调用此文件输出流的 close方法。
FileChannel getChannel()返回与此文件输出流相关联的唯一的FileChannel对象。
FileDescriptor getFD()返回与此流相关联的文件描述符。
void write(byte[] b)b.length个字节从指定的字节数组写入此文件输出流。
void write(byte[] b, int off, int len)len字节从位于偏移量 off的指定字节数组写入此文件输出流。
void write(int b)将指定的字节写入此文件输出流。

FileOutputStream应用实例1

要求:请使用FileOutputStream在a.txt文件,中写入“hello, world”.

[代码演示],如果文件不存在,会创建文件(注意:前提是目录已经存在.)

//创建FileOutPutStream对象
String filePath="D:\\a.txt";
FileOutputStream fileOutputStream=null;

try {
    //1. new FileOutputStream(filePath)创建方式,当写入内容是,会覆盖原来的文件内容
    //2. new FileOutputStream(filePath,true)创建方式,当写入内容是,是追加到文件后面
    fileOutputStream=new FileOutputStream(filePath);
    //写入一个字节
    fileOutputStream.write('H');
    //写入字符串
    String str="hello,world";
    //str.getBytes()可以把字符串->字节数组
    fileOutputStream.write(str.getBytes());
    //write(byte[] b, int off, int len) 将 `len`字节从位于偏移量 `off`的指定字节数组写入此文件输出流。
    fileOutputStream.write("aba".getBytes(),1,2);

} catch (IOException e) {
    e.printStackTrace();
}finally {
    try {
        fileOutputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

FileOutputStream应用实例2

要求:编程完成图片/音乐的拷贝.

FileInputStream fileInputStream=null;
FileOutputStream fileOutputStream=null;

String filepath1="d:\\(1).png";
String filepath2="d:\\NEW\\(1).png";

try {
    fileInputStream=new FileInputStream(filepath1);
    fileOutputStream=new FileOutputStream(filepath2,true);
    byte[] bytes = new byte[1000];
    while (fileInputStream.read(bytes)!=-1){
        fileOutputStream.write(bytes);
    }
} catch (IOException e) {
    e.printStackTrace();
}finally {
    try {
        fileInputStream.close();
        fileOutputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

BufferedOutputStream

应用案例

要求:编程完成图片/音乐的拷贝(要求使用Buffered..流).[代码演示]

//可以完成二进制文件拷贝
int stringLine;
String filePath1 = "D:\\(1).png";
String filePath2 = "D:\\(2).png";
BufferedInputStream bufferedInputStream=null;
BufferedOutputStream bufferedOutputStream=null;
try {
    bufferedInputStream = new BufferedInputStream(new FileInputStream(filePath1));
    bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(filePath2,true));
    byte[] bytes = new byte[1024];
    while ((stringLine=bufferedInputStream.read(bytes))!=-1){
        bufferedOutputStream.write(bytes,0,stringLine);
    }
} catch (IOException e) {
    e.printStackTrace();
} finally {
    try {
        bufferedInputStream.close();
        bufferedOutputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

objectOutputStream

基本介绍看笔记上方objectlnputStream部分

应用案例

  1. 使用ObjectOutputStream序列化基本数据类型和一个 Dog对象(name, age),并保存到data.dat文件中

    public class Test {
        public static void main(String[] args) throws IOException{
            //序列化后,保存的文件格式,不是存文本,而是按照他的格式来保存
            String filePath = "d:\\data.dat" ;
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
            //序列化数据到 e:\data.dat
            oos.writeInt(100);// int -> Integer(实现了Serializable)
            oos.writeBoolean(true) ;// boolean -> Boolean(实现了 Serializable)
            oos.writeChar('a');// char -> Character〔实现了Serializable)
            oos.writeDouble(9.5);// double -> Double (实现了Serializable)
            oos.writeUTF("hello,worldd一二三");//String
            //保存一个dog对象
            oos.writeObject(new Dog("旺财",10));
            
            oos.close();
            System.out.println("数据保存完毕(序列化形式)");
        }
    }
    class Dog implements Serializable {
        private String name;
        private int age;
    
        public Dog(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public int getAge() {
            return age;
        }
    
        @Override
        public String toString() {
            return "Dog{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    

PrintStream

打印流只有输出流,没有输入流

public static void main(String[] args) throws IOException {
    PrintStream out = System.out;
    //在默认情况下,PrintStream输出数据的位置是标准输出,即显示器
    /*
    public void print(String s) {
        if (s == null){
            s = "null";}
        write(s);
    }
    */
    out.print("john,hello");
    //因为print底层使用的是write,所以我们可以直接调用write进行打印/输出
    out.write("你好".getBytes());
    out.close();

    //我们可以去修改打印流输出的位置/设备//修改成到"d:\\f1.txt")
    //public static void setOut(PrintStream out) {
    //    checkIO();
    //    setOut0(out);// native方法,修改了out
    //}
    System.setOut(new PrintStream("d:\\f1.txt"));
    System.out.println("hello,world");
}

Writer

image

Writer下的所有类都是调用close()后才会将数据写入到文件

FileWriter

FileWriter常用方法

  1. new FileWriter(FiIe/String):覆盖模式,相当于流的指针在首端
  2. new FileWriter(File/String,true):追加模式,相当于流的指针在尾端
  3. write(int):写入单个字符
  4. write(char[]):写入指定数组
  5. write(char[],off,len):写入指定数组的指定部分
  6. write (string):写入整个字符串
  7. write(string,off,len):写入字符串的指定部分

相关API:String类:toCharArray将String转换成char[]

注意:

FileWriter使用后,必须要关闭(close)或刷新(flush),否则写入不到指定的文件!

案例

//创建FileOutPutStream对象
String filePath="D:\\a.txt";
FileWriter fileWriter=null;

try {
    fileWriter=new FileWriter(filePath);
    //1) write(int):写入单个字符
    fileWriter.write('H');
    //2) write(char[]):写入指定数组
    char[] chars={'a','b','c','v'};
    fileWriter.write(chars);
    //3) write(char[],off,len):写入指定数组的指定部分
    fileWriter.write(chars,1,3);
    //4) write (string):写入整个字符串
    String str="hello,world";
    fileWriter.write(str);
    //5) write(string,off,len):写入字符串的指定部分
    fileWriter.write("aba",1,2);
} catch (IOException e) {
    e.printStackTrace();
}finally {
    //对应FileWriter ,一定要关闭流,或者flush才能真正的把数据写入到文件
    //看源码就知道原因。
    try {
        fileWriter.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

BufferedWriter

应用案例

  1. 使用BufferedWriter 将”hello”,写入到文件中

    public static void main(String[] args) throws IOException {
        String filePath = "D:\\b.txt";
        //创建bufferedWriter
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath,true));
        bufferedWriter.write("hello");
        bufferedWriter.newLine();//插入一个和系统相关的换行
        bufferedWriter.write("hello,发的发斯蒂芬改");
        bufferedWriter.write("hello");
    
        //关闭流,这里注意,只需要关闭BufferedReader ,因为底层会自动的去关闭节点流FileWrite
        bufferedWriter.close();
    }
    
  2. 综合使用BufferedReader 和 BufferedWriter完成文本文件拷贝,注意文件编码

    //1.BufferedReader和 BufferedWriter是安装字符操作
    //2.不要去操作二进制文件,可能造成文件损坏
    String stringLine;
    String filePath1 = "D:\\b.txt";
    String filePath2 = "D:\\b2.txt";
    BufferedReader bufferedReader = null;
    BufferedWriter bufferedWriter = null;
    try {
        bufferedReader = new BufferedReader(new FileReader(filePath1));
        bufferedWriter = new BufferedWriter(new FileWriter(filePath2,true));
        while ((stringLine=bufferedReader.readLine())!=null){
            bufferedWriter.write(stringLine);
            bufferedWriter.newLine();
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            bufferedReader.close();
            bufferedWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

OutputStreamWriter

OutputStreamWriter:Writer的子类,实现将OutputStream(字节流)包装成Writer(字符流)

应用案例

  1. 编程将字节流 FileOutputStream包装成(转换成)字符流OutputStreamWriter,对文件进行写入(按照gbk格式,可以指定其他,比如utf-8)

    public static void main(String[] args) throws IOException {
        String filePath = "D:\\ab.txt";
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filePath), "utf-8");
        osw.write("hello一二三");
        //5.关闭外层流
        osw.close();//flush +关闭流,才会将数据写入到文件..
        System.out.println("文件保存成功");
    }
    

PrintWriter

public static void main(String[] args) throws IOException {
    //PrintWriter printWriter = new PrintWriter(System.out);//输出到显示器上
    PrintWriter printWriter = new PrintWriter(new FileWriter("d:\\f2.txt"));
    printWriter.print("hi,北京你好~~~~");
    printWriter.close();//flush +关闭流,才会将数据写入到文件..
}

Properties类

看一个需求

程序操作数据库,需要获取用户名和密码。不能将文件写死,就需要保存数据到配置文件。

如下一个配置文件mysql.properties

ip=192.168.0.13
user=root
pwd=12345

请问编程读取ip、user 和pwd的值是多少

√分析

  1. 传统的方法

    public static void main(String[] args) throws IOException {
        //读取mysql.properties 文件,并得到ip,user和 pwd
        BufferedReader br = new BufferedReader(new FileReader("src\\mysql.properties"));
        String line = "";
        while ((line = br.readLine()) != null) {//循环读取
            //比较麻烦
            String[] split = line.split("=");
            System.out.println(split[0] + "值是: " + split[1]);
        }
        br.close();
    }
    
  2. 使用Properties类可以方便实现

基本介绍

  1. 专门用于读写配置文件的集合类
    配置文件的格式:
    键=值
    键=值

  2. 注意:键值对不需要有空格,值不需要用引号一起来。默认类型是String

  3. Properties的常见方法

    load:加载配置文件的键值对到Properties对象

    list:将数据显示到指定设备/流对象

    getProperty(key):根据键获取值

    setProperty(key,value):设置键值对到Properties对象

    store:将Properties中的键值对存储到配置文件,在idea中,保存信息到配置文件,如果含有中文,会存储为unicode码

应用案例

  1. 使用Properties类完成对 mysql.properties的读取,看代码演示

    public static void main(String[] args) throws IOException {
        //使用Properties 类来读取mysql. properties 文件
        //1。创建Properties对象
        Properties properties = new Properties();//2。加载指定配置文件
        properties.load(new FileReader("src\\mysql.properties"));//3.把k-v显示控制台
        properties.list(System.out);//4。根据key 获取对应的值
        String user = properties.getProperty("user");
        String pwd = properties.getProperty("pwd");
        System.out.println("用户名=" + user);
        System.out.println("密码是=" + pwd);
    }
    
  2. 使用Properties类添加key-val 到新文件mysql2.properties中

    public static void main(String[] args) throws IOException {
        //使用Properties类来创建配置文件,修改配置文件内容
        Properties properties = new Properties();
        //创建
        properties.setProperty("charset", "utf8");
        properties.setProperty("user", "汤姆");//注意保存时,是中文的 unicode码值
        properties.setProperty("pwd" , "abc111");
    
        //将k-v存储文件中即可
        properties.store(new FileOutputStream("src\\mysql2.properties"), null);//其中null可换为字符串,为保存的properties文件的头部注释
        System.out.println("保存配置文件成功~");
    }
    
  3. 使用Properties类完成对 mysql.properties的读取,并修改某个key-val

    public static void main(String[] args) throws IOException {
        Properties properties = new Properties();
        properties.load(new FileReader("src\\mysql2.properties"));
        properties.setProperty("user","1111222");
        properties.store(new FileWriter("src\\mysql2.properties"),null);
    }
    
posted @ 2022-09-05 16:02  文杰2000  阅读(134)  评论(0编辑  收藏  举报