IO流

@

文件操作

File类

作用

java.io.File 类是文件和目录路径名的抽象表示,主要用于文件和目录的创建、查找和删除等操作

构造方法

  1. public File(String pathname)
    通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。
  2. public File(String parent, String child)
    从父路径名字符串和子路径名字符串创建新的 File实例。
  3. public File(File parent, String child)
    从父抽象路径名和子路径名字符串创建新的 File实例。
    在这里插入图片描述
		 // 文件路径名
        String  pathname = "D:\fmjava.txt";
        File file1 = new File(pathname);
        // 文件路径名
        String  pathname2 = "D:\aaa\fmjava.txt";
        File file2 = new File(pathname2);

        // 通过父路径和子路径字符串
        String parent = "d:\aaa";
        String child = "fmjava.txt";
        File file3 = new File(parent, child);

        // 通过父级File对象和子路径字符串
        File parentDir = new File("d:\aaa");
        String child2 = "fmjava.txt";
        File file4 = new File(parentDir, child2);

注意事项

一个File对象代表硬盘中实际存在的一个文件或者目录。
无论该路径下是否存在文件或者目录,都不影响File对象的创建。

常用方法

  1. public String getAbsolutePath()
    返回此File的绝对路径名字符串。
  2. public String getPath()
    将此File转换为路径名字符串。
  3. public String getName()
    返回由此File表示的文件或目录的名称。
  4. public long length()
    返回由此File表示的文件的长度
    在这里插入图片描述
		File f = new File("d:/aaa/fmjava.txt");
        System.out.println("文件绝对路径:"+f.getAbsolutePath());
        System.out.println("文件构造路径:"+f.getPath());
        System.out.println("文件名称:"+f.getName());
        System.out.println("文件长度:"+f.length()+"字节");

        File f2 = new File("d:/aaa");
        System.out.println("目录绝对路径:"+f2.getAbsolutePath());
        System.out.println("目录构造路径:"+f2.getPath());
        System.out.println("目录名称:"+f2.getName());
        System.out.println("目录长度:"+f2.length());

在这里插入图片描述

绝对路径和相对路径

绝对路径:从盘符开始的路径,这是一个完整的路径
相对路径:相对于项目目录的路径,不是盘符开始,从项目名称的位置开始,不带项目名称
在这里插入图片描述

判断功能的方法

  1. public boolean exists()
    此File表示的文件或目录是否实际存在。
  2. public boolean isDirectory()
    此File表示的是否为目录。
  3. public boolean isFile()
    此File表示的是否为文件

在这里插入图片描述

		File f = new File("d:\aaa\fmjava.txt");
       File f2 =new File("d:\aaa");
       // 判断是否存在            
        System.out.println("d:\aaa\fmjava.txt 是否存在:"+f.exists());
        System.out.println("d:\aaa 是否存在:"+f2.exists());
        // 判断是文件还是目录
        System.out.println("d:\aaa 是否是文件:"+f2.isFile());
        System.out.println("d:\aaa 是否是目录:"+f2.isDirectory());

创建删除功能的方法

  1. public boolean createNewFile()
    当且仅当具有该名称的文件尚不存在时,创建一个新的空文件
  2. public boolean delete()
    删除由此File表示的文件或目录
  3. public boolean mkdir()
    创建由此File表示的目录。
  4. public boolean mkdirs()
    创建由此File表示的目录,包括任何必需但不存在的父目录。
    在这里插入图片描述
		// 文件的创建
        File f = new File("aaa.txt");
        System.out.println("是否存在:"+f.exists());// false
        /*createNewFile方法只能当文件不存在的时候创建,如果已经存在了,返回false,不创建文件*/
        System.out.println("是否创建:"+f.createNewFile()); // true
        System.out.println("是否存在:"+f.exists()); // true
        // 目录的创建
        File f2= new File("newDir");
        System.out.println("是否存在:"+f2.exists());// false
        System.out.println("是否创建:"+f2.mkdir()); // true
        System.out.println("是否存在:"+f2.exists());// true
        //创建多级目录
        File f3= new File("newDira\newDirb");
        System.out.println(f3.mkdir());//只能创建一级目录  false
        File f4= new File("newDira\newDirb");
        System.out.println(f4.mkdirs());//使用mkdirs创建多级目录  true
        // 文件的删除
        System.out.println(f.delete());// true
        // 目录的删除
        System.out.println(f2.delete());// true
        System.out.println(f4.delete());// false

