Java IO流

2024-01-09 06:45:44

Java IO流

Java File类

概念

Java文件类以抽象的方式代表文件名和目录路径名。该类主要用于文件和目录的创建文件的查找文件的删除等。

File对象代表磁盘中实际存在的文件和目录。

创建一个File对象

可以通过以下四种构造方法其中一个,来创建一个File对象:

通过给定的父抽象路径名和子路径名字符串创建一个新的File实例
File(File parent, String child)

通过将给定路径名字符串转换成抽象路径名来创建一个新 File 实例
File(String pathname)

根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例
File(String parent, String child)

通过将给定的 file: URI 转换成一个抽象路径名来创建一个新的 File 实例
File(URI uri)

File对象的常用方法

序号方法名称方法描述
1public String getName()返回由此抽象路径名表示的文件或目录的名称
2public String getParent()返回此抽象路径名的父路径名的路径名字符串,如果此路径名没有指定父目录,则返回 null
3public File getParentFile()返回此抽象路径名的父路径名的抽象路径名,如果此路径名没有指定父目录,则返回 null
4public String getPath()将此抽象路径名转换为一个路径名字符串
5public boolean isAbsolute()判断此抽象路径名是否为绝对路径名
6public String getAbsolutePath()返回抽象路径名的绝对路径名字符串
7public boolean canRead()判断应用程序是否可以读取此抽象路径名表示的文件
8public boolean canWrite()判断应用程序是否可以修改此抽象路径名表示的文件
9public boolean exists()判断此抽象路径名表示的文件或目录是否存在
10public boolean isDirectory()判断此抽象路径名表示的文件是否是一个目录
11public boolean isFile()判断此抽象路径名表示的文件是否是一个标准文件
12public long lastModified()返回此抽象路径名表示的文件最后一次被修改的时间
13public long length()返回由此抽象路径名表示的文件的长度
14public boolean createNewFile() throws IOException当且仅当不存在具有此抽象路径名指定的名称的文件时,原子地创建由此抽象路径名指定的一个新的空文件
15public boolean delete()删除此抽象路径名表示的文件或目录
16public void deleteOnExit()在虚拟机终止时,请求删除此抽象路径名表示的文件或目录
17public String[] list()返回由此抽象路径名所表示的目录中的文件和目录的名称所组成字符串数组
18public String[] list(FilenameFilter filter)返回由包含在目录中的文件和目录的名称所组成的字符串数组,这一目录是通过满足指定过滤器的抽象路径名来表示的
19public File[] listFiles()返回一个抽象路径名数组,这些路径名表示此抽象路径名所表示目录中的文件
20public File[] listFiles(FileFilter filter)返回表示此抽象路径名所表示目录中的文件和目录的抽象路径名数组,这些路径名满足特定过滤器
21public boolean mkdir()创建此抽象路径名指定的目录
22public boolean mkdirs()创建此抽象路径名指定的目录,包括创建必需但不存在的父目录(迭代创建)
23public boolean renameTo(File dest)重新命名此抽象路径名表示的文件
24public boolean setLastModified(long time)设置由此抽象路径名所指定的文件或目录的最后一次修改时间
25public boolean setReadOnly()标记此抽象路径名指定的文件或目录,以便只可对其进行读操作
26public static File createTempFile(String prefix, String suffix, File directory) throws IOException在指定目录中创建一个新的空文件,使用给定的前缀和后缀字符串生成其名称
27public static File createTempFile(String prefix, String suffix) throws IOException在默认临时文件目录中创建一个空文件,使用给定前缀和后缀生成其名称
28public int compareTo(File pathname)按字母顺序比较两个抽象路径名
29public int compareTo(Object o)按字母顺序比较抽象路径名与给定对象
30public boolean equals(Object obj)判断此抽象路径名与给定对象是否相等
31public String toString()返回此抽象路径名的路径名字符串

文件拷贝工具类

/**
 * <p>
 * 文件拷贝工具类
 * <p/>
 *

 */
public class FileCopyUtil {

    private FileCopyUtil() {

    }

    /**
     * <p>
     * 拷贝文件的功能
     * <p/>
     *
     * @param srcFile 源文件(路径)
     * @param desPath 目标路径
     * @return void
     * @Date 2020/6/6 11:57
     */
    public static void copyFile(String srcFile, String desPath) {
        // String -> File
        copyFile(new File(srcFile), desPath);
    }

