java-io流 超详细!

一、概念

io流用来读写文件中的数据 i:input  o:output

二、分类

1、按流的方法分为:输入流、输出流

2、按操作文件的类型分为:字节流、字符流

其中字节流能处理所有类型的文件 字符流只能处理纯文本文件

纯文本文件可以通过windows自带的记事本能打开且内容可以看得懂 包括txt、md文件

总结:

三、io流详解

1、字节流之FileOutputStream

(1)、概念

操作本地文件的字节输出流 可以将程序中的数据写到本地文件

(2)、步骤

1、创建对象(让程序和文件之间建立一个通道)

2、写数据

3、释放资源(断开程序和文件之间建立一个通道)

防止java程序占用资源 使得在其它程序中可以打开

(3)、细节

细节1:

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class test1 {
    public static void main(String[] args) throws IOException {
        // 创建对象
        // 也可以是字符串表示的路径
        FileOutputStream fos1=new FileOutputStream("D:\\测试安全\\c.txt");
        // 写数据
        fos1.write(97);
        // 释放资源
        fos1.close();

        // 创建对象
        // 参数可以是File对象表示的路径
        File f=new File("a.txt");
        FileOutputStream fos2=new FileOutputStream(f);
        // 写数据
        fos2.write(98);
        // 释放资源
        fos2.close();
    }
}

细节2:

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

public class test2 {
    public static void main(String[] args) throws IOException {
        // 创建对象
        // 也可以是字符串表示的路径
        // 如果文件路径不存在 就会创建文件 前提是父级路径存在
        FileOutputStream fos1=new FileOutputStream("D:\\测试安全\\d.txt");
        // 写数据
        fos1.write(99);
        // 释放资源
        fos1.close();
    }
}

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

public class test2 {
    public static void main(String[] args) throws IOException {
        // 创建对象
        // 也可以是字符串表示的路径
        // 如果文件路径不存在 就会创建文件 前提是父级路径存在
        // 父级路径不存在 就会报错
        FileOutputStream fos1=new FileOutputStream("D:\\测试安全\\f\\e.txt");
        // 写数据
        fos1.write(99);
        // 释放资源
        fos1.close();
    }
}

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

public class test2 {
    public static void main(String[] args) throws IOException {
        // 创建对象
        // 也可以是字符串表示的路径
        // 如果文件路径不存在 就会创建文件 前提是父级路径存在
        // 父级路径不存在 就会报错
        FileOutputStream fos1=new FileOutputStream("D:\\测试安全\\d.txt");
        // 写数据
        // 覆盖写
        fos1.write(101);
        fos1.write(102);
        fos1.write(103);
        // 释放资源
        fos1.close();
    }
}

(4)、写数据的三种方式

FileOutputStream对象.write(int b) 一次写一个字节数据

FileOutputStream对象.write(byte [] b) 一次写一个字节数组数据

FileOutputStream对象.write(byte [] b,int off,int len) 一次写一个字节数组部分数据

off表示起始索引 len表示写入的总个数

方式一:

方式二:

方式三:

(5)、换行写、续写

换行写:添加\r\n

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

public class test3 {
    public static void main(String[] args) throws IOException {
        // 创建对象
        FileOutputStream fos1=new FileOutputStream("a.txt");
        // 写数据
        /*
         当输入的内容很多时 我们可以先定义字符串
         通过字符串.getBytes()的方法将字符串的每个字符转化为其Ascii码值
         形成数组
        */
        String str1="你好 java helloworld";
        byte [] byte1=str1.getBytes();
        fos1.write(byte1);

        // 换行
        String str2="\r\n";
        byte[] byte2 = str2.getBytes();
        fos1.write(byte2);

        String str3="java是世界上最好的语言";
        byte [] byte3=str3.getBytes();
        fos1.write(byte3);
        // 释放资源
        fos1.close();
    }
}

续写:在创建FileOutputStream对象是 添加参数true

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

public class test3 {
    public static void main(String[] args) throws IOException {
        // 创建对象
        FileOutputStream fos1=new FileOutputStream("a.txt",true);
        // 写数据
        /*
         当输入的内容很多时 我们可以先定义字符串
         通过字符串.getBytes()的方法将字符串的每个字符转化为其Ascii码值
         形成数组
        */
        String str1="你好 java helloworld";
        byte [] byte1=str1.getBytes();
        fos1.write(byte1);

        // 换行
        String str2="\r\n";
        byte[] byte2 = str2.getBytes();
        fos1.write(byte2);

        String str3="java是世界上最好的语言";
        byte [] byte3=str3.getBytes();
        fos1.write(byte3);
        // 释放资源
        fos1.close();
    }
}

(6)、小结

2、字节流之FileInputStream

(1)、概念

操作本地文件的字节输入流 可以将本地文件的数据输入到程序中

