IO流

I/O流

存储和读取数据的解决方案

字节流(所有类型的文件)

字节输入流(InputStream)

书写步骤

  1. 创建字节输入流对象
    • 如果文件不存在,就直接报错
  2. 读数据
    • 细节一:一次读一个字节,读出来的是数据在ASCII上对应的数字
    • 细节二:读到文件末尾了,read方法返回-1
  3. 释放资源
    • 每次使用完流之后都要释放资源
import java.io.FileInputStream;
import java.io.IOException;

/**
 * 字节输入流FileInputStream
 * 实现需求:读取文件中的数据
 */
public class Demo01 {
    public static void main(String[] args) throws IOException {
        //1.创建对象
        FileInputStream fis = new FileInputStream("F:\\code\\基础语法\\a.txt");
        //2.读取数据
        int b1 = fis.read();
        System.out.println(b1); //97
        int b2 = fis.read();
        System.out.println((char)b2); //b
        //3.释放资源
        fis.close();
    }
}

FileInputSteam循环读取

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

/**
 * FileInputSteam循环读取
 */
public class Demo02 {
    public static void main(String[] args) throws IOException {
        //1.创建对象
        FileInputStream fis = new FileInputStream("F:\\code\\基础语法\\a.txt");
        //2.循环读取
        int b;
        while ((b = fis.read()) != -1){
            System.out.print((char)b);
        }
        //3.释放资源
        fis.close();
    }
}

字节输出流(OutputStream)

书写步骤

  1. 创建字节输出流对象
    • 细节一:参数是字符串表示的路径或者是File对象都是可以的
    • 细节二:如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的
    • 细节三:如果文件已经存在,则会清空文件
  2. 写数据
    • write方法的参数是整数,但是实际上写到本地文件中的是整数在ASCII上对应的字符
  3. 释放资源
    • 每次使用完流之后都要释放资源
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * 字节输出流FileOutputStream
 * 实现需求:写出一段文字到本地文件中
 */
public class Demo01 {
    public static void main(String[] args) throws IOException {
        //1.创建对象
        FileOutputStream fos = new FileOutputStream("F:\\code\\基础语法\\a.txt");
        //2.写出数据
        fos.write(97);
        //3.释放资源
        fos.close();
    }
}

FileOutputStream写数据的三种方式

方法名称 说明
void write(int b) 一次写一个字节数据
void write(byte[] b) 一次写一个字节数组数据
void write(byte[] b,int off,int len) 一次写一个字节数组的部分数据
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * void write(int b)
 * void write(byte[] b)
 * void write(byte[] b,int off,int len) //byte[] b:数组  int off:起始索引  int len:个数
 */
public class Demo02 {
    public static void main(String[] args) throws IOException {
        //1.创建对象
        FileOutputStream fos = new FileOutputStream("F:\\code\\基础语法\\a.txt");
        //2.写出数据
        //fos.write(97); //a
        //fos.write(98); //b

        //byte[] bytes = {97,98,99,100,101}; //abcde
        //fos.write(bytes);

        byte[] bytes = {97,98,99,100,101};
        fos.write(bytes,1,2);
        
        //3.释放资源
        fos.close();
    }
}

换行和续写

换行:再次写出一个换行符就可以了

  • windows:\r\n
  • Linux:\n
  • Mac:\r

续写:如果想要续写,打开续写开关即可

​ 开关位置:创建对象的第二个参数

​ 默认false:表示关闭续写,此时创建对象会清空文件

​ 手动传递true:表示打开续写,此时创建对象不会清空文件

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

/**
 * 换行和续写
 */
public class Demo03 {
    public static void main(String[] args) throws IOException {
        //1.创建对象
        FileOutputStream fos = new FileOutputStream("F:\\code\\基础语法\\a.txt",true);
        //2.写出数据
        String str1 = "abc";
        byte[] bytes1 = str1.getBytes();
        fos.write(bytes1);

        String wrap = "\r\n";
        byte[] bytes2 = wrap.getBytes();
        fos.write(bytes2);

        String str2 = "666";
        byte[] bytes3 = str2.getBytes();
        fos.write(bytes3);
        //3.释放资源
        fos.close();
    }
}

文件拷贝

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

/**
 * 练习:文件拷贝
 */
public class Demo01 {
    public static void main(String[] args) throws IOException {


        long beginTime = System.currentTimeMillis();
        copyFile();
        long endTime = System.currentTimeMillis();
        System.out.println("拷贝文件花费了"+(endTime-beginTime)+"毫秒");
    }