目录的遍历

  1. public String[] list()
    返回一个String数组,表示该File目录中的所有子文件或目录。
  2. public File[] listFiles()
    返回一个File数组,表示该File目录中的所有的子文件或目录。
    在这里插入图片描述
		File dir = new File("d:\aaa");
        //获取当前目录下的文件以及文件夹的名称。   
        String[] names = dir.list();
        for(String name : names){
            System.out.println(name);
        }
        System.out.println("-----------");
        //获取当前目录下的文件以及文件夹对象,只要拿到了文件对象,那么就可以获取更多信息       
        File[] files = dir.listFiles();
        for (File file : files) {
            System.out.println(file);
        }

注意事项:调用listFiles方法的File对象,表示的必须是实际存在的目录,否则返回null,无法进行遍历

递归

什么是递归

指在当前方法内调用自己的这种现象。
调用时,要有一个退出的条件,否则会死循环

示例
在这里插入图片描述

计算1 ~ n的和

1到3的和
1+2+3
在这里插入图片描述

 public static void main(String[] args) {
        int num = 3;
        // 调用求和的方法   
        int sum = getSum(num);
        //输出结果   
        System.out.println(sum);
    }
    private static int getSum(int num) {
        /*
        num 为1时 返回1 相当于函数的出口
        * */
        if (num == 1){
            return 1;
        }
        /*
           不为1时, 返回num和num-1的累加和
           递归调用getSum
        * */
        return num + getSum(num-1);
    }

递归求阶乘

10的阶乘10!
1098765432*1
在这里插入图片描述

public static void main(String[] args) {
        int num = 4;
        // 调用求和的方法   
        int sum = getJieCheng(num);
        //输出结果   
        System.out.println(sum);
    }
    private static int getJieCheng(int num) {
        /*
        num 为1时 返回1 相当于函数的出口
        * */
        if (num == 1){
            return 1;
        }
        /*
           不为1时, 返回num和num-1的累加和
           递归调用getSum
        * */
        return num * getJieCheng(num-1);
    }

斐波那契数列

什么是斐波那契数列

又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”
指的是这样一个数列:1、1、2、3、5、8、13、21、34、……

求数列的第6位的值是多少

递归分析
	当位数为1和2时,当前返回的值应该是1;
	当位数为3时,返回值应该=2=1+1;
	当位数为4时,返回值=3=2+1;
	当位数为5时,返回值=5=3+2;
	大于等于3的情况下,当前位数(n)的数值=f(n-1)+f(n-2)

实现过程图解
在这里插入图片描述
示例代码
在这里插入图片描述

public static void main(String[] args) {
        int f = f(3);
        System.out.println(f);
        //数列:1,1,2,3,5,8......
        for (int i=1;i<=15;i++){ //输出15个斐波那契数列
            System.out.print(f(i)+"	");
        }
    }
    public  static int f(int n){
        if( n == 1 || n == 2 )
            return 1;
        else
            return f( n - 1 )+f( n - 2 );
    }

文件搜索

搜索指定目录下指定扩展名的文件
D盘下 aaa目录中所有的 .txt文件
在这里插入图片描述

 public static void printDir(File dir) {
        // 获取子文件和目录            
        File[] files = dir.listFiles();
        // 循环打印   
        for(File file : files){
            if(file.isFile()){
                 // 是文件,判断文件名并输出文件绝对路径        
                if(file.getName().endsWith(".txt")){
                    System.out.println("文件名:"+file.getAbsolutePath());
                }
            }else{
                // 是目录,继续遍历,形成递归
                printDir(file);
            }
        }
    }

IO流

什么是IO

把与计算机之间数据的传输,可以看做是一种数据的流动,按照流动的方向
以内存为基准,分为 输入input 和 输出 output ,即流向内存是输入流,流出内存的输出流
可以理解 把程序当中的数据保存到电脑磁盘,为输出流,把电脑磁盘当中的数据加载到程序当中为输入流

示例图
在这里插入图片描述
IO的分类
根据数据的流向分:

  1. 输入流 把数据从 其他设备 上读取到 内存 中的流。
  2. 输出流 把数据从 内存 中写出到 其他设备 上的流。

根据数据的类型分:

  1. 字节流 以字节为单位,读写数据的流。
  2. 字符流 以字符为单位,读写数据的流。

顶级父类
字节输入流 :InputStream
字节输出流:OutputStream
字符输入流 :Reader
字符输出流:Writer

