首页 > 编程语言 >JAVA IO流-小白版

JAVA IO流-小白版

时间:2024-08-22 21:17:17浏览次数:9  
标签:JAVA String java 白版 IO import new public 读取

I/O流原理

  1. I/O 是 Input / Output 的缩写,I / O 流技术是非常实用的技术,用于处理数据传输。如读/写文件,网络通讯等;
  2. Java中对于数据的输入/输出操作以"流(stream)"的方式进行;
  3. Java.io 包下提供了各种"流"类和接口,用以获取不同种类的数据,并通过方法输入或输出数据;
  4. 输入input:读取外部数据(如磁盘数据)到程序(内存)中;
  5. 输出output:将程序(内存)数据输出到磁盘、光盘等存储设备中。

流的分类

  1. 按操作数据单位不同分为:字节流(8 bit)二进制文件,字符流(按字符)文本文件;
  2. 按数据流的流向不同分为:输入流,输出流;
  3. 按流的角色的不同分为:字节流,处理流/包装流。
    | 抽象基类 | 字节流 | 字符流 |
    | :------: | :----------: | :----: |
    | 输入流 | InputStream | Reader |
    | 输出流 | OutputStream | Writer |
  • java的IO流共涉及40多个类,实际上非常规则,都是从上面四个抽象基类派生的;
  • 以这四个派生出来的子类都以父类名作为子类名的后缀。(如FileInputStream、ObjectOutputStream、BufferedReader、StringWriter等)

InputStream:字节输入流

InputSteam抽象类是所有字节输入流类的父类(超类、基类)。

InputStream类常用的子类

  1. FileInputStream:文件输入流
  2. BufferedInputSream:缓冲字节输入流
  3. ObjectInputStream:对象字节输入流
    FileInputStream例题1:
    使用FileInputStream读取hello.test文件,并将文件内容显示到控制台
package IOStream.InputStream;
import java.io.FileInputStream;
import java.io.IOException;

/**
 * @author yeye
 * @desc FileInputStream的使用(字节输入流  文件--->程序)
 * @date 2024/8/20 16:57
 */
public class FileInputStream_ {
    public static void main(String[] args) {
        FileInputStream_ fileInputStream = new FileInputStream_();
        fileInputStream.readFile01();
        fileInputStream.readFile02();
    }