    public static void copyFile() throws IOException {
        //1.创建对象
        FileInputStream fis = new FileInputStream("C:\\Users\\86155\\Videos\\Captures\\a.mp4");
        FileOutputStream fos = new FileOutputStream("F:\\code\\基础语法\\copy.mp4");
        //2.拷贝
        //核心思想:边读边写
        int b;
        while ((b = fis.read()) != -1){
            fos.write(b);
        }
        //3.释放资源
        //规则:先开的最后关闭
        fos.close();
        fis.close();
    }
}

FileInputSteam一次读取多个字节

方法名称 说明
public int read() 一次读一个字节数据
public int read(byte[] buffer) 一次读一个字节数组数据
import java.io.FileInputStream;
import java.io.IOException;

public class Demo02 {
    public static void main(String[] args) throws IOException {
        //1.创建对象
        FileInputStream fis = new FileInputStream("F:\\code\\基础语法\\a.txt");
        //2.读取数据
        byte[] bytes = new byte[2];
        //一次读取多个字节数据,具体读多少,跟数组的长度有关
        //返回值:本次读取到了多少个字节数据
        int len1 = fis.read(bytes);
        System.out.println(len1); //2
        String str1 = new String(bytes,0,len1);
        System.out.println(str1);

        int len2 = fis.read(bytes);
        System.out.println(len2); //2
        String str2 = new String(bytes,0,len2);
        System.out.println(str2);

        int len3 = fis.read(bytes);
        System.out.println(len3); //1
        String str3 = new String(bytes,0,len3);
        System.out.println(str3);
        //3.释放资源
        fis.close();
    }
}
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Demo03 {
    public static void main(String[] args) throws IOException {
        long beginTime = System.currentTimeMillis();
        
        //1.创建对象
        FileInputStream fis = new FileInputStream("C:\\Users\\86155\\Videos\\Captures\\a.mp4");
        FileOutputStream fos = new FileOutputStream("F:\\code\\基础语法\\copy.mp4");
        //2.拷贝
        int len;
        byte[] bytes = new byte[104 * 1024 * 5];
        while ((len = fis.read(bytes)) != -1){
            fos.write(bytes,0,len);
        }
        //3.释放资源
        //规则:先开的最后关闭
        fos.close();
        fis.close();
        
        long endTime = System.currentTimeMillis();
        System.out.println("拷贝文件花费了"+(endTime-beginTime)+"毫秒");
    }
}

字节缓冲流

原理:底层自带了长度为8192的缓冲区提高性能

方法名称 说明
public BufferedInputStream(InputStream is) 把基本流包装成高级流,提高读取数据的性能
public BufferedOutputStream(OutputStream os) 把基本流包装成高级流,提高写出数据的性能
import java.io.*;

public class Demo01 {
    public static void main(String[] args) throws IOException {
        //1.创建缓冲流对象
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("F:\\code\\基础语法\\a.txt"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("F:\\code\\基础语法\\copy.txt"));
        //2.循环读取并写到目的地
        int b;
        while ((b = bis.read()) != -1){
            bos.write(b);
        }
        //3.释放资源
        bos.close();
        bis.close();
    }
}
import java.io.*;

public class Demo02 {
    public static void main(String[] args) throws IOException {
        //1.创建缓冲流对象
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("F:\\code\\基础语法\\a.txt"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("F:\\code\\基础语法\\copy2.txt"));
        //2.拷贝(一次读写多个字节)
        byte[] bytes = new byte[1024];
        int len;
        while ((len = bis.read(bytes)) != -1){
            bos.write(bytes,0,len);
        }
        //3.释放资源
        bos.close();
        bis.close();
    }
}

序列化流/操作对象输出流

可以把Java中的对象写到本地文件中

细节:使用对象输出流将对象保存到文件时会出现NotSerializableException异常

解决方案:需要让Javabean类实现Serializable接口

构造方法 说明
public ObjectOutputStream(OutputStream out) 把基本流包装成高级流
成员方法 说明
public final void writeObject(Object obj) 把对象序列化(写出)到文件中
import java.io.Serializable;

/**
 * Serializable接口里面没有抽象方法,标记型接口
 * 一旦实现了这个接口,那么就表示当前的Student类可以被序列化
 */
public class Student implements Serializable {
    private static final long serialVersionUID = 4322507240361300607L;

    private String name;
    private int age;
    //transient:瞬态关键字
    //作用:不会把当前属性序列化
    private transient String address;

    public Student() {
    }

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

    public static long getSerialVersionUID() {
        return serialVersionUID;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                '}';
    }
}

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