字节流

字节流概述

一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,都一个一个的字节
在传输时也是使用字节进行传输,我们称之为字节流
字节流可以传输任意文件数据
无论使用什么样的流对象,底层传输的始终为二进制数据

字节输出流

OutputStream: 字节输出流

作用:java.io.OutputStream 抽象类是表示字节输出流的所有类的超类,将指定的字节信息写出到目的地

基本方法

  1. public void close()
    关闭此输出流并释放与此流相关联的任何系统资源
    close方法,当完成流的操作时,必须调用此方法,释放系统资源
  2. public void flush()
    刷新此输出流并强制任何缓冲的输出字节被写出。
  3. public void write(byte[] b)
    将 b.length字节从指定的字节数组写入此输出流。
  4. public void write(byte[] b, int off, int len)
    从指定的字节数组写入 len字节,从偏移量 off开始输 出到此输出流。
  5. public abstract void write(int b)
    将指定的字节输出流

OutputStream 有很多子类, 以上方法子类都可以调用

FileOutputStream类

作用:java.io.FileOutputStream 类是文件输出流,用于将数据写出到文件,继承自OutputStream

构造方法

  1. public FileOutputStream(File file)
    创建文件输出流以写入由指定的 File对象表示的文件。
  2. public FileOutputStream(String name)
    创建文件输出流以指定的名称写入文件。

在这里插入图片描述

		//使用File对象创建流对象               
        File file = new File("a.txt");
        /*此处抛出异常*/
        FileOutputStream fos = new FileOutputStream(file);

        // 使用文件名称创建流对象         
        FileOutputStream fos2 = new FileOutputStream("b.txt");

注意事项

当你创建一个流对象时,必须传入一个文件路径
该路径下,如果没有这个文件,会创建该文件。如果有这个文 件,会清空这个文件的数据,写入新的信息

write(int b)

写出字节
每次可以写出一个字节数据
在这里插入图片描述

		//使用File对象创建流对象               
        File file = new File("a.txt");
        //使用文件名称创建流对象         
        FileOutputStream fos = new FileOutputStream(file);
        //写出数据          
        fos.write(97);//一次只能写一个字节数据
        fos.write(98);
        fos.write(99);
        //  关闭资源            
        fos.close();

注意事项
1. 虽然参数为int类型四个字节,但是只会保留一个字节的信息写出。
2. 流操作完毕后,必须释放系统资源,调用close方法,千万记得。

write(byte[] b)

写出字节数组
可以通过getBytes方法把汉字转成字节数组
在这里插入图片描述

		//使用File对象创建流对象               
        File file = new File("a.txt");
        //使用文件名称创建流对象         
        FileOutputStream fos = new FileOutputStream(file);
        // 字符串转换为字节数组          
        byte[] b = "疯狂代码".getBytes();
        fos.write(b);
        //  关闭资源            
        fos.close();

write(byte[] b, int off, int len)

写出指定长度字节数组
每次写出从off索引开始,len个字节
在这里插入图片描述

		//使用File对象创建流对象               
        File file = new File("a.txt");
        //使用文件名称创建流对象         
        FileOutputStream fos = new FileOutputStream(file);
        // 字符串转换为字节数组          
        byte[] b = "abcde".getBytes();
        fos.write(b,2,2);  //cd
        //  关闭资源            
        fos.close();

数据追加续写

每次程序运行,创建输出流对象,都会清空目标文件中的数据

  1. public FileOutputStream(File file, boolean append)
    创建文件输出流以写入由指定的 File对象表示的 文件。
  2. public FileOutputStream(String name, boolean append)
    创建文件输出流以指定的名称写入文件。

参数介绍
参数中都需要传入一个boolean类型的值
true 表示追加数据
false 表示清空原有数据

写出换行

Windows系统里,换行符号是
示例
在这里插入图片描述

字节输入流

java.io.InputStream

作用

java.io.InputStream 抽象类是表示字节输入流的所有类的超类,可以读取字节信息到内存中。它定义了字节输入 流的基本共性功能方法

基本方法
  1. public void close()
    关闭此输入流并释放与此流相关联的任何系统资源
  2. public abstract int read()
    从输入流读取数据的下一个字节
  3. public int read(byte[] b)
    从输入流中读取一些字节数,并将它们存储到字节数组 b中

FileInputStream

作用

java.io.FileInputStream 类是文件输入流,从文件中读取字节