(2)、步骤

1、创建对象(让程序和文件之间建立一个通道)

2、读数据

3、释放资源(断开程序和文件之间建立一个通道)

防止java程序占用资源 使得在其它程序中可以打开

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class test4 {
    /*
    1、创建对象(让程序和文件之间建立一个通道)
    2、读数据
    3、释放资源(断开程序和文件之间建立一个通道)
    防止java程序占用资源 使得在其它程序中可以打开
    */
    public static void main(String[] args) throws IOException {
        // 1.创建对象
        FileInputStream fis=new FileInputStream("a.txt");
        // 2.读数据
        // 每次读取一个数据 依次读取 返回值是字符对应的ASCII码值 全部读取完 返回-1
        int read = fis.read();
        while (read!=-1) {
            System.out.print((char) read);
            read = fis.read();
        }
        // 3.释放资源
        fis.close();
        // 输出:
        // java helloworld
    }
}

(3)、细节

细节1:

(4)、循环读取

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

public class test5 {
    public static void main(String[] args) throws IOException {
        // 1.创建对象
        // 该文件不存在
        FileInputStream fis=new FileInputStream("b.txt");
        // 2.读数据
        // 依次读取读取一个数据 指针后移 返回值是字符对应的ASCII码值 如果全部读取完 返回-1
        // ascii码表中不存在acsii码值为-1的字符
        int read;
        while ((read=fis.read())!=-1) {
            System.out.print((char) read);
        }
        // 3.释放资源
        fis.close();
    }
}

(5)、读数据的两种方式

一次读取一个字节在之前我们已经学习了 现在我们重点学习一次读取多个字节

步骤:

1、创建对象(让程序和文件之间建立一个通道)

2、创建动态数组 数组的长度决定了每次最多读取的个数

3、通过对象.read(数组);存放读到的数据 并通过int len存放返回值

4、创建字符串 String str=new String(bytes,0,len);

5、输出字符串 即可输出读到的数据

防止java程序占用资源 使得在其它程序中可以打开

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

public class test7 {
    public static void main(String[] args) throws IOException {
        // 1.创建对象
        // 该文件不存在
        FileInputStream fis=new FileInputStream("d.txt");
        // 2.读数据
        // 定义一个长度为4的数组 数组的长度决定了每次最多读取的个数
        // 每次读取的数据都会存放在数组中 数组是重复利用的 每次存放的数据都会覆盖原来的数据
        byte [] bytes=new byte[4];
        // fis.read(bytes)该方法的返回值是实际读取的数据个数
        int len1=fis.read(bytes);
        System.out.println("第一次读取的数据个数"+len1);
        // 创建字符数组部分内容的字符串 因为字符数组有的数据没有被覆盖 是原来的内容 属于无效数据
        String str1=new String(bytes,0,len1);
        System.out.println(str1);

        int len2=fis.read(bytes);
        System.out.println("第二次读取的数据个数"+len2);
        String str2=new String(bytes,0,len2);
        System.out.println(str2);


        int len3=fis.read(bytes);
        System.out.println("第三次读取的数据个数"+len3);
        String str3=new String(bytes,0,len3);
        System.out.println(str3);

        // 当没有数据可以读取时 fis.read(bytes)的返回值为-1
        int len4=fis.read(bytes);
        System.out.println("第四次读取的数据个数"+len4);// -1

        // 3.释放资源
        fis.close();
    }
}

3、利用FileInputStream、FileOutStream进行文件拷贝

通过边读边写的思想,先将文件读取到程序中,再将程序中的数据写到另一个文件中

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

public class test6 {
    public static void main(String[] args) throws IOException {
        // 1.创建对象
        FileInputStream fis=new FileInputStream("D:\\测试安全\\d.txt");
        FileOutputStream fos=new FileOutputStream("d.txt");
        // 2.读数据
        // 依次读取读取一个数据 指针后移 返回值是字符对应的ASCII码值 如果全部读取完 返回-1
        // ascii码表中不存在acsii码值为-1的字符
        int read;
        while ((read=fis.read())!=-1) {
            // 3.写数据
            // d.txt文件不存在 会创建文件并写入数据
            // 将读取的数据写到文件中
            fos.write(read);
        }
        // 4.释放资源
        // 先开的流最后释放
        fos.close();
        fis.close();
    }
}

当拷贝的文件过大时 我们可以通过一次读取多个数据进行读取 提高速度

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