public class Demo01 {
    public static void main(String[] args) throws IOException {
        //1.创建对象
        Student s1 = new Student("张三",21,"北京");
        //2.创建序列化流的对象/对象操作输出流
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("F:\\code\\基础语法\\a.txt"));
        //3.写出数据
        oos.writeObject(s1);
        //4.释放资源
        oos.close();
    }
}

反序列化流/操作对象输入流

可以把序列化到本地文件中的对象,读取到程序中来

构造方法 说明
public ObjectInputStream(InputStream out) 把基本流包装成高级流
成员方法 说明
public Object readObject() 把序列化到本地文件中的对象,读取到程序中来
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class Demo02 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //1.创建反序列化流的对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("F:\\code\\基础语法\\a.txt"));
        //2.读取数据
        Student o = (Student) ois.readObject();
        //3.打印对象
        System.out.println(o);
        //4.释放资源
        ois.close();
    }
}

字节打印流PrintStream

特点:

  1. 打印流只操作文件目的地,不操作数据源
  2. 特有的写出方法可以实现,数据原样写出
  3. 特有的写出方法,可以实现自动刷新,自动换行
构造方法 说明
public PrintStream(OutStream/File/String) 关联字节输出流/文件/文件路径
public PrintStream(String filename,Charset charset) 指定字符编码
public PrintStream(OuntputStream out,boolean autoFlush) 自动刷新
public PrintStream(OutputStream out,boolean autoFlush,String encoding) 指定字符编码且自动刷新
成员方法 说明
public void write(int b) 常规方法:规则跟之前一样,将指定的字节写出
public void println(Xxx xx) 特有方法:打印任意数据,自动刷新,自动换行
public void print(Xxx xx) 特有方法:打印任意数据,不换行
public void printf(String format,Object... args) 特有方法:带有占位符的打印语句,不换行
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;

public class Demo01 {
    public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
        //1.创建字节打印流的对象
        PrintStream ps = new PrintStream(new FileOutputStream("F:\\code\\基础语法\\a.txt"),true,Charset.forName("UTF-8"));
        //2.写出数据
        ps.println(97);
        ps.print(true);
        ps.println();
        ps.printf("%s爱%s","我","你");
        //3.释放资源
        ps.close();
    }
}

压缩流

import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class Demo02 {
    public static void main(String[] args) throws IOException {
        //1.创建File对象表示要压缩的文件
        File src = new File("F:\\a.txt");
        //2.创建File对象表示压缩包的位置
        File dest = new File("F:\\");
        //3.调用方法来压缩
        toZip(src,dest);
    }

    /**
     * 作用:压缩
     * 参数一:表示要压缩的文件
     * 参数二:表示压缩包的位置
     */
    public static void toZip(File src,File dest) throws IOException {
        //1.创建压缩流关联压缩包
        ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(new File(dest,"a.zip")));
        //2.创建ZipEntry对象,表示压缩包里面的每一个文件和文件夹
        ZipEntry entry = new ZipEntry("a.txt");
        //3.把ZipEntry对象放到压缩包当中
        zos.putNextEntry(entry);
        //4.把src文件中的数据写到压缩包当中
        FileInputStream fis = new FileInputStream(src);
        int b;
        while ((b = fis.read()) != -1){
            zos.write(b);
        }
        zos.closeEntry();
        zos.close();
    }
}
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class Demo03 {
    public static void main(String[] args) throws IOException {
        //1.创建File对象表示要压缩的文件夹
        File src = new File("F:\\压缩包1");
        //2.创建File对象表示压缩包放在那里(压缩包的父级路径)
        File destParent = src.getParentFile();
        //3.创建File对象表示压缩包的路径
        File dest = new File(destParent, src.getName() + ".zip");
        //4.创建压缩流关联压缩包
        ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(dest));
        //5.获取src里面的每一个文件,变成ZipEntry对象,放入到压缩包当中
        toZip(src,zos,src.getName());
        //6.释放资源
        zos.close();
    }

    /**
     * 作用:获取src里面的每一个文件,变成ZipEntry对象,放入到压缩包当中
     * 参数一:数据源
     * 参数二:压缩流
     * 参数三:压缩包内部的路径
     */
    public static void toZip(File src,ZipOutputStream zos,String name) throws IOException {
        //1.进入src文件夹
        File[] files = src.listFiles();
        //2.遍历数组
        for (File file : files) {
            if (file.isFile()){
                //3.判断-文件,变成ZipEntry对象,放入到压缩包当中
                ZipEntry entry = new ZipEntry(name + "\\" + file.getName());
                zos.putNextEntry(entry);
                //读取文件中的数据,写到压缩包
                FileInputStream fis = new FileInputStream(file);
                int b;
                while ((b = fis.read()) != -1){
                    zos.write(b);
                }
                fis.close();
                zos.closeEntry();
            }else{
                //4.判断-文件夹,递归
                toZip(file,zos,name + "\\" + file.getName());
            }

        }
    }
}

