Java学习笔记===》23.IO流-基本流

文章详细介绍了Java中的IO流,包括字节流的FileOutputStream和FileInputStream的使用,如数据的读写、文件拷贝,以及异常处理。此外,还讨论了字符流的概念,字符编码问题,以及字符流的FileReader和FileWriter。文章强调了字节流与字符流在处理文本文件时的区别,并提供了相关示例代码。
摘要由CSDN通过智能技术生成

I O 流

一、IO流概述

1.什么是IO流

**IO流:**就是存储和读取数据的解决方案,用于读写文件中的数据(可以读写文件,或网络中的数据)

**思考:**IO流中,谁在读,谁在写?以谁为参照物看读写的方向呢===》程序

2.IO流的分类

(1)按IO流的方向分类

在这里插入图片描述

(2)按操作文件类型分类

在这里插入图片描述

3.小结:

(1)什么是IO流

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

​ I:input O:output 流:像水流一样传输数据

(2)IO流的作用

​ 用于读写数据(本地文件,网络)

(3)IO流按照流向可以分类哪两种流?

​ 输出流:程序===》文件

​ 输入流:文件===》程序

(4)IO流按照操作文件类型可以分类哪两种流?

​ 字节流:可以操作所有类型的文件

​ 字符流:只能操作纯文本文件

(5)什么是纯文本文件

​ 能被Windows自带的记事本打开并且能看懂的文件(.txt/.md/.xml/.lrc等)

二、IO流体系结构

1.结构

在这里插入图片描述

三、字节流

1.FileOutputStream

(1)作用:

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

(2)书写步骤:

​ ①创建字节输出流对象

​ ②写数据

​ ③释放资源

import java.io.FileOutputStream;
import java.io.IOException;
public class _01_ByteStreamTest01 {
    public static void main(String[] args) throws IOException {
       /*(1)演示:字节输出流FileOutStream
       实现需求:写一段文字到本地文件中(暂时不写中文)
        (2)书写步骤:
           ①创建字节输出流对象
           ②写数据
            ③释放资源*/
        //1.创建对象
        FileOutputStream fos = new FileOutputStream("D:\\workspace\\idea_space\\Java_based\\study\\a.txt"); //括号里面指定文件写入的路径
        //2.写出数据
        fos.write(97);
        //3.释放资源
        fos.close();
    }
}

(3)FileOutputStream的书写细节

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

(4)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;

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


        //1.创建对象
        FileOutputStream fos = new FileOutputStream("D:\\workspace\\idea_space\\Java_based\\study\\b.txt");
        //2.写入数据
        //void write(int b)                     | 一次写一个字节数据
        //fos.write(97);

        //void write(byte[] b)                  | 一次写一个字节数组数据
        byte [] arr = {97,98,99,100,101,102,103,105,106,107,108};
        fos.write(arr);       //abcdefgijkldefgij

        //void write(byte[] b,int off,int len) | 一次写一个字节数组的部分数据
        //参数一:数组
        //参数二:起始索引
        //参数三:个数
        fos.write(arr,3,6);     //defgij

        //释放资源
        fos.close();

    }
}