public class test6 {
    public static void main(String[] args) throws IOException {
        // 1.创建对象
        FileInputStream fis=new FileInputStream("D:\\测试安全\\d.txt");
        FileOutputStream fos=new FileOutputStream("d.txt");
        // 2.读数据
        // 依次读取读取一个数据 指针后移 返回值是字符对应的ASCII码值 如果全部读取完 返回-1
        // ascii码表中不存在acsii码值为-1的字符
        int len;
        byte [] bytes=new byte[1024];
        while ((len=fis.read(bytes))!=-1) {
            // 3.写数据
            // d.txt文件不存在 会创建文件并写入数据
            // 将读取的数据写到文件中
            fos.write(bytes,0,len);
        }
        // 4.释放资源
        // 先开的流最后释放
        fos.close();
        fis.close();
    }
}

4、利用FileInputStream、FileOutStream进行文件夹拷贝

无论是图片、word、excel、视频等都可以进行复制

如果是文件则直接拷贝 如果是文件夹则需要递归

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

public class 复制文件夹 {
    public static void main(String[] args) throws IOException {
        // 将f1文件的内容拷贝到f2中
        File f1=new File("D:\\测试安全");
        File f2=new File("D:\\测试安全复制版");
        copydir(f1,f2);
    }
    private static void copydir(File f1, File f2) throws IOException {
        // 如果f2文件夹存在则不做任何处理 如果不存在 则创建文件夹
        f2.mkdirs();

        // 获取f1文件夹下的所有内容
        File[] files = f1.listFiles();

        for (File file : files) {
            // 判断是否为文件
            // 如果是文件则边读边写 直接赋值
            if(file.isFile()){
                // 创建该file文件的字节输入流 用来读取file文件内容到程序中
                FileInputStream fis=new FileInputStream(file);
                // 创建该file文件的字节输出流 用来将程序的内容写到读取new File(f2,file.getName())路径表示的文件中
                FileOutputStream fos=new FileOutputStream(new File(f2,file.getName()));
                // 创建字节数组 用来一次最多读取1k个字节 提高读取速度
                byte [] bytes=new byte[1024*10];
                // 实际读取的字节数
                int len;
                while ((len=fis.read(bytes))!=-1) {
                    // 写数据 读多少写多少
                    fos.write(bytes,0,len);
                }
                // 关闭该file文件的字节输出流
                fos.close();
                // 关闭该file文件的字节输入流
                fis.close();
            }
            // 如果不是文件则递归
            else {
                copydir(file,new File(f2,file.getName()));
            }
        }
    }
}

5、利用FileInputStream、FileOutStream进行文件夹文件加密

通过字节流读取文件和写入文件 都是写入对应的编码值

对文件进行加密时 我们就可以将读取文件a得到的字节数据(编码值)进行改变写入文件b

对文件b进行解密时我们就可以将读取文件b得到的字节数据(编码值)进行改变使之变成与读取文件a得到的字节数据一样的数据写入文件c 

如何实现?

之间我们学习过异或运算 数1与另一个数2异或两次即可得到原来的数1

我们就可以将数1与另一个数2异或一次看成加密过程

将数1与另一个数2的结果再与数2异或的过程看成解密过程

加密:

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

public class 加密 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis=new FileInputStream("D:\\测试安全\\c\\机器人.png");
        FileOutputStream fos=new FileOutputStream("D:\\测试安全\\c\\机器人2.png");
        int read;
        // 加密过程
        while ((read=fis.read())!=-1){
            fos.write(read^2);
        }
        fos.close();
        fis.close();
    }
}

解密:

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

public class 解密 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis=new FileInputStream("D:\\测试安全\\c\\机器人2.png");
        FileOutputStream fos=new FileOutputStream("D:\\测试安全\\c\\机器人3.png");
        int read;
        // 解密过程
        while ((read=fis.read())!=-1){
            fos.write(read^2);
        }
        fos.close();
        fis.close();
    }
}

6、io流字符集

io流字符集包括ASCII字符集、GBK字符集、Unicode字符集

数据存储在计算机的形式都是补码!!!

(1)、ASCII字符集

ASCII字符集没有中文的编码

(2)、GBK字符集

存储英文和ASCII字符集存储英文的格式一样

(3)、Unicode字符集

为了统一各个国家的编码 创建了Unicode字符集

Unicode字符集包含了以下三种编码规则:UTF-8、UTF-16、UTF-32

现在我们详细介绍UTF-8的编码规则:

在UTF-8的编码规则下,英文占一个字节,中文占3个字节(且第一个字节的首位是1)

如果是英文,找到Unicode字符集下的编码值后在前面加0即可得到它存储在计算机的值

如果是中文,找到Unicode字符集下的编码值后将其按4 6 6 分成3部分,第一部分前面加1110,第二部分前面加10,第三部分前面加10,即可得到它存储在计算机的值

(4)、字符集小结

(5)、产生乱码的原因

1、读取数据时没有读完整个汉字 

因为一个汉字按GBK字符集需要2个字节的存储空间、按Unicode字符集需要3个字节的存储空间,而字节流每次读取一个字节,就会导致汉字未读完

2、解码规则和编码规则不一致