解压缩流

import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class Demo01 {
    public static void main(String[] args) throws IOException {
        //1.创建一个File表示要解压的压缩包
        File src = new File("F:\\压缩包.zip");
        //2.创建一个File表示解压的目的地
        File dest = new File("F:\\");
        //3.调用方法
        unzip(src,dest);
    }

    //定义一个方法用来解压
    public static void unzip(File src,File dest) throws IOException {
        //解压的本质:把压缩包里面的每一个文件或者文件夹读取出来,按照层级拷贝到目的地当中
        //创建一个解压缩流用来读取解压缩包中的数据
        ZipInputStream zip = new ZipInputStream(new FileInputStream(src));
        //要先获取压缩包里面的每一个zipentry对象

        //表示当前在压缩包中获取到的文件或者文件夹
        ZipEntry entry;
        while ((entry = zip.getNextEntry()) != null){
            System.out.println(entry);

            if (entry.isDirectory()){
                //文件夹:需要在目的地dest处创建一个同样的文件夹
                File file = new File(dest,entry.toString());
                file.mkdirs();
            }else{
                //文件:需要读取到压缩包中的文件,并把它存放到目的地dest文件夹中(按照层级目录进行存放)
                FileOutputStream fos = new FileOutputStream(new File(dest,entry.toString()));
                int b;
                while((b = zip.read()) != -1){
                    //写到目的地
                    fos.write(b);
                }
                fos.close();
                //表示在压缩包中的一个文件处理完毕了
                zip.closeEntry();
            }
        }
        zip.close();
    }
}

字符集

  1. 计算机的存储规则:在计算机中,任意数据都是以二进制的形式来存储的

  2. 计算机中最小的存储单元是一个字节

  3. ASCII字符集中,一个英文占一个字节

  4. 简体中文版windows,默认使用GBK字符集

  5. GBK字符集完全兼容ASCII字符集

    • 一个英文占一个字节,二进制第一位是0
    • 一个中文占两个字节,二进制高位字节的第一位是1
  6. Unicode字符集的UTF-8编码格式

    • 一个英文占一个字节,二进制第一位是0,转成十进制是正数
    • 一个中文占三个字节,二进制第一位是1,第一个字节转成十进制是负数

Java中编码和解码的代码实现

Java中编码的方法:

String类中的方法 说明
public byte[] getBytes() 使用默认方式进行编码
public byte[] getBytes(String charsetName) 使用指定方式进行编码

Java中解码的方法:

String类中的方法 说明
String(byte[] bytes) 使用默认方式进行解码
String(byte[] bytes,String charsetName) 使用指定方式进行解码
import java.io.UnsupportedEncodingException;
import java.util.Arrays;

public class Demo01 {
    public static void main(String[] args) throws UnsupportedEncodingException {
        //1.编码
        String str = "ai你呦";
        byte[] bytes1 = str.getBytes();//utf-8
        System.out.println(Arrays.toString(bytes1));

        byte[] gbks = str.getBytes("GBK");
        System.out.println(Arrays.toString(gbks));

        //2.解码
        String str2 = new String(bytes1);
        System.out.println(str2);

        String str3 = new String(bytes1,"GBK");
        System.out.println(str3);
    }
}

字符流(纯文本文件)

字符流的底层其实就是字节流

字符流=字节流+字符集

特点:

  1. 输入流:一次读一个字节,遇到中文时,一次读多个字节
  2. 输出流:底层会把数据按照指定的编码方式进行编码,变成字节再写到文件中

字符输入流(Reader)

书写步骤

  1. 创建字符输入流对象

    构造方法 说明
    public FileReader(File file) 创建字符输入流关联本地文件
    public FileReader(String pathname) 创建字符输入流关联本地文件
    • 如果文件不存在,就直接报错
  2. 读取数据

    成员方法 说明
    public int read() 读取数据,读到末尾返回-1
    public int read(char[] buffer) 读取多个数据,读到末尾返回-1
    • 细节一:按字节进行读取,遇到中文,一次读多个字节,读取后解码,返回一个整数

    • 细节二:读到文件末尾了,read方法返回-1

  3. 释放资源

    成员方法 说明
    public int close() 释放资源/关流
import java.io.FileReader;
import java.io.IOException;

public class Demo01 {
    public static void main(String[] args) throws IOException {
        //1.创建对象并关联本地文件
        FileReader fr = new FileReader("F:\\code\\基础语法\\a.txt");
        //2.读取文件
        int ch;
        while ((ch = fr.read()) != -1){
            System.out.print((char)ch);
        }
        //3.释放资源
        fr.close();
    }
}
import java.io.FileReader;
import java.io.IOException;