    /**
     * 单个字节的读取,概率比较低
     * */
    public void readFile01() {
        String filePath = "C:\\app\\hello.txt";
        int readDate = 0;
        FileInputStream fileInputStream = null;
        try {
            // 创建FileInputStream对象,用于读取文件
            fileInputStream = new FileInputStream(filePath);
            //从该输入流读取一个字节的数据,如果没有输入可以,此方法将阻止。

            //返回读取的字节数,如果到达文件末尾,则返回-1
            while ((readDate = fileInputStream.read())!= -1) { // 读取文件内容
                System.out.print((char) readDate);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            //关闭文件流,释放资源
            try {
                fileInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 使用read(byte[] b)方法,一次性读取多个字节,提高效率
     */
    public void readFile02() {
        String filePath = "C:\\app\\hello.txt";
        int readLen = 0;
        //字节数组,用于存储读取的文件内容
        byte[] buffer = new byte[4]; //一次性读取4个字节
        FileInputStream fileInputStream = null;
        try {
            // 创建FileInputStream对象,用于读取文件
            fileInputStream = new FileInputStream(filePath);
            //从该输入流最多读b.length个字节,将读取的内容存储在b数组中,返回实际读取的字节数。

            //如果读取的字节数小于b.length,说明到达了文件末尾
            //如果返回值为-1,则说明读取完毕
            //如果读取正常,返回实际读取的字节数
            while ((readLen = fileInputStream.read(buffer))!= -1) { // 读取文件内容
                System.out.print(new String(buffer, 0, readLen));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            //关闭文件流,释放资源
            try {
                fileInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

OutputStream类

FileOutputStream例题1:
使用FileOutputStream在test.txt文件中写入"hello,world",如果文件不存在,则会创建文件

package IOStream.OutputStream;

import java.io.FileOutputStream;
import java.io.IOException;

public class FileOutPutStream01 {
    public static void main(String[] args) {
        FileOutPutStream01 fil = new FileOutPutStream01();
        fil.writeFile();
    }
    /**
     * 使用FileOutputStream将数据写入文件
     * 如果文件不存在,则创建该文件
     */
    public void writeFile(){
        // 创建FileOutputStream对象
        String filePath = "E:/test.txt";
        FileOutputStream fileOutPutStream = null;

        try {
            //得到FileOutputStream对象
            //1.new FileOutputStream(filePath)创建方式,会覆盖原文件
            //2.new FileOutputStream(filePath,true)创建方式,不会覆盖原文件,在文件末尾追加内容
            fileOutPutStream = new FileOutputStream(filePath);
            //写入一个字节
            fileOutPutStream.write('a');
            //写入一个字符串
            String str = "hello world";
            //str.getBytes();可以把字符串转换为字节数组
            //fileOutPutStream.write(str.getBytes());
            //write(byte[] b, int off, int len)方法,可以指定写入的起始位置和长度
            fileOutPutStream.write(str.getBytes(), 0, 5);

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

FileOutputStream例题2
编程完成图片/音乐的拷贝

package IOStream.OutputStream;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * @author yeye
 * @desc
 * @date 2024/8/20 19:10
 */
public class FileCopy {
    public static void main(String[] args) {
        //完成文件拷贝,将e:\dog1.jpg文件拷贝到c:\dog.jpg
        /**
         * 1.创建文件的输入流,将文件读取的程序
         * 2.创建文件的输出流,将读取到的文件数据写入到指定的文件
         * 在完成程序时,应该是读取部分数据,就写入到值得文件,这里使用循环
         */
        //读取文件的路径
        String srcfilePath = "e:\\dog1.jpg";
        String destfilePath = "e:\\dog01.jpg";
        FileInputStream fileInputStream = null;
        FileOutputStream fileOutputStream = null;

        try {
            fileInputStream = new FileInputStream(srcfilePath);
            fileOutputStream = new FileOutputStream(destfilePath);
            //定义一个字节数组,提高读取效率
            byte[] buffer = new byte[1024];
            int ReadLen = 0;
            while ((ReadLen = fileInputStream.read(buffer))!= -1){
                //读取到数据后,就通过fileOutputStream写入到指定的文件
                fileOutputStream.write(buffer,0,ReadLen);
            }
            System.out.println("文件拷贝成功!");
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try{
                //关闭输入流和输出流,释放资源
                if(fileInputStream!= null){
                    fileInputStream.close();
                }
                if (fileOutputStream!= null){
                    fileOutputStream.close();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
}

Reader常用的类、Writer常用的类

FileReader和FileWriter

1.FileReader常用方法

  1. new FileReader(File/String)
  2. read():每次读取单个字符,返回该字符,如果文件末尾,返回-1
  3. read(char []):批量读取多个字符到数组,返回读取到的字符数,如果到文件末尾返回-1
    相关API:
  • new String ( char [] ) : 将char转换成String
  • new String ( char [] ,off,len) : 将char [ ] 值得的部分转换成String

3.FileReader应用案例

要求:1.使用FileReader从story.txt读取内容并显示

package IOStream.Reader;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

/**
 * @author yeye
 * @desc
 * @date 2024/8/20 22:30
 */
public class FileReader01 {
    public static void main(String[] args) {
        //方法1 --read()方法
        String filePath = "e:\\story.txt";
        FileReader fileReader = null;
        int date =' ';
        //创建FileReader对象
        try {
            fileReader = new FileReader(filePath);
            //读取文件内容--循环读取--使用read()方法,单个读取
            while((date = fileReader.read()) !=-1){
                System.out.print((char)date);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(fileReader!= null){
                try {
                    fileReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

//        //方法2 --read(buffer)方法
//        String filePath = "e:\\story.txt";
//        FileReader fileReader = null;
//        int ReadLen = 0;
//        char[]buffer = new char[8];
//        //创建FileReader对象
//        try {
//            fileReader = new FileReader(filePath);
//            //读取文件内容--循环读取--使用read(buffer)方法,批量读取
//            //返回的是实际读取到的字符数
//            //如果返回-1,表示已经读取到文件末尾
//            while((ReadLen = fileReader.read(buffer)) !=-1){
//                System.out.print(new String(buffer,0,ReadLen));
//            }
//
//        } catch (IOException e) {
//            e.printStackTrace();
//        }finally {
//            if(fileReader!= null){
//                try {
//                    fileReader.close();
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            }
//        }

    }
}

2.FileWriter常用方法:

  1. new FileWriter(File/String) : (对象/地址) 覆盖模式,每写一次都会覆盖之前的内容,相当流的指针在首端
  2. new FileWriter(File/String,true) : 追加模式,在原内容尾端输入内容,相当于指针在尾端
  3. writer(int) : 写入单个字符
  4. write(char [] ) : 写入指定数组
  5. write(char [],off,len) :写入指定数组的指定部分
  6. writer(String) : 写入整个字符串
  7. writer(String,off,len) : 写入字符串的指定部分
    相关API:String类 : toCharArray:将String类转换成char[]
    注:FileWriter在使用后,必须关闭(close)或者刷新(flush),否则写入不到指定文件。

3.FileWriter应用案例

要求:使用FileWriter将"你好,Java!"写入到note.txt文件中,

package IOStream.Writer;

import java.io.FileWriter;
import java.io.IOException;

/**
 * @author yeye
 * @desc
 * @date 2024/8/20 23:03
 */
public class FileWriter01 {
    public static void main(String[] args) {
    String filePath = "E:/test.txt";
    //创建一个FileWriter对象,用于写入文件
    FileWriter fileWriter = null;
    char [] buffer = {'h', 'e', 'l', 'l', 'o'};
        try {
            fileWriter = new FileWriter(filePath); //默认是覆盖写入
            //1. writer(int) : 写入单个字符
            fileWriter.write('a');
            //2. write(char [] ) : 写入指定数组
            fileWriter.write(buffer);
            //3. write(char [],off,len) :写入指定数组的指定部分
            fileWriter.write("椰椰在努力学Java".toCharArray(), 1, 9);
            //4. writer(String) : 写入整个字符串
            fileWriter.write("你好,Java!");
            //5. writer(String,off,len) : 写入字符串的指定部分
            fileWriter.write("你好,成都!", 0, 3);
            //在数据量大的情况下,可以使用循环操作


        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //对应FileWriter,一定要关闭(close),或者刷新(flush)才能正真把数据写入文件

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

节点流和处理流

节点流

节点流可以从一个特定的数据源(如文本、数组、字符串、管道等)读写数据,如FileReader、FileWriter、FileInputStream、FileOutputStream等
灵活性低

处理流

处理流也叫包装流,是"连接"在已存在的流(节点流或处理流)之上,为程序提供更为强大的功能,也更加灵活如BufferedReader、BufferedWriter.

public class BufferedReader extends Rander{
    private Reader in;
    private char cb[];
}
//BufferedReader类中,有属性Reader,即可以封装任何一个节点流,只要该节点流是Reader类的子类
public class BufferedWriter extends Writer{
    private Writer out;
    private char cb[];
}
//BufferedWriter类中,有属性Writer,即可以封装任何一个节点流,只要该节点流是Reader类的子类

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

  1. 节点流是底层流/低级流,直接跟数据源相连;
  2. 处理流(包装流)包装节点流,既可以消除不同节点流的实现差异,也可以提供更为方便的方法来完成输入输出。
  3. 处理流(包装流)对节点流进行包装,使用了修饰器设计模式,不会直接跟数据源相连
    处理流的功能主要体现在以下两个方面:
  4. 性能的提高:主要以增加缓存的方式来提高输入输出的效率;
  5. 操作的便捷:处理流可提供一系列便捷的方法来输入输出大批量的数据,使用起来更加的灵活。
    处理流大概实现如下:
//抽象父类
public abstract class Reader_ {
    public void readFile(){}
    public void readString(){}
}
//节点流————直接读取源文件
public class FileReader_  extends Reader_{
    public void readFile(){
        System.out.println("正在读取文件...");
    }
}
//节点流————直接读取字符串
public class StringReader_ extends Reader_ {
    public void readString(){
        System.out.println("正在读取字符串");
    }
}
//处理流(包装流)
public class BufferedReader_ extends Reader_ {
    private Reader_ reader_; //Reader_类型的reader_属性
    //接受Reader_子类对象
    public BufferedReader_(Reader_ reader_){
        this.reader_ = reader_;
    }
    //让方法更加灵活,多次读取文件,或者加缓冲char[]...
    public void readLines(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();
        }
    }
}
public class Test {
    public static void main(String[] args) {
        BufferedReader_ bufferedReader = new BufferedReader_(new FileReader_());
        bufferedReader.readLines(10);
        
        BufferedReader_ bufferedReader1 = new BufferedReader_(new StringReader_());
        bufferedReader1.readStrings(10);
    }
}

处理流—— BufferedReader和BufferedWriter

  1. BufferedReader和BufferedWriter属于字符流,是按照字符来读取数据的;
  2. 关闭处理流时,只需关闭外层流即可。
    例1:使用BufferedReader读取文本文件,并显示在控制台
package IOStream.Reader;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReader02 {
    public static void main(String[] args) throws IOException {

        String filePath ="E:/BufferedReader_.txt";
        // 创建BufferedReader对象
        BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
        // 读取文件内容
        String line ;//按行读取,效率高
        //bufferedReader.readLine()是按行读取
        //当返回null时,表示已经读取到文件末尾
        while((line = bufferedReader.readLine()) !=null){
            System.out.println(line);
        }
        // 关闭流,只需关闭外层流(BufferedReader)即可,因为底层会自动关闭节点流(FileReader)
        bufferedReader.close();
    }
}

例2:使用BufferedWriter 将"hello,JAVA"写入到文件中

package IOStream.Writer;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class BufferedWriter02 {
    public static void main(String[] args) throws IOException {

        String filePath = "E:\\test.txt";
        //创建BufferedWriter对象
        /**
         * new FileWriter(filePath)表示以覆盖的方式写入
         * new FileWriter(filePath,true)表示以追加的方式写入
         */
        BufferedWriter bufferedWriter02 = new BufferedWriter(new FileWriter(filePath,true));
        //写入数据
        bufferedWriter02.write("Hello JAVA!");
        //插入一个和系统相关的换行
        bufferedWriter02.newLine();
        bufferedWriter02.write("Hello 椰椰!");

        //关闭外层流(BufferedWriter)即可,传入的new FileWriter(filePath)会在底层关闭
        bufferedWriter02.close();
    }
}

例3:综合使用BufferedReader和BufferedWriter完成文本文件拷贝

package IOStream.Writer;

import java.io.*;

public class BufferedReader_BufferedWriter_01 {
    public static void main(String[] args) throws IOException {
        /**
         * BufferedReader和BufferedWriter是按照字符操作
         * 不要操作二进制文件,可能会造成文件损坏
         */
        String srcFilePath = "E:\\test.txt";
        String destFilePath = "E:\\test_copy.txt";
        //创建BufferedReader对象
        BufferedReader bufferedReader = new BufferedReader(new FileReader(srcFilePath));
        //创建BufferedWriter对象
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(destFilePath));
        //读取文件内容并写入到目标文件中
        String line;
        //readLine()方法读取一行内容,没有换行
        while ((line = bufferedReader.readLine())!= null){
            bufferedWriter.write(line);
            //插入一个换行
            bufferedWriter.newLine();
        }
       if(bufferedReader!=null){
           bufferedWriter.close();
       }
       if(bufferedWriter!=null){
           bufferedWriter.close();
       }
        System.out.println("文件拷贝成功!");
    }
}

处理流——BufferedInputStream和BufferedOutputStream

BufferedInputStream是字节流,在创建BufferedInputStream时,会创建一个内部缓冲数组
BufferedOutputStream是字节流,实现缓冲的输出流,可以将多个字节写入底层的输出流中,而不必对每次字节写入调用底层系统
例1:编程完成图片/音乐/文本文件的拷贝,(此处以图片为例,音乐/文本文件只需改变相应地址即可)

package IOStream.OutputStream;

import java.io.*;

public class BufferedInputStream_BufferedOutputStream_001 {
    public static void main(String[] args) throws IOException {

        String scrFilePath = "E:/dog01.jpg";
        String destFilePath = "E:/dog01_copy.jpg";
        //创建BufferedInputStream对象和BufferedOutputStream对象
        //FileInputStream是InputStream的子类,BufferedInputStream是FilterInputStream的子类
        BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(scrFilePath));
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(destFilePath));
        //循环读取文件,并写入到destFilePath中
        byte [] buffer = new byte[1024];
        int len = 0;
        //当返回值是-1时,表示文件已经读取完毕
        while((len = bufferedInputStream.read(buffer)) != -1){
            bufferedOutputStream.write(buffer,0,len);
        }

        System.out.println("文件拷贝成功!");
        //关闭流外层处理流,底层会关闭节点流
        if(bufferedInputStream !=null){
            bufferedInputStream.close();
        }
        if(bufferedOutputStream != null){
            bufferedOutputStream.close();
        }
    }
}

处理流——(对象流)———ObjectInputStream和ObjectOutputStream

看一个需求:

  1. 将int num = 100 这个 int 数据保存到文件中,注意不是 100 数字,而是 int 100,并且,能够从文件中直接恢复 int 100
  2. 将 Dog dog = new Dog(“小黄”, 3) 这个 dog对象 保存到 文件中,并且能够从文件恢复.上面的要求,就是 能够将 基本数据类型 或者 对象 进行 序列化 和 反序列化操作
功能:提供了对基本类型或对象类型的序列化和反序列化
  • ObjectOutputStream提供了 序列化功能
  • ObjectInputStream 提供了反序列化功能
注意事项:
  • 读写顺序要一致;
  • 实现序列化或反序列化,要实现Serializable;
  • 序列化的类建议添加SerialVersionUID,为了提高版本的兼容性;
  • 序列化对象时,默认将里面所有的属性都进行序列化,除了static、transient修饰的成员;
  • 序列化对象时,要求里面属性的类型也需要实现序列化接口;
  • 序列化具备可继承性,也就是某类已经实现了序列化,则它所有的子类也以及默认实现了序列化。

序列化和反序列化

  1. 序列化就是在保存数据时,保存数据的值和数据类型
  2. 反序列化就是在恢复数据时,恢复数据的值和数据类型
  3. 需要让某个对象支持序列化机制,就必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现以下两个接口之一:
    • Serializable //一个标记接口,没有方法,一般实现这个接口
    • Externalizable //该方法有方法需要实现
      例1:使用ObjectOutputStream 序列化基本数据类型和一个Dog对象(name,age),并保存到一个文件中。
package IOStream.OutputStream;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
 * @author yeye
 * @desc 使用ObjectOutputStream 完成数据的序列化
 * @date 2024/8/22 13:59
 */
public class ObjectOutputStream01 {
    public static void main(String[] args) throws IOException {
        //序列化后保存到文件格式,不是文本格式,而是按照它的格式保存
        String filePath = "E:/data.dat";
        //创建ObjectOutputStream对象
        ObjectOutputStream obj= new ObjectOutputStream(new FileOutputStream(filePath));

        //序列化数据到E/data.dat
        obj.writeInt(10); //int - >Integer (实现了Serializable接口)
        obj.writeBoolean(true); //boolean -> Boolean(实现了Serializable接口)
        obj.writeChar('a'); //char -> Character(实现了Serializable接口)
        obj.writeDouble(3.1415926); //double -> Double(实现了Serializable接口)
        obj.writeUTF("Hello 椰椰"); //String(实现了Serializable接口)
        //保存一个dog对象
        obj.writeObject(new Dog("小宝",3));
        //关闭流
        obj.close();
        System.out.println("序列化完成");
    }
}
//如果要序列化某个类的对象,该类必须实现Serializable接口
class Dog implements Serializable {
    private String name;
    private int age;

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

例2:使用ObjectInputStream读取data.dat并反序列化恢复数据。

package IOStream.InputStream;

import polymorphism.Dog;

import java.io.*;

/**
 * @author yeye
 * @desc 使用ObjectInputStream读取data.dat并反序列化恢复数据。
 * @date 2024/8/22 14:39
 */
public class ObjectInputStream01 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //指定反序列化文件
        String filePath = "E:/data.dat";
        //创建ObjectInputStream对象
        ObjectInputStream obj = new ObjectInputStream(new FileInputStream(filePath));

        //读取(反序列化)的顺序需要和写入(序列化)顺序保持一致,否则会出现异常
        System.out.println(obj.readInt());
        System.out.println(obj.readBoolean());
        System.out.println(obj.readChar());
        System.out.println(obj.readDouble());
        System.out.println(obj.readUTF());
        //dog编译类型是Dog,dog运行类型是Dog
        Object dog = obj.readObject();
        System.out.println("运行类型:" + dog.getClass());
        System.out.println("dog信息:" + dog); //底层Object - >Dog

        //如果我们希望调用dog的方法,就需要向下转型
        //需要我们将Dog类的定义,拷贝到可以引用的位置
    }
}

标准输入输出流

编译类型 运行类型 默认设备
System.in InputStream BufferedInputStream 键盘
System.out PrintStream PrintStream 显示器
代码展示:
package IOStream.Standard;
import java.util.Scanner;

/**
 * @author yeye
 * @desc
 * @date 2024/8/22 15:49
 */
public class InputAndOutput {
    public static void main(String[] args) {
        //System 类的public final static InputStream in = null;
        //编译类型:InputStream
        //运行类型:BufferedInputStream
        //表示标准输入,键盘
        System.out.println(System.in.getClass());

        //System 类的public final static PrintStream out属性;
        //编译类型:PrintStream
        //运行类型:PrintStream
        //表示标准输出,显示器
        System.out.println(System.out.getClass());

        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入内容:");
        String next = scanner.next();
        System.out.println("你输入的内容是:" + next);

    }
}
//运行结果:
class java.io.BufferedInputStream
class java.io.PrintStream
请输入内容:
nihao
你输入的内容是:nihao

转换流——InputStreamReader和OutputStreamWrider

transformation - 转型

  1. InputStreamReader:是Reader类的子类,可以将InputStream(字节流)包装/转换成Reader(包装流);
  2. OutputStreamWriter:是Writer类的子类,实现将OutputStream(字节流)包装/转换成Writer(包装流);
  3. 当处理纯文本数据时,如果使用字符流效率更高,并且可以有效解决中文问题,建议将字节流转换成字符流
  4. 可以在使用时指定编码格式(比如 utf-8、gbk、gb2312等)
    例1:将字节流 FileInputStream 包装/转换成 InputStreamReader,对文件进行读取(按照utf-8/gbk),进而再包装成BufferedReader
package transformation;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * @author yeye
 * @desc 使用InputStreamReader 转换流解决中文乱码问题
 *  将字节流FileInputStream转换为字符流InputStreamReader,并指定编码格式为UTF-8/GDK,即可解决中文乱码问题。
 * @date 2024/8/22 16:43
 */
public class InputStreamReader01 {
    public static void main(String[] args) throws IOException {

        String filePath = "E:/aaa.txt";
        //第一步:把new InputStreamReader 转成 InputStreamReader流,并指定编码格式为GBK
        InputStreamReader in1 = new InputStreamReader(new FileInputStream(filePath), "gbk");
        //第二步:把InputStreamReader 转成 BufferedReader流
        BufferedReader br = new BufferedReader(in1);

//        //将第一步和第二布流合并,一步到位
//        BufferedReader br = new BufferedReader(new InputStreamReader(
//                                                   new FileInputStream(filePath), "gbk"));

        //读取
        System.out.println("读取到的内容:"+br.readLine());
        //关闭流
        br.close();
    }
}

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

package transformation;

import java.io.*;

/**
 * @author yeye
 * @desc 使用OutputStreamReader写入文件
 *  把字节流 FileOutputStream 转换成字符流 OutputStreamWriter
 *  指定处理的编码格式,如UTF-8、GBK等
 * @date 2024/8/22 17:09
 */
public class OutputStreamWriter01 {
    public static void main(String[] args) throws IOException {

        String filePath = "E:/aaa.txt";
        String encoding = "UTF-8";

        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filePath), encoding);
        osw.write("你好,椰椰!");

        osw.close();
        System.out.println("写入文件成功!");
    }
}

打印流——PrintStream和PrintWriter

PrintStream字节流,PrinteWriter字符流
打印流只有输出流,没有输入流。
例1:printStream 字节流打印

package printstream;

import java.io.IOException;
import java.io.PrintStream;

import static java.lang.System.out;

/**
 * @author yeye
 * @desc PrintStream (字节打印/输出流)
 * @date 2024/8/22 17:30
 */
public class PrintStream01 {
    public static void main(String[] args) throws IOException {

        PrintStream ps = System.out;
        //在默认的情况下,PrintStream 数据输出的位置是 默认输出,即显示器
        ps.println("今天不想吃晚饭!");
        //因为print底层调用的是write方法,所以可以直接使用write方法打印/输出
        ps.write("。。。,".getBytes());
        ps.close();

        //也可以通过System.setOut()方法修改默认的输出位置
        System.setOut(new PrintStream("E://test.txt"));
        out.println("今天吃了晚饭!");

    }
}

例2:PrinteWriter 字符流打印

package IOStream.printstream_;

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @author yeye
 * @desc PrinterWriter 的使用
 * @date 2024/8/22 18:00
 */
public class PrintWriter01 {
    public static void main(String[] args) throws IOException {

        //标准输出,显示器
        PrintWriter pw1 = new PrintWriter(System.out);
        pw1.println("Hello World");
        pw1.close();
        //指定打印文件
        PrintWriter pw2 = new PrintWriter(new FileWriter("E:/test.txt"));
        pw2.println("Hello 明天");
        pw2.close();
    }
}

Properties类

unicode码查询:http://tool.chinaz.com/tools/unicode.aspx

  1. 专门用于读写配置文件的集合类
    配置文件的格式:
    • 键=值
    • 键=值
  2. 键值对不需要有空格,值不需要用 " " ,默认类型是String
  3. Properties父类是HashTable,底层就是Hashtable核心方法
  4. Properties 类常见的方法
    • load:加载配置文件的键值对到Properties对象;
    • list:将得到的键值对显示到指定设备/流对象;
    • getProperty(key):根据键获取对应的值;
    • setProperty(key,value):修改键对应的值,没有key,则添加;
    • store:将Properties中的键值对存储到配置文件中,在idea中,保存信息到配置文件,如果含有中文,会存储为unicode码
如下一个配置文件 mysql.properties
ip = 1234
user = root
password = root
请问编程读取 ip 、user 和 pwd 的值是多少
例1:传统的方法
例2:使用Properties类可以方便实现

例1:传统方法:
配置文件:src/IOStream/mysql.properties

package IOStream.properties;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

/**
 * @author yeye
 * @desc
 * @date 2024/8/22 18:25
 */
public class Properties01 {
    public static void main(String[] args) throws IOException {
        //读取mysql.properties文件,并得到ip,username,password
        BufferedReader br = new BufferedReader(new FileReader("src/IOStream/mysql.properties"));
        String line = null;
        //循环读取
        while((line = br.readLine()) != null){
            //使用line变量调用split方法,以等号(=)作为分隔符来分割字符串。
            //split方法将字符串分割成一个字符串数组split,其中包含两个元素:等号前的文本和等号后的文本。
            String[] split = line.split("=");
            System.out.println(split[0] + " 的值是" + split[1]);
            //System.out.println(line);
        }
        br.close();

    }
}

例2:使用Properties类完成对mysql.properties的读取

package IOStream.properties;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;

/**
 * @author yeye
 * @desc
 * @date 2024/8/22 19:08
 */
public class Properties02 {
    public static void main(String[] args) throws IOException {
        //使用Properties类完成对mysql.properties的读取

        //第一步,创建Properties对象
        Properties properties = new Properties();
        //第二步,读取mysql.properties文件
        properties.load(new FileReader("src/IOStream/mysql.properties"));
        //第三步,把键值对显示到控制台
        properties.list(System.out);
        //第四步,根据键获取对应的值
        String user = properties.getProperty("user");
        String password = properties.getProperty("password");
        System.out.println("用户名:"+user);
        System.out.println("密码:"+password);
  
    }
}
//运行结果
password=1234
encoding=UTF-8
user=root
用户名:root
密码:1234

例3:创建新的配置文件,并保存新的键值对

package IOStream.properties;

import java.io.*;
import java.util.Properties;

/**
 * @author yeye
 * @desc
 * @date 2024/8/22 19:48
 */
public class Properties03 {
    public static void main(String[] args) throws IOException {
        //使用Properties类创建配置文件,并修改配置文件内容
        Properties properties = new Properties();

        //创建键值对
        properties.setProperty("user","椰椰");//保存时,是中文的unicode编码
        properties.setProperty("password","1234");
        properties.setProperty("encoding","UTF-8");
        //将键值对保存到配置文件中
        properties.store(new FileOutputStream("src/IOStream/mysql02.properties"), "配置文件");
        properties.list(System.out);
        System.out.println("保存配置文件成功");
    }
}
//运行结果
password=1234
encoding=UTF-8
user=椰椰
保存配置文件成功
//mysql02.properties文件中保存的内容
#\u914D\u7F6E\u6587\u4EF6
#Thu Aug 22 20:02:06 CST 2024
password=1234
encoding=UTF-8
user=\u6930\u6930

这是我在学习韩顺平老师Java课程所写,韩老师讲的非常好,非常详细,感兴趣的同学可以去学习。

标签:JAVA,String,java,白版,IO,import,new,public,读取
From: https://www.cnblogs.com/wmshun/p/18374685

相关文章

  • 深入理解 Java 中 ArrayList 的底层原理
    在这篇博客中,我们将深入探讨ArrayList的底层实现原理,并通过逐步剖析ArrayList的源码来理解其内部工作机制。我们将重点关注ArrayList的创建、元素添加、扩容机制等关键点。创建ArrayList集合对象ArrayList<String>list=newArrayList<>();使用空参构造器创建ArrayList集合......
  • [Java手撕]线程安全的转账
    首先来看线程不安全的转账publicclassBank{privateint[]accounts;publicBank(){this.accounts=newint[10];for(inti=0;i<10;i++){accounts[i]=1000;}}publicvoidtransfer(intfrom,int......
  • 一起学Java(3)-Java项目构建工具Gradle和Maven场景定位和优缺点对比
    在第一步创建的项目(java-all-in-one)项目里,我们提到了使用Gradle作为项目构建工具。看到这里,不知道你是否有疑惑,什么是项目构建工具。Java项目常用构建工具有哪些?都有什么特点?带着疑惑,本文对Java的构建工具进行一些梳理,以同步理解。从而使大家对我们项目中使用到的技术栈和技术......
  • Java多态
    1.多态1.1多态的概述(记忆)什么是多态不同类的对象在调用同一个方法时表现出来的多种不同行为多态的前提要有继承或实现关系要有方法的重写要有父类引用指向子类对象代码演示classAnimal{  publicvoideat(){    System.out.println("动物吃肉")......
  • 5. 概述(General description)
    5.概述(Generaldescription)5.1.Introduction5.1.Alow-ratewirelesspersonalareanetwork(LR-WPAN)isasimple,low-costcommunicationnetworkthatallowswirelessconnectivityinapplicationswithlimitedpowerandrelaxedthroughputrequirements.The......
  • 【App Service】在App Service中配置Virtual applications and directories,访问目录中
    问题描述在AppServiceWindows的环境中,想一个AppServices下部署多个站点,比如/根目录下,从wwwroot中读取项目文件,而/files则通过配置的虚拟目录来读取\mounts\sitefiles目录中的静态文件。在AppService的 ConfigurationPathMapping中配置如下:通过Kudu查看AppService......
  • Java设计模式之代理模式:静态代理VS动态代理,与其他模式的对比分析和案例解析
    一、代理模式简介代理模式(ProxyPattern)是一种结构型设计模式,它提供了一个代理对象,用来控制对另一个对象的访问。这种模式通常用于在访问对象时引入额外的功能,而不改变对象的接口。代理模式的核心思想是为其他对象提供一种代理,以控制对这个对象的访问。在现实生活中,代理模......
  • java 面向对象4
    1.java存在抽象类,不写函数的具体实现,需要再函数前边加上abstract修饰.这个和c++语法存在差别,但是同样抽象类不可以创建对象,可以用抽象类的引用指向子类创建的对象,这个用法在一定程度上使得接口一致.利于在开发中保持接口一致,避免接口混乱的问题.同时利用抽象类可以使得一些......
  • localStorage、sessionStorage、Cookie的区别以及特点
    文章目录一、localStorage、sessionStorage、Cookie是什么?二、各自特点以及之间的区别1.`window.localStorage`2.`sessionStorage`3.`Cookie`三、写一个html页面以用来测试这三者不同的区别四、开始测试测试`localStorage`:测试`sessionStorage`:测试`Cookie`:总......
  • JavaSE基础知识分享(十三)
    写在前面今天继续讲Java中的网络编程的知识!网络编程概述计算机网络计算机网络是将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统、网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。例如:极域。网络......