因为一个汉字按GBK字符集需要2个字节的存储空间、按Unicode字符集需要3个字节的存储空间,如果按Unicode字符集中UTF-8编码而用GBK字符集进行解码就会将3个字节拆分成2个字节、1个字节进行解码

(6)、解决乱码

(7)、编码

在idea中默认的编码方式是UTF-8,在eclipse默认的编码方式是GBK

语法1:

字符串.getBytes(); 使用平台默认的方式进行编码

语法2:

字符串.getBytes(指定字符集); 使用指定字符集进行编码

import java.io.FileInputStream;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;

public class test8 {
    public static void main(String[] args) throws UnsupportedEncodingException {
        String str1="ok世界";
        // 系统默认的编码方式进行编码
        byte[] bytes1 = str1.getBytes();
        System.out.println(Arrays.toString(bytes1));
        /*
        [111, 107, -28, -72, -106, -25, -107, -116]
        其中111表示o对应的Unicode编码
        107表示k对应的Unicode编码
        -28 -72 -106表示世对应的Unicode编码
        -25 -107 -116表示界对应的Unicode编码
        */

        String str2="ok世界";
        // 指定的编码方式进行编码
        byte[] bytes2 = str2.getBytes("GBK");
        System.out.println(Arrays.toString(bytes2));
        /*
        [111, 107, -54, -64, -67, -25]
        其中111表示o对应的Unicode编码
        107表示k对应的Unicode编码
        -54 -64表示世对应的Unicode编码
        -67 -25表示界对应的Unicode编码
        */
    }
}

(8)、解码

在idea中默认的解码方式是UTF-8,在eclipse默认的解码方式是GBK

语法1:

new 字符串(字节数组); 使用平台默认的方式进行编码

语法2:

new 字符串(字节数组,指定字符集); 使用指定字符集进行编码

import java.io.FileInputStream;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;