public class Demo02 {
    public static void main(String[] args) throws IOException {
        //1.创建对象
        FileReader fr = new FileReader("F:\\code\\基础语法\\a.txt");
        //2.读取数据
        char[] chars = new char[2];
        int len;
        //read(chars):读取数据,解码,强制三步合并了,把强转之后的字符放到数组当中
        //空参的read+强制类型转换
        while ((len = fr.read(chars)) != -1){
            //把数组中的数据变成字符串再进行打印
            System.out.println(new String(chars,0,len));
        }
        //3.释放资源
        fr.close();
    }
}

字符输出流(Writer)

书写步骤

  1. 创建字符输出流对象

    构造方法 说明
    public FileWriter(File file) 创建字符输出流关联本地文件
    public FileWriter(String pathname) 创建字符输出流关联本地文件
    public FileWriter(File file,boolean append) 创建字符输出流关联本地文件,续写
    public FileWriter(String pathname,boolean append) 创建字符输出流关联本地文件,续写
    • 细节一:参数是字符串表示的路径或者File对象都是可以的

    • 细节二:如果文件不存在就会创建一个新的文件,但是要保证父级路径是存在的

    • 细节三:如果文件已经存在,则会清空文件,如果不想清空可以打开续写开关

  2. 写出数据

    成员方法 说明
    void write(int c) 写出一个字符
    void write (String str) 写出一个字符串
    void write(String str,int off,int len) 写出一个字符串的一部分
    void write(char[] cbuf) 写出一个字符数组
    void write(char[] cbuf,int off,int len) 写出一个字符数组的一部分
    • 如果write方法的参数是整数,但是实际上写到本地文件中的是整数在字符集上对应的字符
  3. 释放资源

    • 每次使用完流之后都要释放资源
import java.io.FileWriter;
import java.io.IOException;

public class Demo03 {
    public static void main(String[] args) throws IOException {
        //1.创建对象
        FileWriter fw = new FileWriter("F:\\code\\基础语法\\a.txt",true);
        //2.写数据
        //fw.write(25105);

        //fw.write("你好!!!");

        //String str = "你你你好好好";
        //fw.write(str,2,2);

        char[] chars = {'a','b','c','我'};
        fw.write(chars);


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

字符缓冲流

原理:底层自带了长度为8192的缓冲区提高性能

方法名称 说明
public BufferedReader(Reader r) 把基本流变成高级流
public BufferedWriter(Writer r) 把基本流变成高级流

字符缓冲输入流(BufferedReader)

字符缓冲输入流特有方法 说明
public String readLine() 读取一行数据,如果没有数据可读了,会返回null
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class Demo03 {
    public static void main(String[] args) throws IOException {
        //1.创建字符缓冲输入流的对象
        BufferedReader br = new BufferedReader(new FileReader("F:\\code\\基础语法\\a.txt"));
        //2.读取数据
        //细节:
        //readLine方法在读取的时候,一次读一整行,遇到回车换行结束,但是它不会把回车换行读到内存当中
        //String line = br.readLine();
        //System.out.println(line);

        String line;
        while ((line = br.readLine()) != null){
            System.out.println(line);
        }
        //3.释放资源
        br.close();
    }
}

字符缓冲输出流(BufferedWriter)

字符缓冲输出流特有方法 说明
public void newLine() 跨平台的换行
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class Demo04 {
    public static void main(String[] args) throws IOException {
        //1.创建字符缓冲输出流的对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("F:\\code\\基础语法\\a.txt",true));
        //2.写出数据
        bw.write("我我我");
        bw.newLine();
        bw.write("你你你");
        bw.newLine();
        //3.释放资源
        bw.close();
    }
}

字符转换流

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

字符转换输入流:InputStreamReader

字符转换输出流:OutputStreamWriter

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

/**
 * 利用转换流按照指定字符编码读取
 */
public class Demo01 {
    public static void main(String[] args) throws IOException {
        //1.创建对象并指定字符编码
        InputStreamReader isr = new InputStreamReader(new FileInputStream("F:\\code\\基础语法\\gbkfile.txt"),"GBK");
        //2.读取数据
        int ch;
        while ((ch = isr.read()) != -1){
            System.out.println((char)ch);
        }
        //3.释放资源
        isr.close();

        //替代方案
        //FileReader fr = new FileReader("F:\\code\\基础语法\\gbkfile.txt", Charset.forName("GBK"));
        //2.读取数据
        //int ch;
        //while ((ch = fr.read()) != -1){
            //System.out.println((char)ch);
        //}
        //3.释放资源
        //fr.close();
    }
}
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;

/**
 * 利用转换流按照指定字符集编码写出
 */
public class Demo02 {
    public static void main(String[] args) throws IOException {
        //1.创建转换流的对象
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("F:\\code\\基础语法\\a.txt"),"GBK");
        //2.写入数据
        osw.write("你好");
        //3.释放资源
        osw.close();

        //FileWriter fw = new FileWriter("F:\\code\\基础语法\\b.txt", Charset.forName("GBK"));
        //2.写出数据
        //osw.write("你好");
        //3.释放资源
        //osw.close();
    }
}
import java.io.*;
import java.nio.charset.Charset;

/**
 * 将本地文件中的GBK文件,转成UTF-8
 */
public class Demo03 {
    public static void main(String[] args) throws IOException {
        //1.JDK11以前的方案
        InputStreamReader isr = new InputStreamReader(new FileInputStream("F:\\code\\基础语法\\gbkfile.txt"),"GBK");
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("F:\\code\\基础语法\\b.txt"),"UTF-8");