    /**
     * <p>
     * 拷贝文件的功能
     * <p/>
     *
     * @param srcFile 源文件(file类型)
     * @param desPath 目标路径
     * @return void
     * @Date 2020/6/6 12:01
     */
    public static void copyFile(File srcFile, String desPath) {
        // 1.取出源文件名称
        String fileName = srcFile.getName();

        // 2.判断目标路径是否存在
        File dPath = new File(desPath);
        if (!dPath.exists()) {
            //拷贝的目的地路径,如果目录不存在,创建目录
            // boolean mkdir() 创建此抽象路径名指定的目录,创建此抽象路径名指定的目录,包括所有必需但不存在的父目录。
            System.out.println("创建目标路径是否成功:" + dPath.mkdirs());
        }

        // 3.设置目标文件名称
        //static String separator() 与系统有关的默认名称分隔符,为了方便,它被表示为一个字符串。
        String desFileName = desPath + File.separator + fileName;

        // 声明低级流
        FileInputStream fileInputStream;
        FileOutputStream fileOutputStream;

        // 声明高级流
        BufferedInputStream bufferedInputStream = null;
        BufferedOutputStream bufferedOutputStream = null;

        try {
            // 初始化的时候先初始化低级流(FileInputStream为文件字节输入流,FileOutputStream为文件字节输出流)
            fileInputStream = new FileInputStream(srcFile);
            fileOutputStream = new FileOutputStream(desFileName);

            // 然后初始化高级流,使用缓冲流提升io性能
            bufferedInputStream = new BufferedInputStream(fileInputStream);
            bufferedOutputStream = new BufferedOutputStream(fileOutputStream);

            //定义一个字节数组,相当于缓存
            byte[] b = new byte[1024 * 1024];
            //得到实际读取到的字节数 读到最后返回-1
            int i = 0;
            //循环读取,把bufferedInputStream里的东西读到bytes数组里去
            while ((i = bufferedInputStream.read(b)) != -1) {
                bufferedOutputStream.write(b, 0, i);
            }

            System.out.println(srcFile + " 文件拷贝到目标目录【" + desPath + "】完成!");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 高级流bout关闭的时候,JVM会自动的刷新缓冲区,即在关闭流之前会自动调用flush方法刷新缓存
            try {
                if (bufferedOutputStream != null) {
                    bufferedOutputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

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

    /**
     * <p>
     * 拷贝目录的功能
     * <p/>
     *
     * @param srcPath 源目录(路径)
     * @param desPath 目标目录
     * @return void
     * @Date 2020/6/6 13:13
     */
    public static void copyDir(String srcPath, String desPath) {
        copyDir(new File(srcPath), desPath);
    }

    /**
     * <p>
     * 拷贝目录的功能
     * <p/>
     *
     * @param srcPath 源目录(file类型)
     * @param desPath 目标目录
     * @return void
     * @Date 2020/6/6 13:20
     */
    public static void copyDir(File srcPath, String desPath) {
        // 判断srcPath是文件还是目录
        if (srcPath.isFile()) {
            // 递归调用,如果是文件则继续调用,直到为一个目录
            copyFile(srcPath, desPath);
        } else {
            // 获取源目录中所有的子文件
            File[] files = srcPath.listFiles();

            // 从源目录中获取要拷贝的目录的名称,例如:从"d:\\test-case"源目录中获取到 test-case 这个目录的名称
            String srcPathName = srcPath.getName();

            // 在目标路径中创建要拷贝的目录名称,例如 在d:\\创建 src 目录
            String descPathName = desPath + File.separator;
            // 通过将给定路径名字符串,转换为抽象路径名,来创建一个新 File 实例
            File filePath = new File(descPathName);

            // 创建此抽象路径名指定的目录,包括所有必需但不存在的父目录
            if (!filePath.exists()) {
                filePath.mkdirs();
            }

            // 遍历数组,一个一个目录的拷贝
            for (File file : files) {
                // 递归调用
                copyDir(file, descPathName);
            }
        }
    }

}

拷贝文件的功能
public void testCopyFile() {
    String srcFile = "D:\\test-case\\log.txt";
    FileCopyUtil.copyFile(srcFile, "d:\\test-case\\src");
}
拷贝文件目录的功能
public void testCopyDir() {
        String srcFile = "D:\\test-case";
        FileCopyUtil.copyDir(srcFile, "c:\\test-case\\test");
    }

IO流

流的概念和作用

流:代表任何有能力产出数据的数据源对象或者是有能力接受数据的接收端对象

流的本质:数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。

IO流的概念

? 对数据的读写操作称为IO流,IO流发生在本地传输或网络传输中

作用:为数据源和目的地建立一个输送通道

分类

1.按数据流的方向分为 输入流、输出流

此输入、输出是相对于我们写的代码程序而言,

输入流:从别的地方(本地文件,网络上的资源等)获取资源 输入到 我们的程序中

输出流:从我们的程序中 输出到 别的地方(本地文件), 将一个字符串保存到本地文件中,就需要使用输出流。

2、按处理数据单位不同分为 字节流、字符流

1字符 = 2字节 、 1字节(byte) = 8位(bit) 、 一个汉字占两个字节长度

字节流:每次读取(写出)一个字节,当传输的资源文件有中文时,就会出现乱码,

字符流:每次读取(写出)两个字节,有中文时,使用该流就可以正确传输显示中文。

3、按功能不同分为 节点流、处理流

节点流:以从或向一个特定的地方(节点)读写数据。如FileInputStream

处理流:是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader。处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,

4、4个基本的抽象流类型,所有的流都继承这四个。

输入流      输出流

字节流  InputStream  outputStream

字符流  Reader      Writer

inputStream:字节输入流

img

outputStream:字节输出流

img

Reader:字符输入流

img

Writer:字符输出流

img

字符流的由来: Java中字符是采用Unicode标准,一个字符是16位,即一个字符使用两个字节来表示。为此,JAVA中引入了处理字符的流。因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。

IO流特性

1、先进先出,最先写入输出流的数据最先被输入流读取到。

2、顺序存取,可以一个接一个地往流中写入一串字节,读出时也将按写入顺序读取一串字节,不能随机访问中间的数据。(RandomAccessFile可以从文件的任意位置进行存取(输入输出)操作

3、只读或只写,每个流只能是输入流或输出流的一种,不能同时具备两个功能,输入流只能进行读操作,对输出流只能进行写操作。在一个数据传输通道中,如果既要写入数据,又要读取数据,则要分别提供两个流。

IO流常用到的五类一接口

在整个Java.io包中最重要的就是5个类和一个接口。5个类指的是File、OutputStream、InputStream、Writer、Reader;一个接口指的是Serializable.掌握了这些IO的核心操作那么对于Java中的IO体系也就有了一个初步的认识了。

主要的类如下:

  1. File(文件特征与管理):File类是对文件系统中文件以及文件夹进行封装的对象,可以通过对象的思想来操作文件和文件夹。 File类保存文件或目录的各种元数据信息,包括文件名、文件长度、最后修改时间、是否可读、获取当前文件的路径名,判断指定文件是否存在、获得当前目录中的文件列表,创建、删除文件和目录等方法。
  2. InputStream(二进制格式操作):抽象类,基于字节的输入操作,是所有输入流的父类。定义了所有输入流都具有的共同特征。
  3. OutputStream(二进制格式操作):抽象类。基于字节的输出操作。是所有输出流的父类。定义了所有输出流都具有的共同特征。
  4. Reader(文件格式操作):抽象类,基于字符的输入操作。
  5. Writer(文件格式操作):抽象类,基于字符的输出操作。
  6. RandomAccessFile(随机文件操作):一个独立的类,直接继承至Object.它的功能丰富,可以从文件的任意位置进行存取(输入输出)操作。

img

Java IO流对象

1、输入字节流InputStream

img

每个类的功能即作用

**ByteArrayInputStream:**字节数组输入流,该类的功能就是从字节数组(byte[])中进行以字节为单位的读取,也就是将资源文件都以字节的形式存入到该类中的字节数组中去,我们拿也是从这个字节数组中拿

PipedInputStream:管道字节输入流,它和PipedOutputStream一起使用,能实现多线程间的管道通信

FilterInputStream :装饰者模式中处于装饰者,具体的装饰者都要继承它,所以在该类的子类下都是用来装饰别的流的,也就是处理类。具体装饰者模式在下面会讲解到,到时就明白了

BufferedInputStream:缓冲流,对处理流进行装饰,增强,内部会有一个缓存区,用来存放字节,每次都是将缓存区存满然后发送,而不是一个字节或两个字节这样发送。效率更高

DataInputStream:数据输入流,它是用来装饰其它输入流,它“允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型”

**FileInputSream:**文件输入流。它通常用于对文件进行读取操作

**File:**对指定目录的文件进行操作,具体可以查看讲解File的博文。注意,该类虽然是在IO包下,但是并不继承自四大基础类。

**ObjectInputStream:**对象输入流,用来提供对“基本数据或对象”的持久存储。通俗点讲,也就是能直接传输对象(反序列化中使用),

**InputStream(输入流)**是Java中用于从数据源(如文件、网络连接、内存等)读取数据的抽象类。它是一个抽象类,不能直接实例化,但可以通过它的子类来实现不同的输入源。

InputStream提供了一些常用的方法来读取数据,其中包括:

  1. int read():从输入流中读取单个字节并返回,读取到末尾时返回-1。
  2. int read(byte[] buffer):从输入流中读取最多buffer.length个字节,并将其存储在给定的缓冲区数组中,返回实际读取的字节数。如果已到达文件末尾,则返回-1。
  3. int read(byte[] buffer, int offset, int length):从输入流中读取最多length个字节,并将其存储在给定的缓冲区数组中,从偏移量offset开始存储,返回实际读取的字节数。如果已到达文件末尾,则返回-1。
  4. void close():关闭输入流,释放与其关联的资源。

以下是一个示例代码,演示了如何使用InputStream从文件中读取数据:

import java.io.FileInputStream;
import java.io.InputStream;

public class InputStreamExample {
    public static void main(String[] args) {
        try {
            InputStream inputStream = new FileInputStream("path/to/your/file.txt"); // 打开文件输入流

            byte[] buffer = new byte[1024]; // 缓冲区
            int bytesRead;

            while ((bytesRead = inputStream.read(buffer)) != -1) {
                // 处理读取到的数据,这里直接将其转换为字符串并打印
                String data = new String(buffer, 0, bytesRead);
                System.out.print(data);
            }

            inputStream.close(); // 关闭输入流
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

注意,在使用InputStream读取数据时,需要适时关闭输入流,以释放与其关联的资源。以上示例中使用inputStream.close()方法关闭输入流。

FileInputStream类提供了一些方法来读取文件中的数据。以下是一些常用的方法:

  1. read(): 从文件中读取下一个字节并返回作为int类型的数据。如果已经读取到文件的末尾,则返回-1。
int data = fileInputStream.read();
  1. read(byte[] buffer): 从文件中将字节读取到指定的字节数组buffer中,并返回读取的字节数。如果已经读取到文件的末尾,则返回-1。
byte[] buffer = new byte[1024];
int bytesRead = fileInputStream.read(buffer);
  1. n): 从文件中跳过n个字节,返回实际跳过的字节数。
long skippedBytes = fileInputStream.skip(5);
  1. available(): 返回文件中可用的字节数。
int bytesAvailable = fileInputStream.available();
  1. getChannel(): 返回与该文件输入流关联的唯一文件通道。
FileChannel channel = fileInputStream.getChannel();
  1. close(): 关闭文件输入流。一旦关闭,将无法读取更多的字节。
fileInputStream.close();

这些方法使得您可以从文件中读取数据。您可以根据需要选择和组合这些方法来满足您的具体需求。记得在不需要使用文件输入流时,要及时调用close()方法关闭流,以释放资源。

BufferedInputStream类是Java中用于输入流缓冲的一个包装类。它提供了一个缓冲区来提高从输入流中读取数据的性能。以下是一些常用的BufferedInputStream方法:

  1. read(): 从输入流中读取下一个字节,并返回该字节的int表示。如果已经读取到流的末尾,则返回-1。
int data = bufferedInputStream.read();
  1. read(byte[] buffer): 从输入流中将字节读取到指定的字节数组buffer中,并返回读取的字节数。如果已经读取到流的末尾,则返回-1。
byte[] buffer = new byte[1024];
int bytesRead = bufferedInputStream.read(buffer);
  1. available(): 返回缓冲区中可用的字节数。
int bytesAvailable = bufferedInputStream.available();
  1. mark(int readlimit): 标记当前位置,以便稍后可以通过reset()方法返回到此位置。
bufferedInputStream.mark(10);
  1. reset(): 将输入流的当前位置重置为最后标记的位置。
bufferedInputStream.reset();
  1. skip(long n): 从输入流中跳过n个字节,返回实际跳过的字节数。
long skippedBytes = bufferedInputStream.skip(5);
  1. close(): 关闭输入流。
bufferedInputStream.close();

这些方法允许您在使用BufferedInputStream时更好地控制和操作输入流数据。它提供了更高的性能,尤其是在以字节为单位从输入流中读取数据时。

2、输出字节流OutputStream

img

IO 中输出字节流的继承图可见上图,可以看出:

  1. OutputStream 是所有的输出字节流的父类,它是一个抽象类。
  2. ByteArrayOutputStream、FileOutputStream 是两种基本的介质流,它们分别向Byte 数组、和本地文件中写入数据。PipedOutputStream 是向与其它线程共用的管道中写入数据,
  3. ObjectOutputStream 和所有FilterOutputStream 的子类都是装饰流(序列化中使用)。

img

FileOutputStream类是Java中用于将数据写入文件的类。它提供了一些方法来操作文件输出流。以下是一些常用的FileOutputStream方法:

  1. write(int b): 将指定的字节写入输出流。
fileOutputStream.write(65); // 写入ASCII码为65的字符'A'
  1. write(byte[] b): 将指定的字节数组写入输出流。
byte[] byteArray = {65, 66, 67};
fileOutputStream.write(byteArray); // 写入字节数组
  1. flush(): 刷新输出流,将缓冲区中的数据立即写入文件。
fileOutputStream.flush();
  1. close(): 关闭输出流,并释放相关的系统资源。
fileOutputStream.close();

这些方法允许您使用FileOutputStream来将数据写入文件。您可以使用write()方法将单个字节或字节数组写入文件。使用flush()方法可以确保所有的数据都被写入文件。最后,使用close()方法关闭输出流以释放相关资源。请注意,当您写入完毕后,务必调用flush()和close()方法,以防止数据丢失和资源泄漏。

请注意,通过FileOutputStream写入的数据将覆盖文件中的旧数据。如需进行追加写入,请参考FileOutputStream的另一个构造函数或使用RandomAccessFile类。

要在FileOutputStream中进行追加写入,可以使用FileOutputStream的另一个构造函数或使用RandomAccessFile类。以下是两种方法:

方法一:使用FileOutputStream的另一个构造函数

FileOutputStream fileOutputStream = new FileOutputStream("file.txt", true);

在这种方法中,将文件名和一个boolean值true作为参数传递给FileOutputStream的构造函数。这个boolean值表示是否在写入时追加到文件末尾。如果设置为true,则会在文件末尾追加写入;如果设置为false,则会覆盖文件中的旧数据。

BufferedOutputStream类是Java中用于输出流缓冲的一个包装类。它提供了一个缓冲区来提高向输出流写入数据的性能。以下是一些常用的BufferedOutputStream方法:

  1. write(int b): 将指定的字节写入缓冲区。
bufferedOutputStream.write(65); // 写入ASCII码为65的字符'A'
  1. write(byte[] b): 将指定的字节数组写入缓冲区。
byte[] byteArray = {65, 66, 67};
bufferedOutputStream.write(byteArray); // 写入字节数组
  1. flush(): 将缓冲区中的数据立即写入到底层输出流。
bufferedOutputStream.flush();
  1. close(): 关闭输出流,并释放相关的系统资源。
bufferedOutputStream.close();

这些方法允许您在使用BufferedOutputStream时更好地控制和操作输出流数据。它提供了更高的性能,尤其是在以字节为单位向输出流写入数据时。通过使用缓冲区,数据可以暂时存储在内存中,减少了对底层输出流的直接写入次数。

当您使用BufferedOutputStream写入数据时,只有当缓冲区满了或显式调用flush()方法时,数据才会被写入底层的输出流。为了避免数据丢失,请确保在写入完毕后调用flush()方法来刷新缓冲区中的数据。

最后,通过调用close()方法,可以关闭输出流并释放相关的系统资源。关闭输出流会自动刷新缓冲区中的数据,并将其写入到底层的输出流中。

3、字符输入流Reader

img

在上面的继承关系图中可以看出:

  1. Reader 是所有的输入字符流的父类,它是一个抽象类。

  2. CharReader、StringReader 是两种基本的介质流,它们分别将Char 数组、String中读取数据。**PipedReader 是从与其它线程共用的管道中读取数据。

  3. BufferedReader 很明显就是一个装饰器,它和其子类负责装饰其它Reader 对象。

  4. FilterReader 是所有自定义具体装饰流的父类,其子类PushbackReader 对Reader 对象进行装饰,会增加一个行号。

  5. InputStreamReader 是一个连接字节流和字符流的桥梁,它将字节流转变为字符流。FileReader 可以说是一个达到此功能、常用的工具类,在其源代码中明显使用了将FileInputStream 转变为Reader 的方法。我们可以从这个类中得到一定的技巧。Reader 中各个类的用途和使用方法基本和InputStream 中的类使用一致。后面会有Reader 与InputStream 的对应关系。

    FilterReader是Java中用于字符流过滤的抽象类。它在Reader类的基础上提供了一些额外的功能,例如字符流的过滤和转换。虽然FilterReader是一个抽象类,但Java提供了一些具体的子类,如BufferedReader和LineNumberReader。以下是一些常用的FilterReader方法

    1. read(): 从输入流中读取下一个字符,并返回int类型的字符表示。如果已经读取到流的末尾,则返回-1。
    int data = filterReader.read();
    
    1. read(char[] cbuf): 从输入流中将字符读取到指定的字符数组cbuf中,并返回读取的字符数。如果已经读取到流的末尾,则返回-1。
    char[] cbuf = new char[1024];
    int charsRead = filterReader.read(cbuf);
    
    1. ready(): 检查输入流是否准备好被读取,返回一个boolean值。
    boolean isReady = filterReader.ready();
    
    1. mark(int readAheadLimit): 标记当前位置,以便稍后可以通过reset()方法返回到此位置。
    filterReader.mark(10);
    
    1. reset(): 将输入流的当前位置重置为最后标记的位置。
    filterReader.reset();
    
    1. close(): 关闭输入流,并释放相关的系统资源。
    filterReader.close();
    

    这些方法允许您在使用FilterReader时更好地控制和操作字符流数据。FilterReader类是一个抽象类,因此通常会使用它的具体子类,如BufferedReader,来读取字符数据并提供更高级别的功能,如缓冲读取和行号计数等。

    在使用FilterReader时,请根据需要选择和组合这些方法,以满足您的具体需求。记住,在不再需要使用FilterReader时,要调用close()方法来关闭输入流,以释放相关的资源。

    BufferedReader类是Java中用于字符流缓冲的一个包装类。它提供了一些方法来读取字符数据并提供更高级别的功能,如缓冲读取和一次读取一行数据。以下是一些常用的BufferedReader方法:

    1. read(): 从缓冲区中读取下一个字符,并返回int类型的字符表示。如果已经读取到流的末尾,则返回-1。
    int data = bufferedReader.read();
    
    1. read(char[] cbuf): 从缓冲区中将字符读取到指定的字符数组cbuf中,并返回读取的字符数。如果已经读取到流的末尾,则返回-1。
    char[] cbuf = new char[1024];
    int charsRead = bufferedReader.read(cbuf);
    
    1. readLine(): 从缓冲区中读取一行字符数据,并作为String返回。如果已经读取到流的末尾,则返回null。
    String line = bufferedReader.readLine();
    
    1. ready(): 检查缓冲区是否准备好被读取,返回一个boolean值。
    boolean isReady = bufferedReader.ready();
    
    1. mark(int readAheadLimit): 标记当前位置,以便稍后可以通过reset()方法返回到此位置。
    bufferedReader.mark(10);
    
    1. reset(): 将输入流的当前位置重置为最后标记的位置。
    bufferedReader.reset();
    
    1. close(): 关闭输入流,并释放相关的系统资源。
    bufferedReader.close();
    

    这些方法允许您在使用BufferedReader时更好地控制和操作字符流数据。通过使用缓冲区,可以提高读取字符数据的性能,尤其是进行一次读取一行数据的时候。

    请根据需要选择和组合这些方法,以满足您的具体需求。记住,在不再需要使用BufferedReader时,要调用close()方法来关闭输入流,以释放相关的资源。

4、字符输出流Writer

img

在上面的关系图中可以看出:

  1. Writer 是所有的输出字符流的父类,它是一个抽象类。
  2. CharArrayWriter、StringWriter 是两种基本的介质流,它们分别向Char 数组、String 中写入数据。**PipedWriter 是向与其它线程共用的管道中写入数据,
  3. BufferedWriter 是一个装饰器为Writer 提供缓冲功能。
  4. PrintWriter 和PrintStream 极其类似,功能和使用也非常相似。
  5. OutputStreamWriter 是OutputStream 到Writer 转换的桥梁,它的子类FileWriter 其实就是一个实现此功能的具体类(具体可以研究一SourceCode)。功能和使用和OutputStream 极其类似,后面会有它们的对应图。

img

BufferedWriter类是Java中用于字符流缓冲的一个包装类。它提供了一些方法来写入字符数据并提供了缓冲写入的功能。以下是一些常用的BufferedWriter方法:

  1. write(int c): 将指定的字符写入缓冲区。
bufferedWriter.write('A');
  1. write(String str): 将指定的字符串写入缓冲区。
String str = "Hello, World!";
bufferedWriter.write(str);
  1. newLine(): 写入一个平台特定的行分隔符。可以使用这个方法来换行。
bufferedWriter.newLine();
  1. flush(): 刷新缓冲区,将缓冲区中的数据立即写入到底层Writer流。
bufferedWriter.flush();
  1. close(): 关闭写入流,并释放相关的系统资源。
bufferedWriter.close();

这些方法允许您在使用BufferedWriter时更好地控制和操作字符数据的写入。通过使用缓冲区,可以提高写入字符数据的性能。

例如,您可以使用write()方法将字符或字符串写入缓冲区,然后使用newLine()方法来换行。最后,可以使用flush()方法刷新缓冲区并确保数据被写入底层的写入流。

请根据需要选择和组合这些方法,以满足您的具体需求。记住,在不再需要使用BufferedWriter时,要调用close()方法来关闭写入流,以释放相关的资源。

FileWriter类是Java中用于将字符数据写入文件的类。它是Writer类的子类,并提供了一些方法用于写入字符数据。以下是一些常用的FileWriter方法:

  1. write(int c): 将指定的字符写入文件。
fileWriter.write('A');
  1. write(char[] cbuf): 将字符数组中的数据写入文件。
char[] data = {'H', 'e', 'l', 'l', 'o'};
fileWriter.write(data);
  1. write(String str): 将字符串写入文件。
String str = "Hello, World!";
fileWriter.write(str);
  1. flush(): 将缓冲区中的数据立即写入文件。
fileWriter.flush();
  1. close(): 关闭写入流,并释放相关的系统资源。
fileWriter.close();

这些方法允许您使用FileWriter将字符数据写入文件中。您可以使用write()方法将字符、字符数组或字符串写入文件。通过调用flush()方法,可以确保缓冲区中的数据被写入到文件中。最后,通过调用close()方法,关闭写入流以释放相关资源。

请注意,在使用完FileWriter之后,一定要记得调用close()方法来关闭写入流,以确保文件资源和系统资源得到正确释放。同时,可以使用try-with-resources语句来自动关闭写入流,以避免手动关闭的疏忽。例如:

try (FileWriter fileWriter = new FileWriter("filename.txt")) {
    // 写入操作
} catch (IOException e) {
    e.printStackTrace();
}

这样,在try块结束后,无论是否发生异常,都会自动关闭写入流。

5、字节流和字符流使用情况:(重要)

字符流和字节流的使用范围:字节流一般用来处理图像,视频,以及PPT,Word类型的文件。字符流一般用于处理纯文本类型的文件,如TXT文件等,字节流可以用来处理纯文本文件,但是字符流不能用于处理图像视频等非文本类型的文件。

字符流与字节流转换

img

转换流的作用,文本文件在硬盘中以字节流的形式存储时,通过InputStreamReader读取后转化为字符流给程序处理,程序处理的字符流通过OutputStreamWriter转换为字节流保存。

转换流的特点:

  1. 其是字符流和字节流之间的桥梁
  2. 可对读取到的字节数据经过指定编码转换成字符
  3. 可对读取到的字符数据经过指定编码转换成字节

何时使用转换流?

  1. 当字节和字符之间有转换动作时;
  2. 流操作的数据需要编码或解码时。

具体的对象体现:

  1. InputStreamReader:字节到字符的桥梁
  2. OutputStreamWriter:字符到字节的桥梁

这两个流对象是字符体系中的成员,它们有转换作用,本身又是字符流,所以在构造的时候需要传入字节流对象进来。

OutputStreamWriter(OutStreamout):将字节流以字符流输出。

InputStreamReader(InputStream in):将字节流以字符流输入。

字节流和字符流的区别(重点)

字节流和字符流的区别:(详细可以参见http://blog.csdn.net/qq_25184739/article/details/51203733)

字节流没有缓冲区,是直接输出的,而字符流是输出到缓冲区的。因此在输出时,字节流不调用colse()方法时,信息已经输出了,而字符流只有在调用close()方法关闭缓冲区时,信息才输出。要想字符流在未关闭时输出信息,则需要手动调用flush()方法

· 读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。

· 处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。

结论:只要是处理纯文本数据,就优先考虑使用字符流。除此之外都使用字节流。

序列化

将保存在内存中的对象数据转化为二进制数据流进行传输,任何对象都可以序列化

实现方法:实现java.io.Serializable接口

作用:把一个Java对象写入到硬盘或者传输到网路上面的其它计算机,这时我们就需要自己去通过java把相应的对象写成转换成字节流。对于这种通用的操作,我们为什么不使用统一的格式呢?没错,这里就出现了java的序列化的概念。在Java的OutputStream类下面的子类ObjectOutput-Stream类就有对应的WriteObject(Object object) 其中要求对应的object实现了java的序列化的接口。

在使用tomcat开发JavaEE相关项目的时候,我们关闭tomcat后,相应的session中的对象就存储在了硬盘上,如果我们想要在tomcat重启的时候能够从tomcat上面读取对应session中的内容,那么保存在session中的内容就必须实现相关的序列化操作,还有jdbc加载驱动用的就是反序列化,将字符串变为对象。

//序列化类:java.ioObjectOutputStream
//讲对象变为指定的二进制数据
class Book implements Serializable{

	private String title;

	private double price;

	public Book(String tit,double pri){
		this.title=tit;
		this.price=pri;
	}

	public String toString() {

		return "书名:"+this.title+",价格:"+this.price;

	}

}

public class Demo10 {

	public static void main(String[] args) throws Exception {
		//序列化到指定的文本
		ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(new File("e:"+File.separator+"demoA.txt")));
		oos.writeObject(new Book("java开发", 45.2));
		oos.close();
	}
}

反序列化

将二进制数据换回原对象

构造:

ObjectInputStream(InputStream in)

方法:

Object readObject() 从 ObjectInputStream 读取对象

class Book implements Serializable{

	private String title;

	private double price;

	public Book(String tit,double pri){
		this.title=tit;
		this.price=pri;
	}
	public String toString() {
		return "书名:"+this.title+",价格:"+this.price;
	}
}

public class Demo11 {

	public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
        
		ObjectInputStream ois=new ObjectInputStream(new FileInputStream(new File("e:"+File.separator+"demoA.txt")));
		Object obj=ois.readObject();
		Book book=(Book) obj;
		System.out.println(book);
		ois.close();
	}
}

transient关键字(一个类某些属性不需要序列化)

以上序列化和反序列化实现了的对象序列化,但是可以发现,操作时是将整个对象的所有属性序列化,那么transient关键字可以将某些内容不需要保存,就可以通过transient关键字来定义

private transient string title;

此时title属性无法被序列化,

Properties集合

Properties概述

Properties 类位于 java.util.Properties ,是Java 语言的配置文件所使用的类, Xxx.properties 为Java 语言常见的配置文件,如数据库的配置 jdbc.properties, 系统参数配置 system.properties。 这里,讲解一下Properties 类的具体使用。
以key=value 的 键值对的形式进行存储值。 key值不能重复。

继承了Hashtable 类,以Map 的形式进行放置值, put(key,value) get(key)
作为Map集合的使用
Properties的特殊功能
public Object setProperty(String key,String value)
public String getProperty(String key)
public Set stringPropertyNames()
Properties和IO流的结合使用
public void load(Reader reader)
public void store(Writer writer,String comments)

package com.shujia.day16;

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

public class Demo05Properties {
    public static void main(String[] args) throws IOException {
        /*
            需求:
                现在程序运行时,有时需要读取一些配置信息,有些如果直接写死在程序代码中,当程序编译后,不能进行修改,
                所以对于配置信息,需要保存在一个配置文件中,程序运行时,可以对其进行读取,之后进行分析得到想要的数据

                如果使用原先的字符流,那么字符串切分判断会很麻烦
                所以可以提供一个专门的类来做该部分事情

            可以使用 Properties 来加载配置文件

            构造方法
                public Properties() {
            操作方法:
                load()
                    public synchronized void load(Reader reader)
                    需要提供一个字符流对象,同时给定字符流时,其文件路径需要使用当前项目中的resource目录

                setProperty
                    可以给当前的properties对象添加配置信息
                store
                    可以存储相关配置到一个文件中
                    public void store(Writer writer, String comments)
                    writer 表示输出的字符流
                    comments 表示对当前配置的描述

         */

        Properties properties = new Properties();
        FileReader fileReader = new FileReader("resource/Mysql.properties");
        properties.load(fileReader);

        // 读取配置
        String userName = properties.getProperty("userName");
        String password = properties.getProperty("password");
        String url = properties.getProperty("url");

        System.out.println(userName);
        System.out.println(password);
        System.out.println(url);

        // 写入配置
        properties.setProperty("table","user_table");
        properties.setProperty("filed","name,age,info");

        FileWriter fileWriter = new FileWriter("resource/setMysql.properties");
        properties.store(fileWriter,"mysql 新增的配置");
    }
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

总结

inputStream类的功能不足被Scanner解决了

OutputStream类的功能不足被PrintStream解决了

Reader类功能不足被BufferReader解决了

Writer类的功能不足被PrintWriter解决了

    */

    Properties properties = new Properties();
    FileReader fileReader = new FileReader("resource/Mysql.properties");
    properties.load(fileReader);

    // 读取配置
    String userName = properties.getProperty("userName");
    String password = properties.getProperty("password");
    String url = properties.getProperty("url");

    System.out.println(userName);
    System.out.println(password);
    System.out.println(url);

    // 写入配置
    properties.setProperty("table","user_table");
    properties.setProperty("filed","name,age,info");

    FileWriter fileWriter = new FileWriter("resource/setMysql.properties");
    properties.store(fileWriter,"mysql 新增的配置");
}

}




[外链图片转存中...(img-LXD3mAEk-1704714245434)]

### 总结

inputStream类的功能不足被Scanner解决了

OutputStream类的功能不足被PrintStream解决了

Reader类功能不足被BufferReader解决了

Writer类的功能不足被PrintWriter解决了

输出数据用printStream,printwriter读取数据用Scanner其次是bufferReader

文章来源:https://blog.csdn.net/sheep55/article/details/135464946
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。