public class test8 {
    public static void main(String[] args) throws UnsupportedEncodingException {
        String str1="ok世界";
        // 系统默认的编码方式进行编码
        byte[] bytes1 = str1.getBytes();
        System.out.println(Arrays.toString(bytes1));
        /*
        [111, 107, -28, -72, -106, -25, -107, -116]
        其中111表示o对应的Unicode编码
        107表示k对应的Unicode编码
        -28 -72 -106表示世对应的Unicode编码
        -25 -107 -116表示界对应的Unicode编码
        */
        // 系统默认的编码方式进行解码
        String s1 = new String(bytes1);
        System.out.println(s1);
        // ok世界

        String str2="ok世界";
        // 指定的编码方式进行编码
        byte[] bytes2 = str2.getBytes("GBK");
        System.out.println(Arrays.toString(bytes2));
        /*
        [111, 107, -54, -64, -67, -25]
        其中111表示o对应的Unicode编码
        107表示k对应的Unicode编码
        -54 -64表示世对应的Unicode编码
        -67 -25表示界对应的Unicode编码
        */
        // 指定编码方式进行解码
        String s2 = new String(bytes2,"GBK");
        System.out.println(s2);
        // ok世界

        // 如果解码方式与编码方式不一致则会出现乱码
        // bytes1是通过Unicode的UTF-8进行编码 而采用GBK进行解码
        String s3 = new String(bytes1,"GBK");
        System.out.println(s3);
        // ok涓栫晫
    }

7、字符流概要

8、字符流之FileReader

(1)、概念

操作本地文件的字符输入流 可以将本地文件的数据读取到程序中

(2)、步骤+细节

1、创建对象(让程序和文件之间建立一个通道)

细节:如果文件不存在则会报错

语法1:

FileReader fr=new FileReader(字符串表示的路径);

语法2:

FileReader fr=new FileReader(文件对象表示的路径);

2、读数据

语法1:无参read方法 一次读取一个数据,返回值为读取的数据(是数据对应的码值),读到末尾返回-1 

字符流对象.read();

语法2:有参read方法  一次读取多个数据,返回值为读取的数据(是数据对应的码值),读到末尾返回-1 

字符流对象.read(字符数组);

细节:

而字节流通通都是一个字节一个字节读取

3、释放资源(断开程序和文件之间建立一个通道)

防止java程序占用资源 使得在其它程序中可以打开

语法:

字符流对象.close();

(3)、无参read方法读取数据

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

public class FileReader字符流 {
    public static void main(String[] args) throws IOException {
        // 1.创建对象 字符串的形式表示路径
        FileReader fr=new FileReader("a.txt");
        // 2.读取数据
        // 字符流的底层原理还是字节流 读取出的数据还是字符对应的码值的形式
        // 一次读取一个字节 遇到中文读取3个字节
        int ch;
        while ((ch= fr.read())!=-1) {
            System.out.print((char)ch);
        }
        /*
        java 你好星期六
        我与我周旋久 宁作我
        */
        // 3.释放资源
        fr.close();
    }
}

(4)、有参read方法读取数据

import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;

public class FileReader字符流1 {
    public static void main(String[] args) throws IOException {
        // 1.创建对象 字符串的形式表示路径
        FileReader fr=new FileReader("a.txt");
        // 2.读取数据
        // 字符流的底层原理还是字节流 读取出的数据还是字符对应的码值的形式
        // 一次读取一个字节 遇到中文读取3个字节
        // 此时len表示读取的数据个数 而不是数据
        int len;
        // 定义一个长度为2的数组 数组的长度决定了每次最多读取的个数
        // 每次读取的数据都会存放在数组中 数组是重复利用的 每次存放的数据都会覆盖原来的数据
        char [] c=new char[2];
        while ((len= fr.read(c))!=-1) {
            // 创建字符串c部分内容的字符串
            String str=new String(c,0,len);
            System.out.print(str);
        }
        /*
        java 你好星期六
        我与我周旋久 宁作我
        */
        // 3.释放资源
        fr.close();
    }
}

9、字符流之FileWrite

(1)、构造方法

当append为true 表示打开续写开关 默认情况下是关闭续写开关

(2)、成员方法(写入数据的5种方式)

写一个字符:

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

public class FileWrite字符流2 {
    public static void main(String[] args) throws IOException {
        // 1.创建对象 字符串的形式表示路径
        // true表示文件不是覆盖写 是追加写
        FileWriter fw=new FileWriter("a.txt",true);
        // 2.写入数据
        // fw.write(字符编码);
        // 一次写入一个字符(无论是英文字符还是汉字字符)
        // write方法会根据字符集的编码方式进行编码 如果是汉字则为3个字节 英文则为一个字节 并把编码之后的数据写到文件中
        fw.write(97);
        fw.write(25105);
        // 3.释放资源
        fw.close();
    }

写一个字符串:

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

public class FileWrite字符流2 {
    public static void main(String[] args) throws IOException {
        // 1.创建对象 字符串的形式表示路径
        // true表示文件不是覆盖写 是追加写
        FileWriter fw=new FileWriter("a.txt",true);
        // 2.写入数据
        // fw.write(字符串);
        // 一次写入一个字符串
        // 英文状态下的标点符号是英文字符 中文状态下的标点符号是汉字字符
        fw.write("java你好!");
        // 3.释放资源
        fw.close();
    }
}

写一个字符串的一部分:

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

public class FileWrite字符流2 {
    public static void main(String[] args) throws IOException {
        // 1.创建对象 字符串的形式表示路径
        // true表示文件不是覆盖写 是追加写
        FileWriter fw=new FileWriter("a.txt");
        // 2.写入数据
        // fw.write(字符串,开始索引,总个数);
        // 一次写入一个字符串的一部分
        // 英文状态下的标点符号是英文字符 中文状态下的标点符号是汉字字符
        fw.write("java你好!",0,4);
        // 3.释放资源
        fw.close();
    }
}

写一个字符数组:

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

public class FileWrite字符流2 {
    public static void main(String[] args) throws IOException {
        // 1.创建对象 字符串的形式表示路径
        // true表示文件不是覆盖写 是追加写
        FileWriter fw=new FileWriter("a.txt");
        // 2.写入数据
        // fw.write(字符数组);
        // 一次写入一个字符数组
        // 英文状态下的标点符号是英文字符 中文状态下的标点符号是汉字字符
        char [] chs={'j','a','v','a','你','好'};
        fw.write(chs);
        // 3.释放资源
        fw.close();
    }
}

(3)、书写细节

10、字符流和字节流的使用场景

11、缓冲流概要

为了提高字节流和字符流的效率 java设计了缓冲流

但是缓冲流是对字节流和字符流进行包装 真正读取和写入数据的还是字节流和字符流

12、缓冲流之字节缓冲流

字节缓冲流的使用与字节缓冲流的使用很相似

(1)、构造方法

利用字节缓冲流进行拷贝:

一次读取一个字节

import java.io.*;

public class 字节缓冲流拷贝 {
    public static void main(String[] args) throws IOException {
        // 1.创建字节缓冲流
        BufferedInputStream bis= new BufferedInputStream(new FileInputStream("D:\\测试安全\\d.txt"));
        BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("D:\\测试安全\\dd.txt"));
        // 2.循环读取并写入数据
        int len;
        while ((len=bis.read())!=-1){
            bos.write(len);
        }
        // 3.关闭流(不需要关闭字节输入流、字节输出流 只需要关闭字节缓冲流)
        bos.close();
        bis.close();
    }
}

利用字节缓冲流进行拷贝:

一次读取多个字节:

import java.io.*;

public class 字节缓冲流拷贝 {
    public static void main(String[] args) throws IOException {
        // 1.创建字节缓冲流
        BufferedInputStream bis= new BufferedInputStream(new FileInputStream("D:\\测试安全\\d.txt"));
        BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("D:\\测试安全\\ddd.txt"));
        // 2.循环读取并写入数据
        // 一次读取多个字节
        // len表示每次读取的实际个数
        int len;
        // 创建bytes 用来存放每次读取的数据的码值 20表示每次读取最多的个数
        byte [] bytes=new byte[20];
        while ((len=bis.read(bytes))!=-1){
            bos.write(bytes,0,len);
        }
        // 3.关闭流(不需要关闭字节输入流、字节输出流 只需要关闭字节缓冲流)
        bos.close();
        bis.close();
    }

13、缓冲流之字符缓冲流

(1)、构造方法

(2)、特有方法

细节:

readLine()方法读取数据 是一次读取一行数据 遇到回车换行就停止

且不会将回车换行读取到内存中 如果使用println进行打印则会一行一行输出

如果使用print进行打印则不会一行一行输出 会粘在一起

import java.io.*;

public class 字符缓冲流拷贝 {
    public static void main(String[] args) throws IOException {
        // 1.创建字节缓冲流
        BufferedReader br= new BufferedReader(new FileReader("D:\\测试安全\\c.txt"));
        BufferedWriter bw=new BufferedWriter(new FileWriter("D:\\测试安全\\cc.txt"));
        // 2.循环读取并写入数据
        // readLine()方法读取数据 是一次读取一行数据 遇到回车换行就停止
        // 且不会将回车换行读取到内存中
        String line;
        // 当读取完成line的返回值为null
        while ((line=br.readLine())!=null){
            System.out.println(line);
        }
        // 3.关闭流(不需要关闭字节输入流、字节输出流 只需要关闭字节缓冲流)
        br.close();
    }
}

细节2:

换行 这是BufferedWriter特有的方法 在之前通过字节流或字符流换行 对于不同的操作系统书写的方式不一样

而BufferedWriter只需要通过newLine方法即可在不同的操作系统下实现换行

细节3:

如果要实现续写 则需要在创建FileWriter时加上true 不是在创建BufferedWriter时添加true

14、缓冲流小结

15、拷贝文件方式总结

字节基本流 一次读取一个字节:

import java.io.*;

public class 拷贝 {
    public static void main(String[] args) throws IOException {
        // 字节基本流 一次读取一个字节
        // 1.创建对象
        FileInputStream fis=new FileInputStream("D:\\测试安全\\d.txt");
        FileOutputStream fos=new FileOutputStream("D:\\测试安全\\dd.txt");
        // 2.读数据
        // 依次读取读取一个数据 指针后移 返回值是字符对应的ASCII码值 如果全部读取完 返回-1
        // ascii码表中不存在acsii码值为-1的字符
        int len;
        while ((len=fis.read())!=-1) {
            // 3.写数据
            // d.txt文件不存在 会创建文件并写入数据
            // 将读取的数据写到文件中
            fos.write(len);
        }
        // 4.释放资源
        // 先开的流最后释放
        fos.close();
        fis.close();
    }
}

字节基本流 一次读取一个字节数组:

import java.io.*;

public class 拷贝 {
    public static void main(String[] args) throws IOException {
        // 字节基本流 一次读取一个字节数组
        // 1.创建对象
        FileInputStream fis=new FileInputStream("D:\\测试安全\\d.txt");
        FileOutputStream fos=new FileOutputStream("D:\\测试安全\\dd.txt");
        // 2.读数据
        // 依次读取读取一个数据 指针后移 返回值是字符对应的ASCII码值 如果全部读取完 返回-1
        // ascii码表中不存在acsii码值为-1的字符
        int len;
        byte [] bytes=new byte[8192];
        while ((len=fis.read(bytes))!=-1) {
            // 3.写数据
            // d.txt文件不存在 会创建文件并写入数据
            // 将读取的数据写到文件中
            fos.write(bytes,0,len);
        }
        // 4.释放资源
        // 先开的流最后释放
        fos.close();
        fis.close();
    }
}

字节缓冲流 一次读取一个字节:

import java.io.*;

public class 拷贝 {
    public static void main(String[] args) throws IOException {
        // 字节缓冲流 一次读取一个字节
        // 1.创建字节缓冲流
        BufferedInputStream bis= new BufferedInputStream(new FileInputStream("D:\\测试安全\\d.txt"));
        BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("D:\\测试安全\\ddd.txt"));
        // 2.循环读取并写入数据
        int len;
        while ((len=bis.read())!=-1){
            bos.write(len);
        }
        // 3.关闭流(不需要关闭字节输入流、字节输出流 只需要关闭字节缓冲流)
        bos.close();
        bis.close();
    }
}