        int b;
        while ((b = isr.read()) != -1){
            osw.write(b);
        }

        osw.close();
        isr.close();

        //替代方案
        //FileReader fr = new FileReader("F:\\code\\基础语法\\gbkfile.txt", Charset.forName("GBK"));
        //FileWriter fw = new FileWriter("F:\\code\\基础语法\\b.txt",Charset.forName("UTF-8"));

        //int b;
        //while ((b = fr.read()) != -1){
            //fw.write(b);
        //}

        //fr.close();
        //fw.close();
    }
}
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * 利用字节流读取文件中的数据,每次读一整行,而且不能出现乱码
 */
public class Demo04 {
    public static void main(String[] args) throws IOException {
//        FileInputStream fis = new FileInputStream("F:\\code\\基础语法\\b.txt");
//        InputStreamReader isr = new InputStreamReader(fis);
//        BufferedReader br = new BufferedReader(isr);
//
//        String str = br.readLine();
//        System.out.println(str);
//        br.close();

        //替代方案
        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("F:\\code\\基础语法\\b.txt")));
        String line;
        while ((line = br.readLine()) != null){
            System.out.println(line);
        }
        br.close();
    }
}

字符打印流PrintWriter

字符流底层有缓冲区,想要自动刷新需要开启

特点:

  1. 打印流只操作文件目的地,不操作数据源
  2. 特有的写出方法可以实现,数据原样写出
  3. 特有的写出方法,可以实现自动刷新,自动换行
构造方法 说明
public PrintWriter(Write/File/String) 关联字节输出流/文件/文件路径
public PrintWriter(String filename,Charset charset) 指定字符编码
public PrintWriter(Write w,boolean autoFlush) 自动刷新
public PrintWriter(OutputStream out,boolean autoFlush,Charset charset) 指定字符编码且自动刷新
成员方法 说明
public void write(...) 常规方法:规则跟之前一样,将指定的字节写出
public void println(Xxx xx) 特有方法:打印任意类型的数据并且换行
public void print(Xxx xx) 特有方法:打印任意数据,不换行
public void printf(String format,Object... args) 特有方法:带有占位符的打印语句
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class Demo02 {
    public static void main(String[] args) throws IOException {
        //1.创建字符打印流的对象
        PrintWriter pw = new PrintWriter(new FileWriter("F:\\code\\基础语法\\a.txt"),true);
        //2.写出数据
        pw.println("我我哦我我");
        pw.print(true);
        pw.printf("%s爱%s","我","你");
        //3.释放资源
        pw.close();
    }
}

综合练习

1.拷贝文件夹

/**
 * 拷贝文件夹
 */
import java.io.*;

public class Test01 {
    public static void main(String[] args) throws IOException {
        //拷贝一个文件夹,考虑子文件夹
        //1.创建对象表示数据源
        File test = new File("F:\\test");
        //2.创建对象表示目的地
        File dest = new File("F:\\dest");
        //3.调用方法开始拷贝
        copydir(test,dest);
    }

    /**
     * 作用:拷贝文件夹
     * 参数一:数据源
     * 参数二:目的地
     */
    private static void copydir(File test,File dest) throws IOException {
        //递归
        //1.进入数据源
        File[] files = test.listFiles();
        //2.遍历数组
        for (File file : files){
            if (file.isFile()){
                //3.判断文件,拷贝
                FileInputStream fis = new FileInputStream(file);
                FileOutputStream fos = new FileOutputStream(new File(dest,file.getName()));
                byte[] bytes = new byte[1024];
                int len;
                while ((len = fis.read(bytes)) != -1){
                    fos.write(bytes,0,len);
                }
                fos.close();
                fis.close();
            }else{
                //4.判断文件夹,递归
                copydir(file,new File(dest,file.getName()));
            }
        }
    }
}