构造方法

FileInputStream(File file) 
FileInputStream(String name) 

示例

File file = new File("a.txt");
FileInputStream fileInputStream = new FileInputStream(file);
FileInputStream fileInputStream1 = new FileInputStream("a.txt");

注意事项
当你创建一个流对象时,必须传入一个文件路径。该路径下,如果没有该文件,会抛出 FileNotFoundException 。

读取字节数据

read()方法
作用:每次可以读取一个字节的数据,提升为int类型,读取到文件末尾,返回 -1

示例
方式1

	 // 使用文件名称创建流对象           
FileInputStream fis = new FileInputStream("a.txt");
int read = fis.read();
System.out.println((char)read);
int read2 = fis.read();
System.out.println((char)read2);
int read3 = fis.read();
System.out.println((char)read3);
int read4 = fis.read();
System.out.println((char)read4);
int read5 = fis.read();
System.out.println(read5);//-1

方式2

	// 使用文件名称创建流对象           
FileInputStream fis = new FileInputStream("a.txt");
int b;
while ((b = fis.read())!= -1){
    System.out.println((char)b);
}

read(byte[] b)方法
作用:每次读取b的长度个字节到数组中,返回读取到的有效字节个数,读 取到末尾时,返回 -1

public static void main(String[] args) throws Exception {
        // 使用文件名称创建流对象           
        FileInputStream fis = new FileInputStream("a.txt");//abcd
        //定义变量作为有效个数
        int len;
        // 定义字节数组,作为装字节数据的容器 
        byte[] b = new byte[2];
        while ((len=fis.read(b)) != -1){
            //每次读取后,把数组变成字符串打印
            System.out.println(new String(b));
        }
        fis.close();
    }

复制图片

在这里插入图片描述

public static void main(String[] args) throws Exception {
        //指定数据源        
        FileInputStream fis = new FileInputStream("D:\logo.jpg");
        //指定目的地
        FileOutputStream fos = new FileOutputStream("copyLogo.jpg");
        byte[] b = new byte[1024];
        int len;//在外面声明变量, 不用每次循环时, 创建新的变量
        while ((len = fis.read(b)) != -1){
            fos.write(b,0,len);
        }
        fos.close();
        fis.close();

    }

字符流

什么是字符流

当使用字节流读取文本文件时,可能会有一个小问题。
就是遇到中文字符时,可能不会显示完整的字符,那是因为 一个中文字符可能占用多个字节存储。
所以Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文 件。

Reader类

作用

java.io.Reader 抽象类是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中。
它定义了字符输入 流的基本共性功能方法

基本方法

  1. public void close()
    关闭此流并释放与此流相关联的任何系统资源
  2. public int read()
    从输入流读取一个字符。
  3. public int read(char[] cbuf)
    从输入流中读取一些字符,并将它们存储到字符数组 cbuf中 。

FileReader类

作用

java.io.FileReader 类是读取字符文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。

构造方法

  1. FileReader(File file)
  2. FileReader(String fileName)

注意事项
当你创建一个流对象时,必须传入一个文件路径。类似于FileInputStream

读取字符数据

read 方法
每次可以读取一个字符的数据,提升为int类型,读取到文件末尾,返回 -1

public static void main(String[] args) throws Exception {
        //使用文件名称创建流对象
        FileReader fr = new FileReader("fmjava.txt");
        int b;//定义变量保存数据
        while ((b = fr.read()) != -1){
            System.out.println((char)b);
        }
        fr.close();
    }

read(char[] cbuf)
每次读取b的长度个字符到数组中,返回读取到的有效字符个数, 读取到末尾时,返回 -1在这里插入图片描述
使用上面这种方法会发现,如果是5个字符的时候 会多读取一个, 是因为chars中内容没有被清空
在这里插入图片描述
指定有效个数

FileWriter类

作用

java.io.FileWriter 类是写出字符到文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。

构造方法

  1. FileWriter(File file)
  2. FileWriter(String fileName)

当你创建一个流对象时,必须传入一个文件路径,类似于FileOutputStream。

write(int b)

作用
每次可以写出一个字符数

示例

FileWriter fw = new FileWriter("fmjava.txt",true);
fw.write(97);
fw.write('b');
fw.write(30000);
//关闭资源时,与FileOutputStream不同
//如果不关闭,数据只是保存到缓冲区,并未保存到文件。
fw.close();