字节缓冲流 一次读取一个字节数组:

import java.io.*;

public class 拷贝 {
    public static void main(String[] args) throws IOException {
        // 字节缓冲流 一次读取一个字节数组
        // 1.创建字节缓冲流
        BufferedInputStream bis= new BufferedInputStream(new FileInputStream("D:\\测试安全\\d.txt"));
        BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("D:\\测试安全\\ddd.txt"));
        // 2.循环读取并写入数据
        // 一次读取多个字节
        // len表示每次读取的实际个数
        int len;
        // 创建bytes 用来存放每次读取的数据的码值
        byte [] bytes=new byte[8192];
        while ((len=bis.read(bytes))!=-1){
            bos.write(bytes,0,len);
        }
        // 3.关闭流(不需要关闭字节输入流、字节输出流 只需要关闭字节缓冲流)
        bos.close();
        bis.close();
    }
}

16、字符转化流

(1)、概念

转化流是字节流和字符流之间的桥梁

(2)、利用转化流按照指定的字符编码读取数据

语法:FileReader 对象名=new FileReader(路径, Charset.forName("字符集"));

为了解决这个问题 我们可以指定字符输入流的字符集 使之与文本文件的字符集保持一致

(3)、利用转化流按照指定的字符编码写入数据

语法:FileWriter 对象名=new FileWriter(路径, Charset.forName("字符集"));