2.加密和解密文件

/**
 * 加密和解密文件
 */
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Test02 {
    public static void main(String[] args) throws IOException {
        //加密
        //1.创建对象关联原始文件
        FileInputStream fis = new FileInputStream("F:\\code\\基础语法\\gy.jpg");
        //2.创建对象关联加密文件
        FileOutputStream fos = new FileOutputStream("F:\\code\\基础语法\\ency.jpg");
        //3.加密处理
        int b;
        while ((b = fis.read()) != -1){
            fos.write(b ^ 2);
        }
        //4.释放资源
        fos.close();
        fis.close();

        //解密
        //1.创建对象关联原始文件
        FileInputStream fis1 = new FileInputStream("F:\\code\\基础语法\\ency.jpg");
        //2.创建对象关联加密文件
        FileOutputStream fos1 = new FileOutputStream("F:\\code\\基础语法\\redu.jpg");
        //3.加密处理
        int b1;
        while ((b1 = fis1.read()) != -1){
            fos1.write(b1 ^ 2);
        }
        //4.释放资源
        fos.close();
        fis.close();
    }
}

3.将文件中的数据进行排序

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;

/**
 * 将文件中的数据进行排序
 */
public class Test03 {
    public static void main(String[] args) throws IOException {
        //1.读取数据
        FileReader fr = new FileReader("F:\\code\\基础语法\\a.txt");
        StringBuffer sb = new StringBuffer();
        int ch;
        while ((ch = fr.read()) != -1){
            sb.append((char)ch);
        }
        fr.close();
        System.out.println(sb);
        //2.排序
        String str = sb.toString();
        String[] arrstr = str.split("-");

        ArrayList<Integer> list = new ArrayList<>();
        for (String string : arrstr){
            int i = Integer.parseInt(string);
            list.add(i);
        }
        Collections.sort(list);
        System.out.println(list);
        //3.写出
        FileWriter fw = new FileWriter("F:\\code\\基础语法\\a.txt");
        for (int i = 0; i < list.size(); i++) {
            if (i == list.size()-1){
                 fw.write(list.get(i)+"");
            }else{
                fw.write(list.get(i)+"-");
            }
        }
        fw.close();
    }
}

4.四种拷贝方式效率对比

/**
 * 四种拷贝方式效率对比
 */
import java.io.*;

public class Test04 {
    public static void main(String[] args) throws IOException {
        long beginTime = System.currentTimeMillis();
        //method1();
        //method2();
        //method3();
        method4();
        long endTime = System.currentTimeMillis();
        System.out.println("拷贝文件花费了"+(endTime-beginTime)+"毫秒");
    }

    /**
     * 字节流的基本流:一次读写一个字节
     */
    public static void method1() throws IOException {
        //1.创建对象
        FileInputStream fis = new FileInputStream("F:\\code\\基础语法\\a.txt");
        FileOutputStream fos = new FileOutputStream("F:\\code\\基础语法\\a1.txt");
        //2.拷贝
        //核心思想:边读边写
        int b;
        while ((b = fis.read()) != -1){
            fos.write(b);
        }
        //3.释放资源
        //规则:先开的最后关闭
        fos.close();
        fis.close();
    }

    /**
     *  字节流的基本流:一次读写一个字节数组
     */
    public static void method2() throws IOException {
        //1.创建对象
        FileInputStream fis = new FileInputStream("F:\\code\\基础语法\\a.txt");
        FileOutputStream fos = new FileOutputStream("F:\\code\\基础语法\\a1.txt");
        //2.拷贝
        int len;
        byte[] bytes = new byte[104 * 1024 * 5];
        while ((len = fis.read(bytes)) != -1){
            fos.write(bytes,0,len);
        }
        //3.释放资源
        //规则:先开的最后关闭
        fos.close();
        fis.close();
    }

    /**
     * 字节缓冲流:一次读写一个字节
     */
    public static void method3() throws IOException {
        //1.创建缓冲流对象
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("F:\\code\\基础语法\\a.txt"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("F:\\code\\基础语法\\a1.txt"));
        //2.循环读取并写到目的地
        int b;
        while ((b = bis.read()) != -1){
            bos.write(b);
        }
        //3.释放资源
        bos.close();
        bis.close();
    }