关闭和刷新
刷新
因为内置缓冲区的原因,如果不关闭输出流,无法写出字符到文件中。但是关闭的流对象,是无法继续写出数据 的。
如果我们既想写出数据,又想继续使用流,就需要 flush 方法了
flush
刷新缓冲区,流对象可以继续使用
close
关闭流,释放系统资源。关闭前会刷新缓冲区。

示例

	 FileWriter fw = new FileWriter("fmjava.txt",true);
fw.write(97);
fw.write('b');
fw.write(30000);
//关闭资源时,与FileOutputStream不同
//如果不关闭,数据只是保存到缓冲区,并未保存到文件。
fw.flush();
fw.write('d');
fw.close();

write(char[] cbuf) 和 write(char[] cbuf, int off, int len)

作用
write(char[] cbuf) 和 write(char[] cbuf, int off, int len) ,每次可以写出字符数 组中的数据
示例

FileWriter fw = new FileWriter("fmjava.txt");
String msg = "疯狂代码";
char[] chars = msg.toCharArray();
//写出字符数组
fw.write(chars);//疯狂代码
//写出从索引2开始,2个字符。
fw.write(chars,2,2);//代码
fw.close();

write(String str) 和 write(String str, int off, int len)

作用
write(String str) 和 write(String str, int off, int len) ,每次可以写出字符串中的 数据

示例
在这里插入图片描述

异常处理

方式1