为了解决这个问题 我们可以指定字符输出流的字符集 使之与文本文件的字符集保持一致

(4)、利用字节流读取文本文件中的每一行数据

语法:

BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream(路径)));

详细写法:

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;

public class 字节流读取文本文件 {
    public static void main(String[] args) throws IOException {
        // 创建字节输入流
        FileInputStream fis=new FileInputStream("D:\\测试安全\\e.txt");
        // 将字节输入流转化为字符输入流 使之能读取文本文件中的数据 同时指定字符输入流的编码规则为GBK
        InputStreamReader isr=new InputStreamReader(fis, Charset.forName("GBK"));
        // 将字符输入流包装成字符缓冲流 使之能一行一行读取数据
        BufferedReader br=new BufferedReader(isr);
        System.out.println(br.readLine());
        isr.close();
    }
}

简便写法:

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;

public class 字节流读取文本文件 {
    public static void main(String[] args) throws IOException {
        // 将字节输入流转化为字符输入流 使之能读取文本文件中的数据 同时指定字符输入流的编码规则为GBK
        // 将字符输入流包装成字符缓冲流 使之能一行一行读取数据
        BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream("D:\\测试安全\\e.txt"), Charset.forName("GBK")));
        System.out.println(br.readLine());
        br.close();
    }
}

(5)、小结

16、序列化流

只有字节流才有序列化流,字符流没有序列化流

(1)、概念

通过序列化流可以将java对象写在本地文件中

(2)、构造方法/成员方法

通过序列化流可以将java对象写在本地文件中

构造方法语法:

ObjectOutputStream 对象名称=new ObjectOutputStream(new FileOutputStream(路径));​​​​​​​

成员方法语法:

序列化流对象.writeObject(要写入的java对象);

细节:

要写入的java对象必须实现Serializable接口才能被写入本地文件

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

public class 序列化流 {
    public static void main(String[] args) throws IOException {
        // 1.创建对象
        Student s = new Student("zhangsan", 23);
        // 2.创建序列化流
        // 需要传入字节输出流作为参数
        ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("D:\\测试安全\\ee.txt"));
        // 3.写对象到本地文件
        oos.writeObject(s);
        // 4.释放资源
        oos.close();
    }
}
// Student类必须实现Serializable接口才能被写入本地文件
// Serializable没有任何抽象方法 因此Student类必须实现Serializable接口时不需要重写任何方法
class Student implements Serializable {
    private String name;
    private int age;

    public Student() {
    }

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

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "Student{name = " + name + ", age = " + age + "}";
    }
}

17、反序列化流

只有字节流才有反序列化流,字符流没有反序列化流

(1)、概念

通过序列化流可以将本地文件中的java对象读取到程序中

(2)、构造方法/成员方法

构造方法语法:

ObjectInputStream 对象名称=new ObjectInputStream(new FileInputStream(路径));

成员方法语法:

序列化流对象.readObject();

18、打印流概要

打印流是高级流,只有输出流才有打印流

因此打印流不能从文件读取数据 只能打印数据到文件中

19、打印流之字节打印流

(1)、构造方法

重点掌握第1、2种方法

(2)、特有方法

特有方法可以将数据原样打印在文件上

常规方法是将码值为该数字对应的字符打印在文件中

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;