(5)FileOutputStream写数据的两个小问题

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
public class _04_FileOutputStreamTest04 {
    public static void main(String[] args) throws IOException {
         /*
            换行写:
                再次写出一个换行符就可以了
                windows: \r\n
                Linux:    \n
                Mac:      \r
            细节:
                在windows操作系统当中,java对回车换行进行了优化。
                虽然完整的是\r\n,但是我们写其中一个\r或者\n,
                java也可以实现换行,因为java在底层会补全。
            建议:
                不要省略,还是写全了。


            续写:
                如果想要续写,打开续写开关即可
                开关位置:创建对象的第二个参数
                默认false:表示关闭续写,此时创建对象会清空文件
                手动传递true:表示打开续写,此时创建对象不会清空文件
        */
        //1.创建对象
        FileOutputStream fos = new FileOutputStream("D:\\workspace\\idea_space\\Java_based\\study\\b.txt",true);

        //2.写出数据
        String str = "geweikankelaoyehaoshuai";
        byte[] bytes1 = str.getBytes();
        System.out.println(Arrays.toString(bytes1));
        fos.write(bytes1);

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

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

(6)小结

①FileOutputStream的作用

​ 可以把程序中的数据写道本地文件上,是字节流的基本流

②书写步骤

​ 创建对象,写出数据,释放资源

③三步操作的细节

​ ★创建对象:文件存在(先清空再写入)、文件不存在(先创建,再写入,但要保证父级路径是存在的)、追加写入(创建对象时传递第二个参数true,表示打开续写开关)

​ ★写出数据:写出整数(实际写出的是整数再ASCII码表对应的字符)、写出字节数组(将字符数组的全部或者部分内容写到文件当中)、换行写(写入换行符 windows:\r\n、Linux:\n、MacOS:\r)

​ ★释放资源:关闭通道

2.FileInputStream

(1)作用:

​ 操作本地文件的字节输入流,可以把本地文件中的数据读取到程序中来

(2)书写步骤:

​ ①创建字节输入流对象

​ ②读取数据

​ ③释放资源

public class _01_FileInputStreamTest01 {
    public static void main(String[] args) throws IOException {
        /*
         * 演示:字节输入流FileInputStream
         * 实现需求:读取文件中的数据。(暂时不写中文)
         * 实现步骤:
         *       创建对象
         *       读取数据
         *       释放资源
         * */
        //1.创建对象
        FileInputStream fis = new FileInputStream("D:\\workspace\\idea_space\\Java_based\\study\\b.txt");

        //2.读取数据
        int b1 = fis.read();
        System.out.println(b1); //97 返回字符再ASCII码表中对应的数字

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

(3)FileInputStream书写细节

1.创建字节输入流对象

	细节1:如果文件不存在,就会直接报错
	Java为什么会这么设计呢?
	输出流:不存在,创建
    把数据写到文件当中

	输入流:不存在,而是报错呢?
    因为创建出来的文件是没有数据的,没有任何意义。
    所以Java就没有设计这种无意义的逻辑,文件不存在直接报错。
	程序中最重要的是:数据。
	
	
2.读取数据
	细节1:一次读一个字节,读出来的是数据在ASCII码表上对应的数字
	细节2:读到末尾了,read方法返回-1

3.释放资源
	每一次使用完流之后,都要释放资源

(4)FileInputStream循环读取

import java.io.FileInputStream;
import java.io.IOException;
public class _03_FileInputStreamTest03 {
    public static void main(String[] args) throws IOException {
       /*
             字节输入流循环读取
         */

       //1.创建对象
        FileInputStream fis = new FileInputStream("myio\\a.txt");
        //2.循环读取
        int b;
        while ((b = fis.read()) != -1) {
            System.out.println((char) b);
        }
        //3.释放资源
        fis.close();


       /* *//*
        * 错误演示:不用变量接受数据会造成指针跳跃
        * read :表示读取数据,而且是读取一个数据就移动一次指针
        *
        * *//*
        FileInputStream fis = new FileInputStream("myio\\a.txt");
        //2.循环读取
        while ((fis.read()) != -1) {
            System.out.println(fis.read());//98  100  -1
        }
        //3.释放资源
        fis.close();*/

    }
}

(5)文件拷贝

package com_08_IO._02FileInputStream;

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

public class _04_FileInputStreamTest04 {
    public static void main(String[] args) throws IOException {
        /*
         *   练习:
         *       文件拷贝
         *       把D:\itheima\movie.mp4拷贝到当前模块下。
         *
         *   注意:
         *       选择一个比较小的文件,不要太大。大文件拷贝我们下一个视频会说。
         *
         *
         *
         *   课堂练习:
         *       要求统计一下拷贝时间,单位毫秒
         * */

        long start = System.currentTimeMillis();

        //1.创建对象
        FileInputStream fis = new FileInputStream("D:\\workspace\\movie.mp4");
        FileOutputStream fos = new FileOutputStream("D:\\workspace\\copy.mp4");
        //2.拷贝
        //核心思想:边读边写
        int b;
        while((b = fis.read()) != -1){
            fos.write(b);
        }
        //3.释放资源
        //规则:先开的最后关闭
        fos.close();
        fis.close();

        long end = System.currentTimeMillis();

        System.out.println(end - start);

    }
}

(6)FileInputStream读取的问题

在这里插入图片描述

(7)FileInputStream一次读取多个字节

方法名称说明
public int read()一次读一个字节数据
public int read(byte[] buffer)一次读一个字节数组数据

**注意:**这种一次读取一个字节数组的数据,每次读取会尽可能吧数组装满

public class _05_FileInputStreamTest05 {
    public static void main(String[] args) throws IOException {
        
        //1.创建对象
        FileInputStream fis = new FileInputStream("D:\\workspace\\idea_space\\Java_based\\study\\b.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);// ed

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

3.try . . . catch 异常处理(捕获异常的完整形态)

(1)格式:

try{
	
}catch{

}finally{
	//finally里面的代码一定会执行,除非虚拟机停止
}

(2)练习:

public class _06_FileInputStreamTest06 {
    public static void main(String[] args) {
        /*    利用try...catch...finally捕获拷贝文件中代码出现的异常* */
        //1.创建对象
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream("D:\\workspace\\movie.mp4");
            fos = new FileOutputStream("D:\\workspace\\copy.mp4");
            //2.拷贝
            int len;
            byte[] bytes = new byte[1024 * 1024 * 5];
            while((len = fis.read(bytes)) != -1){
                fos.write(bytes,0,len);
            }
        } catch (IOException e) {
            //e.printStackTrace();
        } finally {
            //3.释放资源
            if(fos != null){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(fis != null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

(3)Java中提供的简化方式

在Java中提供了一个接口 AutoCloseable,只有在特定情况下,这个接口会自动释放资源
在这里插入图片描述

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

public class _07_FileInputStreamTest07 {
    public static void main(String[] args) {
        /*    JDK7:IO流中捕获异常的写法
         *      try后面的小括号中写创建对象的代码,
         *          注意:只有实现了AutoCloseable接口的类,才能在小括号中创建对象。
         *     try(){
         *
         *     }catch(){
         *
         *     }
         * */

        try(FileInputStream fis = new FileInputStream("D:\\workspace\\movie.mp4");
            FileOutputStream fos = new FileOutputStream("D:\\workspace\\copy.mp4")){
            //2.拷贝
            int len;
            byte[] bytes = new byte[1024 * 1024 * 5];
            while ((len = fis.read(bytes)) != -1) {
                fos.write(bytes, 0, len);
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

//JDK9
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class _08_FileInputStreamTest08 {
    public static void main(String[] args) throws FileNotFoundException {
        /*
         *
         *    JDK9:IO流中捕获异常的写法
         *
         *
         * */

        FileInputStream fis = new FileInputStream("D:\\workspace\\movie.mp4");
        FileOutputStream fos = new FileOutputStream("D:\\workspace\\movie.mp4");

        try (fis;fos) {
            //2.拷贝
            int len;
            byte[] bytes = new byte[1024 * 1024 * 5];
            while ((len = fis.read(bytes)) != -1) {
                fos.write(bytes, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }


    }
}

四、字符集

1.计算机的存储规则

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

在这里插入图片描述

(1)计算机存储英文

在这里插入图片描述

(2)计算机存储中文:

①GB2312字符集:

​ 1980年发布,1981年5-1实施的简体中文汉字比编码国家标准,收录7445个图形字符,其中巴奥括6763个简体汉字

②BIG5字符集:

​ 台湾地区繁体中文标准字符集,共收录13053个中文字,1984年实施

③GBK字符集:

​ 2000年3月17日发布,收录21003个汉字。包含国家标准GB13000-1中的全部中日韩汉字,和BIG5编码中的而所有汉字,Windows系统默认使用的就是GBK,系统显示:
在这里插入图片描述

小结:

★在计算机中,任意数据都是以二进制数据的形式来存储的

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

★ASCII码表字符集中,一个英文占一个字节

★简体中文版Windows,默认使用GBK字符集

★GBK字符集完全兼容ASCII字符集

​ 一个英文占一个字节,二进制第一位是0

​ 一个中文占两个字符,二进制高位字节的第一位是1

④Unicode字符集:

​ 国际标准字符集,它将世界各国语言的每个字符定义一个唯一的编码,以满足跨语言、跨平台的文本信息交换

在这里插入图片描述

总结

★Unicode字符集的UTF-8编码格式

​ 一个英文占一个字节,二进制第一位是0,转成十进制是正数

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

五、为什么会有乱码

原因1:

​ 读取数据时未读完整个汉字

原因2:

​ 编码和解码的方式不统一

1.如何才能不产生乱码?

(1)不要使用字节流读取文本文件

(2)编码解码使用同一个码表,同一个编码方式

2.扩展

(1)字节流读取中文会乱码,但是为什么拷贝不会乱码呢

因为拷贝和读取都是一个字节一个字节进行的,只要编码解码方式一样,就不会出现乱码

六、编码和解码

1.Java中编码的方式:

String类中方法名称说明
public byte[] getBytes()根据默认方式进行编码
public byte[] getBytes(String charsetName)根据指定方式进行编码

2.Java中解码的方式:

String类中方法名称
String (byte [] bytes)根据默认方式解码
String (byte [] bytes,String charsetName)根据指定方式解码
import java.io.UnsupportedEncodingException;
import java.util.Arrays;

public class CharsetTest03 {
    public static void main(String[] args) throws UnsupportedEncodingException {
        
        //编码
        String str = "ai你哟";
        byte[] bytes1 = str.getBytes(); //idea默认使用utf-8 eclipse默认使用GBK编码
        System.out.println(Arrays.toString(bytes1));

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

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

        String str2 = new String(bytes2,"GBK");
        System.out.println(str2);
    }
}

六、字符流

1.概述

(1)什么是字符流?

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

​ 字符流 = 字节流 + 字符集

(2)特点:

输入流:一次读一个字节,遇到中文,一次读三个字节

输出流:底层会把数据按照指定编码方式的方式进行编码,变成字节再写到文件中

(3)使用场景

​ 对纯文本文件进行操作

2.FileReader

(1)创建字符输入流对象

方法名称
public FileReader(File file)创建字符输入流关联本地文件
public FileReader(String getPathname)创建字符输入流关联本地文件

细节:如果文件不存在,会直接报错

(2)读取数据

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

(3)释放资源

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

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

        //1.创建对象并关联本地文件
        FileReader fr = new FileReader("D:\\workspace\\idea_space\\Java_based\\study\\b.txt");
        //2.读取数据 read()
        //字符流的底层也是字节流,默认也是一个字节一个字节的读取的。
        //如果遇到中文就会一次读取多个,GBK一次读两个字节,UTF-8一次读三个字节

        //read()细节:
        //1.read():默认也是一个字节一个字节的读取的,如果遇到中文就会一次读取多个
        //2.在读取之后,方法的底层还会进行解码并转成十进制。
        //  最终把这个十进制作为返回值
        //  这个十进制的数据也表示在字符集上的数字
        //  英文:文件里面二进制数据 0110 0001
        //          read方法进行读取,解码并转成十进制97
        //  中文:文件里面的二进制数据 11100110 10110001 10001001
        //          read方法进行读取,解码并转成十进制27721

        // 我想看到中文汉字,就是把这些十进制数据,再进行强转就可以了

        int ch;
        while((ch = fr.read()) != -1){
            System.out.print((char)ch);
        }

        //3.释放资源
        fr.close();

    }
}
//read含参构造
import java.io.FileReader;
import java.io.IOException;

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

3.FileWriter

(1)FileWriter构造方法

方法名称说明
public FileWriter ( File file)创建字符输出流关联本地文件
public FileWriter(String pathname)创建字符输出流关联本地文件
public Fi了Writer(File file,boolean append)创建字符输出流关联本地文件,续写
public Fi了Writer(String pathname,boolean append)创建字符输出流关联本地文件,续写

(2)FileWriter成员方法

方法名称说明
void write(int c)写出一个字符
void write(String str)写出一个字符串
void write(String str,int off,int len)写出一个字符串的一部分
void write(char [] cubf)写出一个字符数组
void write(char [] cubf,int off,int len)写出一个字符数组的一部分

(3)FileWriter书写细节

①创建字符输出流对象

​ ★细节1:参数是字符串表示的路径或者是File对象都是可以的

​ ★细节2:如果文件按不存在会创建一个新的文件,但要保证腹肌路径是存在的

​ ★细节3:如果文件存在,则会清空文件,如果不想清空,可以打开续写开关

②写数据

​ ★如果write方法的参数是整数,但是实际上写到本地文件中的是整数再字符集上对一个的字符

③释放资源

​ ★每次使用完流之后,都要释放资源

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

        FileWriter fw = new FileWriter("D:\\workspace\\idea_space\\Java_based\\study\\b.txt",true);

        //void write(int c)                          | 写出一个字符             |
        fw.write(25105);//根据字符集的编码方式将参数表示的字符进行编码,把编码之后的数据写道文件中取

        //void write(String str)                     | 写出一个字符串           |
        fw.write("你好坏啊,我好喜欢");

        //void write(String str,int off,int len)   | 写出一个字符串的一部分
        fw.write("你好坏啊我好喜欢",2,4);

        //void write(char [] cubf)                   | 写出一个字符数组
        char [] chars = {'我','是','中','国','人'};
        fw.write(chars);

        //void write(char [] cubf,int off,int len) | 写出一个字符数组的一部分
        fw.write(chars,2,3);

        fw.close();
    }
}

4.字符流原理分析

(1)字符输入流的底层原理

①创建字符输入流对象:

​ 底层:关联文件,并创建缓冲区(长度位8192的字节数组)

②读取数据

​ 底层:

​ ①判断缓冲区是否有数据可以读取

​ ②如果缓冲区没有数据,会从文件直接获取,装到缓冲区,每次尽可能地装满缓冲区,如果文件也没有数据,返回-1

​ ③如果缓冲区有数据,从缓冲区直接获取,英文每次获取一个字节,中文每次获取三个字节,把字节解码并转成十进制返回(有参的read方法会把读取,解码,强转合并,将强转之后的字符放到数组中),直到缓冲区没有数据,再次从文件获取,如果文件中也没有数据了,那么返回-1

在这里插入图片描述

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

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


        FileReader fr = new FileReader("D:\\workspace\\idea_space\\Java_based\\study\\b.txt");
        fr.read();//会把文件中的数据放到缓冲区当中

        //清空文件
        FileWriter fw = new FileWriter("D:\\workspace\\idea_space\\Java_based\\study\\b.txt");

        //请问,如果我再次使用fr进行读取
        //会读取到数据吗?

        //会把缓冲区中的数据全部读取完毕

        //正确答案:
        //但是只能读取缓冲区中的数据,文件中剩余的数据无法再次读取
        int ch;
        while((ch = fr.read()) != -1){
            System.out.println((char)ch);
        }


        fw.close();
        fr.close();

    }
}

(2)字符输出流的底层原理

在这里插入图片描述

5.字节流和字符流的使用场景

(1)字节流

​ ★拷贝任意类型的文件

(2)字符流

​ ★读取纯文本文件中的数据

​ ★往纯文本文件中写出数据

七、练习

1.需求:拷贝一个文件夹,考虑子文件夹

细节:如果listFiles获取的文件夹是带有权限的,那么方法返回null,

package com_08_IO.Test;

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

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

        

        //1.创建对象表示数据源
        File file1 = new File("D:\\aaa");
        
        //2.创建对象表示目的地
        File file2 = new File("D:\\bbb");
        
        //3.调用方法拷贝文件
        copyFile(file1,file2);

    }

    /*
    * 作用:拷贝文件夹
    * 参数一:数据源
    * 参数二:目的地
    * */
    private static void copyFile(File file1, File file2) throws IOException {
        file2.mkdirs();
        /*递归
        * 1.进入数据源
        * 2.遍历数组
        * 3.判断文件,拷贝
        * 4.判断文件夹,递归*/

        //进入数据源
        File[] listFiles = file1.listFiles();
        //遍历数组
        for (File file : listFiles) {
            if(file.isFile()){
                //判断文件,拷贝
                FileInputStream fis = new FileInputStream(file);
                FileOutputStream fos = new FileOutputStream(new File(file2,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{
                copyFile(file,new File(file2,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 {
 /*
^ : 异或
                 两边相同:false
                 两边不同:true

                 0:false
                 1:true

               100:1100100
               10: 1010

               1100100
             ^ 0001010
             __________
               1101110
             ^ 0001010
             __________
               1100100

        */

        //加密
        FileInputStream fis = new FileInputStream("D:\\aaa\\1.png");
        FileOutputStream fos = new FileOutputStream("D:\\bbb\\1.png");
        int b;
        while((b = fis.read()) != -1){
            fos.write(b ^ 2);
        }
        //fos.close();
        //fis.close();

        //解密:
        FileInputStream fis1 = new FileInputStream("D:\\bbb\\1.png");
        FileOutputStream fos1 = new FileOutputStream("D:\\bbb\\2.png");
        int c;
        while((c = fis.read()) != -1){
            fos.write(c ^ 2);
        }
        fos.close();
        fis.close();
    }
}

3.需求:

文本文件中有以下数据:2-1-9-4-7-8

将文件的数据进行排序,变成以下的数据:1-2-4-7-8-9

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

public class Test03 {
    public static void main(String[] args) throws IOException {
 
        //1.读取文件中的数据
        FileReader fr = new FileReader("D:\\aaa\\a.txt");
        StringBuilder sb = new StringBuilder();

        int b;
        while ((b = fr.read()) != -1) {
            sb.append((char) b);
            System.out.println(b);
        }
        fr.close();
        System.out.println(sb);

        //排序
        String str = sb.toString();
        String[] arrStr = str.split("-");

        ArrayList<Integer> list = new ArrayList<>();
        for (String s : arrStr) {
            int i = Integer.parseInt(s);
            list.add(i);
        }

        Collections.sort(list, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1 - o2;
            }
        });
        System.out.println(list);
        //写出数据
        FileWriter fw = new FileWriter("D:\\aaa\\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();

    }
}

简化写法:

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

public class Test04 {
    public static void main(String[] args) throws IOException {
 /* 3.需求:
文本文件中有以下数据:2-1-9-4-7-8
将文件的数据进行排序,变成以下的数据:1-2-4-7-8-9
*/
        //1.读取文件中的数据
        FileReader fr = new FileReader("D:\\aaa\\a.txt");
        StringBuilder sb = new StringBuilder();

        int b;
        while ((b = fr.read()) != -1) {
            sb.append((char) b);
            System.out.println(b);
        }
        fr.close();
        System.out.println(sb);

        //排序
        /*Integer[] arr = Arrays.stream(sb.toString().split("-")).map(new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return Integer.parseInt(s);
            }
        }).sorted().toArray(Integer[]::new);

        System.out.println(Arrays.toString(arr));*/

        //简化
        Integer[] arr = Arrays.stream(sb.toString()
                        .split("-"))
                .map(Integer::parseInt)
                .sorted()
                .toArray(Integer[]::new);
        System.out.println(Arrays.toString(arr));


        //写出数据
        FileWriter fw = new FileWriter("D:\\aaa\\a.txt");
        String str = Arrays.toString(arr).replace(", ","-");
        fw.write(str.substring(1,str.length()-1));
        fw.close();
    }
}

细节:

1.文件中的数据不要换行,否则读取文件会读取到换行符

2.有些文本文件带有bom头,可能会导致排序失败

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值