FileWriter fw = null;
try {
    fw = new FileWriter("fmjava.txt");
} catch (IOException e) {
    e.printStackTrace();
}finally {
    if (fw != null){
        try {
            fw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

方式2
格式

try(创建流对象语句,如果多个,使用';'隔开){
代码
} catch(IOException e){
e.printStackTrace();
}

示例

	//该语句确保了每个资源在语句结束时关闭
try(FileWriter fw = new FileWriter("fmjava.txt");
    FileReader fr = new FileReader("fmjava.txt")) {
    fw.write("fmjava.com");
    int read = fr.read();
}catch (IOException e){
    e.printStackTrace();
}

缓冲流

概述

什么是缓冲流

缓冲流,也叫高效流,是对4个基本的 File*** 流的增强
所以也是4个流,按照数据类型分类:
字节缓冲流: BufferedInputStream , BufferedOutputStream
字符缓冲流: BufferedReader , BufferedWriter

基本原理

缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,
通过缓冲区读写,减少系统IO 次数,从而提高读写的效率。

字节缓冲流

构造方法

  1. public BufferedInputStream(InputStream in)
    创建一个 新的缓冲输入流。
  2. public BufferedOutputStream(OutputStream out)
    创建一个新的缓冲输出流。
    示例
//创建字节缓冲输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("fmjava.txt"));
//创建字节缓冲输出流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("fmjava.txt"));

直接使用FileInputStream与FileOutStream复制文件

		long start = System.currentTimeMillis();
        FileInputStream fis  = new FileInputStream("D:\apache-maven-3.5.4.rar");
        FileOutputStream fos = new FileOutputStream("newMaven.rar");
        int len;
        byte[] b = new byte[1024];
        while ((len = fis.read(b)) != -1){
            fos.write(b);
        }
        fis.close();
        fos.close();
        long end = System.currentTimeMillis();
        System.out.println("时间:"+(end-start));

使用缓冲流复制文件

		long start = System.currentTimeMillis();
        BufferedInputStream bis  = new BufferedInputStream(new FileInputStream("D:\apache-maven-3.5.4.rar"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("newMaven.rar"));
        int len;
        byte[] b = new byte[1024];
        while ((len = bis.read(b)) != -1){
            bos.write(b);
        }
        bis.close();
        bos.close();
        long end = System.currentTimeMillis();
        System.out.println("时间:"+(end-start));

字符缓冲流

构造方法

  1. public BufferedReader(Reader in)
  2. public BufferedWriter(Writer out)
    示例
 BufferedReader br = new BufferedReader(new FileReader("fmjava.txt"));
 BufferedWriter bw = new BufferedWriter(new FileWriter("fmjava.txt"));

特有方法

  1. BufferedReader
    public String readLine()
    读一行文字
  2. BufferedWriter
    public void newLine()
    写一行行分隔符,由系统属性定义符号

示例

			 BufferedReader br = new BufferedReader(new FileReader("fmjava.txt"));
        String line = null;
        while ((line = br.readLine())!= null){
            System.out.println(line);
        }
        br.close();
		
			BufferedWriter br = new BufferedWriter(new FileWriter("out.txt"));
        br.write("疯码");
        br.newLine();
        br.write("教育");
        br.newLine();
        br.close();

转换流

字符编码

计算机中储存的信息都是用二进制数表示的,而我们在屏幕上看到的数字、英文、标点符号、汉字等字符是二进制 数转换之后的结果。
按照某种规则,将字符存储到计算机中,称为编码 反之,将存储在计算机中的二进制数按照 某种规则解析显示出来,称为解码
按照A规则存储,同样按照A规则解析,那么就能显示正确的文本f符 号。反之,按照A规则存储,再按照B规则解析,就会导致乱码现象

字符集

字符集概念

字符集 Charset :也叫编码表。是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符 号、数字等。
计算机要准确的存储和识别各种字符集符号,需要进行字符编码,一套字符集必然至少有一套字符编码。 常见字符
集有ASCII字符集、GBK字符集、Unicode字符集等

常见字符集

  1. ASCII字符集
    ASCII编码
  2. GBK字符集
    GBK编码
  3. Unicode字符集
    UTF8编码
    UTF16编码
    UTF32编码

当指定了编码,它所对应的字符集自然就指定了,所以编码才是我们最终要关心的。

字符集介绍

  1. ASCII字符集
    ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)
    是基于拉丁 字母的一套电脑编码系统,用于显示现代英语,
    主要包括控制字符(回车键、退格、换行键等)和可显 示字符(英文大小写字符、阿拉伯数字和西文符号)。
    基本的ASCII字符集,使用7位(bits)表示一个字符,共128字符
    ASCII的扩展字符集使用8位(bits) 表示一个字符,共256字符,方便支持欧洲常用字符

  2. ISO-8859-1字符集
    拉丁码表,别名Latin-1,用于显示欧洲使用的语言,包括荷兰、丹麦、德语、意大利语、西班牙语等
    ISO-5559-1使用单字节编码,兼容ASCII编码

  3. GBxxx字符集
    GB就是国标的意思,是为了显示中文而设计的一套字符集
    GB2312
    简体中文码表。一个小于127的字符的意义与原来相同,但两个大于127的字符连在一起时, 就表示一个汉字,
    这样大约可以组合了包含7000多个简体汉字
    此外数学符号、罗马希腊的字母、日文 的假名们都编进去了
    在ASCII里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,
    这 就是常说的"全角"字符,而原来在127号以下的那些就叫"半角"字符了。
    GBK
    最常用的中文码表。是在GB2312标准基础上的扩展规范,使用了双字节编码方案,
    共收录了 21003个汉字,完全兼容GB2312标准,同时支持繁体汉字以及日韩汉字等
    GB18030
    新的中文码表。收录汉字70244个,采用多字节编码,每个字可以由1个、2个或4个字节 组成。
    支持中国国内少数民族的文字,同时支持繁体汉字以及日韩汉字等

  4. Unicode字符集
    Unicode编码系统为表达任意语言的任意字符而设计,是业界的一种标准,也称为统一码、标准万国 码。
    它最多使用4个字节的数字来表达每个字母、符号,或者文字。有三种编码方案
    UTF-8、UTF-16和UTF32,最为常用的UTF-8编码
    UTF-8编码,可以用来表示Unicode标准中任何字符,它是电子邮件、网页及其他存储或传送文字的应用 中,优先采用的编码
    UTF8编码规则
    128个US-ASCII字符,只需一个字节编码。
    拉丁文等字符,需要二个字节编码
    大部分常用字(含中文),使用三个字节编码
    其他极少使用的Unicode辅助字符,使用四字节编码

编码引出的问题

在IDEA中,使用 FileReader 读取项目中的文本文件。由于IDEA的设置,都是默认的 UTF-8 编码,所以没有任何 问题
但是,当读取Windows系统中创建的文本文件时,由于Windows系统的默认是GBK编码,就会出现乱码。

示例

		
			 public static void main(String[] args) throws  Exception{
        FileReader fileReader = new FileReader("d://gbkfile.txt");
        int read;
        while ((read = fileReader.read())!= -1){
            System.out.println((char)read); //读出的内容是乱码
        }
        fileReader.close();
    }
		

解决乱码
InputStreamReader
作用
转换流 java.io.InputStreamReader ,是Reader的子类,是从字节流到字符流的桥梁
它读取字节,并使用指定 的字符集将其解码为字符。它的字符集可以由名称指定,也可以接受平台的默认字符集
构造方法

  1. InputStreamReader(InputStream in)
    创建一个使用默认字符集的字符流
  2. InputStreamReader(InputStream in, String charsetName)
    创建一个指定字符集的字符流。
    示例
			
		InputStreamReader isr = new InputStreamReader(new FileInputStream("d://gbkfile.txt"),"gbk");
        int read;
        while ((read = isr.read())!= -1){
            System.out.println((char)read); //读出的内容是乱码
        }
        isr.close();

OutputStreamWriter
作用
转换流 java.io.OutputStreamWriter ,是Writer的子类,是从字符流到字节流的桥梁
使用指定的字符集将字符 编码为字节。它的字符集可以由名称指定,也可以接受平台的默认字符集
构造方法
OutputStreamWriter(OutputStream in)
创建一个使用默认字符集的字符流。
OutputStreamWriter(OutputStream in, String charsetName)
创建一个指定字符集的字符流

示例

			
		String fileName1 = "d://out.txt";
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(fileName1));
        osw.write("疯码");//保存为6个字节
        osw.close();

        String fileName2 = "d://out2.txt";
        OutputStreamWriter osw2 = new OutputStreamWriter(new FileOutputStream(fileName2), "gbk");
        osw2.write("疯码");//4个字节
        osw2.close();

序列化

什么是序列化

用一个字节序列可以表示一个对象,该字节序列包含该 对象的数据 、 对象的 类型 和 对象中存储的属性 等信息
字节序列写出到文件之后,相当于文件中持久保存了一个对象的信息。 字节序列还可以从文件中读取回来,重构对象,对它进行反序列化
对象的数据 、 对象的类型 和 对象中 存储的数据 信息,都可以用来在内存中创建对象。

序列化,必须满足两个条件:

该类必须实现 java.io.Serializable 接口 Serializable 是一个标记接口,不实现此接口的类将不会使任
何状态序列化或反序列化,会抛出 NotSerializableException
该类的所有属性必须是可序列化的。如果有一个属性不需要可序列化的,则该属性必须注明是瞬态的,使用 transient 关键字修饰

ObjectOutputStream类

作用:将Java对象的原始数据类型写出到文件,实现对象的持久存储
构造方法

public ObjectOutputStream(OutputStream out) 

创建一个指定OutputStream的ObjectOutputStream。 构造举例,

写出对象方方法
public final void writeObject (Object obj)

示例
创建Person类

public class Person  implements java.io.Serializable{
    public String name;
    public String age;
    public transient String address;
    public void show(){
        System.out.println("myName is "+name);
    }
}

写到文件当中

		public static void main(String[] args) throws Exception{
        Person person = new Person();
        person.name = "fmjava";
        person.age = "1";
        person.address = "南京";
        FileOutputStream fos = new FileOutputStream("person.txt");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(person);
        oos.close();
        fos.close();
    }

ObjectInputStream类

作用:ObjectInputStream反序列化流,将之前使用ObjectOutputStream序列化的原始数据恢复为对象

构造方法

	public ObjectInputStream(InputStream in) 

创建一个指定InputStream的ObjectInputStream

读取对象方法
readObject()
示例

		
			FileInputStream fileIn = new FileInputStream("person.txt");
        ObjectInputStream in = new ObjectInputStream(fileIn);
        Person p = (Person)in.readObject();
        System.out.println(p.name);
        System.out.println(p.age);
        System.out.println(p.address);
        p.show();
        fileIn.close();
        in.close();

注意事项
对于JVM可以反序列化对象,它必须是能够找到class文件的类。
如果找不到该类的class文件,则抛出一个 ClassNotFoundException 异常

打印流

概述

我们在控制台打印输出,是调用 print 方法和 println 方法完成的 这两个方法都来自于 java.io.PrintStream
类 该类能够方便地打印各种数据类型的值,是一种便捷的输出方式。

使用指定的文件名创建一个新的打印流

public PrintStream(String fileName) 

System.out 就是 PrintStream 类型的,只不过它的流向是系统规定的,打印在控制台上

示例

System.out.println("疯码");

PrintStream os = new PrintStream("fmjava.txt");
//设置系的打印流向,输出到指定的文件
System.setOut(os);
System.out.println("疯码");
原文地址:https://www.cnblogs.com/joker-dj/p/13388717.html