public class 打印流 {
    public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
        // 1.创建字节打印流的对象
        PrintStream ps=new PrintStream(new FileOutputStream("a.txt"),true,"UTF-8");
        // 2.打印数据
        ps.println(97);// 打印任意数据 包括了三步:写出、自动刷新、换行
        ps.print("臣妾要告发熹贵妃私通");// 打印任意数据 不换行
        ps.printf("那年杏花微雨 你说你是%s","果郡王");// 打印含有占位符的语句 不换行
        // 3.关闭资源
        ps.close();
    }
}

19、打印流之字符打印流

字符打印流与字节打印流的用法很相似

(1)、构造方法

(2)、特有方法

特有方法可以将数据原样打印在文件上

import java.io.*;

public class 打印流 {
    public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
        // 1.创建字节打印流的对象
        // 如果自动刷新为false 则不会将内容立刻打印在文件上
        PrintWriter ps=new PrintWriter(new FileOutputStream("a.txt"),true);
        // 2.打印数据
        ps.write(97);// 普通打印
        ps.println();
        ps.println(97);// 打印任意数据 包括了三步:写出、自动刷新、换行
        ps.print("这福气给你要不要啊");// 打印任意数据 不换行
        ps.printf("我儿%s必定高中","长柏");// 打印含有占位符的语句 不换行
        // 3.关闭资源
        ps.close();
        
        /*补充
        在Java中,当使用I/O流(如FileOutputStream、PrintWriter等)进行文件操作时,数据通常不是直接写入文件的。
        相反,它们首先被写入到一个内部缓冲区中,以提高写入效率。当你调用写入方法(如write(), println(), print(), printf()等)时,数据实际上是被放入这个缓冲区中的。
        只有当缓冲区满了,或者当你显式地调用flush()方法,或者关闭流(这通常会自动调用flush()方法)时,缓冲区中的数据才会被真正写入到文件或目标输出中。
        在你的例子中,你创建了一个PrintWriter对象,并指定了autoFlush参数为false,这意味着每次调用写入方法后不会自动刷新缓冲区。
        然后,你写入了一些数据,但你没有调用flush()方法,也没有关闭流。
        由于你没有关闭流(即没有调用ps.close()),也没有调用flush()方法,缓冲区中的数据就一直在内存中,没有被写入到文件a.txt中。这就是为什么你打开文件时看不到任何内容的原因。
        但是,当你调用ps.close()时,PrintWriter对象的close()方法会被调用。
        这个方法不仅关闭了流,还会确保所有待写入的数据都被刷新(即写入)到目标文件中。这就是为什么在调用ps.close()之后,你可以在文件中看到写入的数据。
        所以,为了避免数据丢失或看不到写入的内容,你应该始终在完成写入操作后关闭流,或者使用flush()方法手动刷新缓冲区。
        但在实际开发中,更常见的做法是使用try-with-resources语句来自动管理资源(包括流的关闭),这样可以确保即使发生异常,资源也能被正确关闭。*/
    }
}

  • 24
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java IO编程是Java语言中的一个重要组成部分,用于处理输入输出流,包括文件读取、网络通信、数据库操作等。以下是Java IO编程的详细介绍: 1. Java IO模型 Java IO模型由InputStream和OutputStream两个抽象类构成。InputStream和OutputStream提供了大量的方法用于处理字节流输入输出。 2. 字节流和字符流 Java IO中的流分为两种:字节流和字符流。字节流主要用于二进制数据的读取和入,而字符流主要用于字符数据的读取和入。字节流处理的是字节数据,字符流处理的是字符数据。 3. 文件输入输出流 Java提供了FileInputStream和FileOutputStream用于读取和文件中的数据。FileInputStream从文件中读取数据,FileOutputStream将数据文件中。 4. 缓冲流 缓冲流是Java IO中常用的一种流,可以通过缓存机制提升输入输出性能。BufferedInputStream和BufferedOutputStream可以增加字节输入输出时的缓冲区大小,从而提高读性能,BufferedReader和BufferedWriter可以增加字符输入输出时的缓冲区大小,提高读性能。 5. 对象输入输出流 ObjectInputStream和ObjectOutputStream可以用来读取和Java对象。这两个流用于对象的序列化和反序列化,将对象转化为字节序列,或将字节序列转化为对象。 6. 网络输入输出流 Java提供了Socket、ServerSocket、DatagramSocket等类用于网络通信。对于网络输入输出,可以使用DataInputStream和DataOutputStream进行读,也可以使用BufferedReader和PrintWriter进行读。 7. 转换流 转换流可以用来转换字节流和字符流之间的读,比如InputStreamReader和OutputStreamWriter可以将字节流转换为字符流,FileReader和FileWriter也可以转换为字符流。 8. 数据库输入输出流 Java中提供了JDBC(Java Database Connectivity)用于数据库操作。JDBC中的输入输出流用于读取和入数据库中的数据。 以上是Java IO编程的详细介绍,希望能对您有帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值