    /**
     * 字节缓冲流:一次读写一个字节数组
     */
    public static void method4() throws IOException {
        //1.创建缓冲流对象
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("F:\\code\\基础语法\\a.txt"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("F:\\code\\基础语法\\a1.txt"));
        //2.拷贝(一次读写多个字节)
        byte[] bytes = new byte[1024];
        int len;
        while ((len = bis.read(bytes)) != -1){
            bos.write(bytes,0,len);
        }
        //3.释放资源
        bos.close();
        bis.close();
    }
}

5.将<<出师表>>的文章顺序进行恢复到一个新文件中

/**
 * 将<<出师表>>的文章顺序进行恢复到一个新文件中
 */
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class Test05Case01 {
    public static void main(String[] args) throws IOException {
        //1.读取数据
        BufferedReader br = new BufferedReader(new FileReader("F:\\code\\基础语法\\a.txt"));
        String line;
        ArrayList<String> list = new ArrayList<>();
        while ((line = br.readLine()) != null){
            list.add(line);
        }
        br.close();

        //2.排序
        //排序规则:按照每一行前面的序号进行排序
        Collections.sort(list, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                //获取o1和o2的序号
                int i1 = Integer.parseInt(o1.split("\\.")[0]);
                int i2 = Integer.parseInt(o2.split("\\.")[0]);
                return i1 - i2;
            }
        });

        //3.写出
        BufferedWriter bw = new BufferedWriter(new FileWriter("F:\\code\\基础语法\\csb.txt"));
        for (String str : list){
            bw.write(str);
            bw.newLine();
        }
        bw.close();
    }
}
import java.io.*;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class Test05Case02 {
    public static void main(String[] args) throws IOException {
        //1.读取数据
        BufferedReader br = new BufferedReader(new FileReader("F:\\code\\基础语法\\a.txt"));
        String line;
        TreeMap<Integer, String> tm = new TreeMap<>();
        while ((line = br.readLine()) != null){
            String[] arr = line.split("\\.");
            //0:序号 1:内容
            tm.put(Integer.parseInt(arr[0]),arr[1]);
        }
        br.close();
        System.out.println(tm);

        //2.写出数据
        BufferedWriter bw = new BufferedWriter(new FileWriter("F:\\code\\基础语法\\csb.txt"));
        Set<Map.Entry<Integer,String>> entries = tm.entrySet();
        for (Map.Entry<Integer,String> entry : entries){
            String value = entry.getValue();
            bw.write(value);
            bw.newLine();
        }
        bw.close();
    }
}

6.软件运行次数

/**
 * 软件运行次数
 */
import java.io.*;

public class Test06 {
    public static void main(String[] args) throws IOException {
        //1.把文件中的数据读取到内存中
        BufferedReader br = new BufferedReader(new FileReader("F:\\code\\基础语法\\count.txt"));
        String line = br.readLine();
        int count = Integer.parseInt(line);
        count++;
        //2.判断
        //<=3 正常运行
        //>3 不能运行
        if (count <= 3){
            System.out.println("欢迎使用本软件,第"+count+"次使用免费~");
        }else{
            System.out.println("本软件只能免费试用三次,欢迎您注册会员后继续使用");
        }

        //3.把当前自增后的count写出到文件当中
        BufferedWriter bw = new BufferedWriter(new FileWriter("F:\\code\\基础语法\\count.txt"));
        bw.write(count + "");
        bw.close();
    }
}

7.将多个自定义对象序列化到文件中,但是对象的个数不确定,该如何操作

import java.io.Serializable;

public class Student implements Serializable {
    private static final long serialVersionUID = -2910356930418031274L;
    private String name;
    private int age;
    private String address;

    public Student() {
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                '}';
    }
}
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;

/**
 * 将多个自定义对象序列化到文件中,但是对象的个数不确定,该如何操作
 */
public class Test07 {
    public static void main(String[] args) throws IOException {
        //1.序列化多个对象
        Student s1 = new Student("张三", 21, "北京");
        Student s2 = new Student("李四", 22, "南京");
        Student s3 = new Student("王五", 23, "东京");

        ArrayList<Student> list = new ArrayList<>();
        list.add(s1);
        list.add(s2);
        list.add(s3);

        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("F:\\code\\基础语法\\a.txt"));
        oos.writeObject(list);
        oos.close();
    }
}
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;

public class Test08 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //1.创建反序列化流的对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("F:\\code\\基础语法\\a.txt"));
        //2.读取数据
        ArrayList<Student> list = (ArrayList<Student>)ois.readObject();
        for (Student student : list) {
            System.out.println(student);
        }
        ois.close();
    }
}
posted @ 2023-07-29 15:37  郭岩不会打代码  阅读(13)  评论(0)    收藏  举报