IO流

一、IO概述

1.什么是IO流?
存储和读取数据的解决方案l: inputo: output流∶像水流一样传输数据

2.IO流的作用?
用于读写数据(本地文件,网络)

3.IO流按照流向可以分类哪两种流?
输出流:程序   - >    文件
输入流:文件   - >    程序
4.IO流按照操作文件的类型可以分类哪两种流?
字节流:可以操作所有类型的文件
字符流:只能操作纯文本文件

5.什么是纯文本文件?
用windows系统自带的记事本打开并且能读懂的文件

txt文件,md文件,xml文件,lrc文件等

顶级父类们:

输入流输出流
字节流字节输入流 InputStream字节输出流 OutputStream
字符流字符输入流 Reader字符输出流 Writer

二、字节流

1. 一切皆为字节

一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,都一个一个的字节,那么传输时一样如此。所以,字节流可以传输任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底层传输的始终为二进制数据。

字节输出流【OutputStream】

java.io.OutputStream抽象类是表示字节输出流的所有类的超类,将指定的字节信息写出到目的地。它定义了字节输出流的基本共性功能方法。

  • public void close() :关闭此输出流并释放与此流相关联的任何系统资源。

  • public void flush() :刷新此输出流并强制任何缓冲的输出字节被写出。

  • public void write(byte[] b):将 b.length字节从指定的字节数组写入此输出流。

  • public void write(byte[] b, int off, int len) :从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。

  • public abstract void write(int b) :将指定的字节输出流。

小贴士:

close方法,当完成流的操作时,必须调用此方法,释放系统资源。

FileOutputStream类

OutputStream有很多子类,我们从最简单的一个子类开始。

java.io.FileOutputStream类是文件输出流,用于将数据写出到文件。

构造方法

  • public FileOutputStream(File file):创建文件输出流以写入由指定的 File对象表示的文件。

  • public FileOutputStream(String name): 创建文件输出流以指定的名称写入文件。

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

  • 构造举例,代码如下:

public class FileOutputStreamConstructor throws IOException {
    public static void main(String[] args) {
   	 	// 使用File对象创建流对象
        File file = new File("a.txt");
        FileOutputStream fos = new FileOutputStream(file);
      
        // 使用文件名称创建流对象
        FileOutputStream fos = new FileOutputStream("b.txt");
    }
}

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

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

写出字节数据

write(int b) 方法,每次可以写出一个字节数据

void write(int b)                                       一次写一个字节数据
void write(byte[] b)                                  一次写一个字节数组数据
void write(byte[] b, int off, int len)            一次写一个字节数组的部分数据

           参数一:
                数组
           参数二:
                起始索引  0
           参数三:
                个数      3

//1.创建对象
 FileOutputStream fos = new FileOutputStream("myio\\a.txt");
//2.写出数据
//fos.write(97); // a
//fos.write(98); // b
byte[] bytes = {97, 98, 99, 100, 101};
 /* fos.write(bytes);*/

fos.write(bytes,1,2);// b c
 //3.释放资源
fos.close();

换行写

换行写:
                再次写出一个换行符就可以了
                windows: \r\n
                Linux:    \n
                Mac:      \r

 细节:
                在windows操作系统当中,java对回车换行进行了优化。
                虽然完整的是\r\n,但是我们写其中一个\r或者\n,
                java也可以实现换行,因为java在底层会补全。

建议:
                不要省略,还是写全了。

数据追加续写

如果想要续写,打开续写开关即可
                开关位置:创建对象的第二个参数
                默认false:表示关闭续写,此时创建对象会清空文件
                手动传递true:表示打开续写,此时创建对象不会清空文件

  //1.创建对象
        FileOutputStream fos = new FileOutputStream("myio\\a.txt",true);
        //2.写出数据
        String str = "kankelaoyezuishuai";
        byte[] bytes1 = str.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();

小结:

1. FileOutputStream的作用
可以把程序中的数据写到本地文件上,是字节流的基本流。
2.书写步骤
创建对象,写出数据,释放资源
3.三步操作的细节
创建对象:文件存在、文件不存在、追加写入
写出数据:写出整数、写出字节数组、换行写
释放资源:关闭通道

字节输入流【InputStream】

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

  • public void close() :关闭此输入流并释放与此流相关联的任何系统资源。

  • public abstract int read(): 从输入流读取数据的下一个字节。

  • public int read(byte[] b): 从输入流中读取一些字节数,并将它们存储到字节数组 b中 。

小贴士:

close方法,当完成流的操作时,必须调用此方法,释放系统资源。

FileInputStream类

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

构造方法

  • FileInputStream(File file): 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。

  • FileInputStream(String name): 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。

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

实现步骤:
         *       创建对象
         *       读取数据
         *       释放资源

FilelnputStream书写细节
创建字节输入流对象
细节1∶如果文件不存在,就直接报错。

Java为什么会这么设计呢?
                    输出流:不存在,创建
                        把数据写到文件当中

                    输入流:不存在,而是报错呢?
                        因为创建出来的文件是没有数据的,没有任何意义。
                        所以Java就没有设计这种无意义的逻辑,文件不存在直接报错。

                    程序中最重要的是:数据。

读取数据
细节1:一次读一个字节,读出来的是数据在ASCII上对应的数字

细节2:读到文件末尾了, read方法返回-1。
③释放资源
细节1:每次使用完流必须要释放资源。

读取字节数据

  1. 读取字节read方法,每次可以读取一个字节的数据,提升为int类型,读取到文件末尾,返回-1,代码使用演示:

    public class FISRead {
        public static void main(String[] args) throws IOException{
          	// 使用文件名称创建流对象
           	FileInputStream fis = new FileInputStream("read.txt");
          	// 定义变量,保存数据
            int b ;
            // 循环读取
            while ((b = fis.read())!=-1) {
                System.out.print((char)b);
            }
    		// 关闭资源
            fis.close();
        }
    }
    输出结果:
    abcde

    小贴士:

虽然读取了一个字节,但是会自动提升为int类型。

流操作完毕后,必须释放系统资源,调用close方法,千万记得

2.使用字节数组读取read(byte[] b),每次读取b的长度个字节到数组中,返回读取到的有效字节个数,读取到末尾时,返回-1 ,代码使用演示:

public class ByteStreamDemo5 {
    public static void main(String[] args) throws IOException {
      /*
          public int read(byte[] buffer)      一次读一个字节数组数据
      */



        //1.创建对象
        FileInputStream fis = new FileInputStream("myio\\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);// ed



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


    }
}

复制文件

public class ByteStreamDemo6 {
    public static void main(String[] args) throws IOException {
        /*
         *   练习:
         *       文件拷贝
         *       把D:\itheima\movie.mp4 (16.8 MB) 拷贝到当前模块下。
         *
         * */


        long start = System.currentTimeMillis();

        //1.创建对象
        FileInputStream fis = new FileInputStream("D:\\itheima\\movie.mp4");
        FileOutputStream fos = new FileOutputStream("myio\\copy.mp4");
        //2.拷贝
        int len;
        byte[] bytes = new byte[1024 * 1024 * 5];
        while((len = fis.read(bytes)) != -1){
            fos.write(bytes,0,len);
        }
        //3.释放资源
        fos.close();
        fis.close();

        long end = System.currentTimeMillis();

        System.out.println(end - start);


    }
}

流的关闭原则:先开后关,后开先关。

三、IO异常的处理

JDK7前处理

之前的入门练习,我们一直把异常抛出,而实际开发中并不能这样处理,建议使用try...catch...finally 代码块,处理异常部分,代码使用演示:

package com.itheima.mybytestream2;

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

public class ByteStreamDemo7 {
    public static void main(String[] args) {
       /*
       *
       *    利用try...catch...finally捕获拷贝文件中代码出现的异常
       *
       *
       * */


        //1.创建对象
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream("D:\\itheima\\movie.mp4");
            fos = new FileOutputStream("myio\\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();
                }
            }

        }


    }
}

JDK7的处理(扩展知识点了解内容)

还可以使用JDK7优化后的try-with-resource 语句,该语句确保了每个资源在语句结束时关闭。所谓的资源(resource)是指在程序完成后,必须关闭的对象。

格式:

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

使用演示:

package com.itheima.mybytestream2;

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

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


        try (FileInputStream fis = new FileInputStream("D:\\itheima\\movie.mp4");
             FileOutputStream fos = new FileOutputStream("myio\\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的改进(扩展知识点了解内容)

JDK9中try-with-resource 的改进,对于引入对象的方式,支持的更加简洁。被引入的对象,同样可以自动关闭,无需手动close,我们来了解一下格式。

改进前格式:

// 被final修饰的对象
final Resource resource1 = new Resource("resource1");
// 普通对象
Resource resource2 = new Resource("resource2");
// 引入方式:创建新的变量保存
try (Resource r1 = resource1;
     Resource r2 = resource2) {
     // 使用对象
}

改进后格式:

package com.itheima.mybytestream2;

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

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

        FileInputStream fis = new FileInputStream("D:\\itheima\\movie.mp4");
        FileOutputStream fos = new FileOutputStream("myio\\copy.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.在计算机中,任意数据都是以二进制的形式来存储的
2.计算机中最小的存储单元是一个字节
3. ASCII字符集中,一个英文占一个字节
4.简体中文版windows,默认使用GBK字符集
5.GBK字符集完全兼容ASCII字符集
        一个英文占一个字节,二进制第一位是0
        一个中文占两个字节,二进制高位字节的第一位是1

1. Unicode字符集的UTF-8编码格式
一个英文占一个字节,二进制第一位是0,转成十进制是正数
一个中文占三个字节,二进制第一位是1,第一个字节转成十进制是负数


为什么会产生乱码?

1,不要用字节流读取文本文件
2,编码解码时使用同一个码表,同一个编码方式

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

        Java中解码的方法
            String(byte[] bytes)                            使用默认方式进行解码
            String(byte[] bytes, String charsetName)        使用指定方式进行解码

//1.编码
        String str = "ai你哟";
        byte[] bytes1 = str.getBytes();
        System.out.println(Arrays.toString(bytes1));

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


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

        String str3 = new String(bytes1,"GBK");
        System.out.println(str3);
        String str4=new String(bytes2,"GBK");
        System.out.println(str4);
结果为:
[97, 105, -28, -67, -96, -27, -109, -97]
[97, 105, -60, -29, -45, -76]
ai你哟
ai浣犲摕
ai你哟

五、字符流

        字符流的底层其实就是字节流
        字符流=字节流+字符集
特点:
输入流:一次读一个字节,遇到中文时,一次读多个字节
输出流:底层会把数据按照指定的编码方式进行编码,变成字节再写到文件中

使用场景:

对纯文本文档进行读写操作

IO流体系:

1字符输入流【Reader】

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

  • public void close() :关闭此流并释放与此流相关联的任何系统资源。

  • public int read(): 从输入流读取一个字符。

  • public int read(char[] cbuf): 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中 。

2 FileReader类

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

小贴士:

  1. 字符编码:字节与字符的对应规则。Windows系统的中文编码默认是GBK编码表。

    idea中UTF-8

  2. 字节缓冲区:一个字节数组,用来临时存储字节数据。

1创建字符输入流对象

2读取数据

成员方法说明
public int read()读取数据,读到末尾返回-1
public  read(char[ ] buffer)读取多个数据,读到末尾返回-1

细节1:按字节进行读取,遇到中文,一次读多个字节,读取后解码,返回一个整数

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

3.释放资源

Public int close()                释放资源、关流
 

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

public class CharStreamDemo1 {
    public static void main(String[] args) throws IOException {
        /*
            第一步:创建对象
            public FileReader(File file)        创建字符输入流关联本地文件
            public FileReader(String pathname)  创建字符输入流关联本地文件

            第二步:读取数据
            public int read()                   读取数据,读到末尾返回-1
            public int read(char[] buffer)      读取多个数据,读到末尾返回-1

            第三步:释放资源
            public void close()                 释放资源/关流
        */

        //1.创建对象并关联本地文件
        FileReader fr = new FileReader("myio\\a.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();





    }
}

3 字符输出流【Writer】

java.io.Writer抽象类是表示用于写出字符流的所有类的超类,将指定的字符信息写出到目的地。它定义了字节输出流的基本共性功能方法。

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

  • void write(int c) 写入单个字符。

  • void write(char[] cbuf)写入字符数组。

  • abstract void write(char[] cbuf, int off, int len)写入字符数组的某一部分,off数组的开始索引,len写的字符个数。

  • void write(String str)写入字符串。

  • void write(String str, int off, int len) 写入字符串的某一部分,off字符串的开始索引,len写的字符个数。

  • void flush()刷新该流的缓冲。

  • void close() 关闭此流,但要先刷新它。

  • 4 FileWriter类

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

  • 构造方法
  • FileWriter(File file): 创建一个新的 FileWriter,给定要读取的File对象。

  • FileWriter(String fileName): 创建一个新的 FileWriter,给定要读取的文件的名称。

第一步:创建对象
public FileWriter(File file)                                                 创建字符输出流关联本地文件
public FileWriter(String pathname)                                  创建字符输出流关联本地文件
public FileWriter(File file,  boolean append)                    创建字符输出流关联本地文件,续写
public FileWriter(String pathname,  boolean append)     创建字符输出流关联本地文件,续写

细节1:参数是字符串表示的路径或者File对象都是可以的
细节2:如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的细节3:如果文件已经存在,则会清空文件,如果不想清空可以打开续写开关
 

第二步:读取数据
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)                              写出字符数组的一部分

第三步:释放资源
public void close()                                                        释放资源/关流

字符流原理解析

输入:


1.创建字符输入流对象
底层:关联文件,并创建缓冲区(长度为8192的字节数组)
2读取数据
底层:1.判断缓冲区中是否有数据可以读取
        2.缓冲区没有数据:就从文件中获取数据,装到缓冲区中,每次尽可能装满缓冲t
           如果文件中也没有数据了,返回-1
        3.缓冲区有数据:就从缓冲区中读取。
           空参的read方法:一次读取一个字节,遇到中文一次读多个字节,把字节解码并转成十进制返回有参的read方法:把读取字节,解码,强转三步合并了,强转之后的字符放到数组中

输出:

flush和close方法

成员方法说明
public void flush()将缓冲区中的数据,刷新到本地文件中
public void close()释放资源/关流

flush刷新:刷新之后,还可以继续往文件中写出数据
close关流:断开通道,无法再往文件中写出数据
 

练习一、拷贝文件夹

package com.itheima.mytest;

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 src = new File("D:\\aaa\\src");
        //2.创建对象表示目的地
        File dest = new File("D:\\aaa\\dest");

        //3.调用方法开始拷贝
        copydir(src,dest);



    }

    /*
    * 作用:拷贝文件夹
    * 参数一:数据源
    * 参数二:目的地
    *
    * */
    private static void copydir(File src, File dest) throws IOException {
        dest.mkdirs();
        //递归
        //1.进入数据源
        File[] files = src.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()));
            }
        }
    }
}

练习二、加密和解密

package com.itheima.mytest;

import java.io.*;

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

        */




    }


    public static void encryptionAndReduction(File src, File dest) throws IOException {
        FileInputStream fis = new FileInputStream(src);
        FileOutputStream fos = new FileOutputStream(dest);
        int b;
        while ((b = fis.read()) != -1) {
            fos.write(b ^ 2);
        }
        //4.释放资源
        fos.close();
        fis.close();
    }


}

练习三、修改文件中的数据

package com.itheima.mytest;


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 {
        /*
            文本文件中有以下的数据:
                2-1-9-4-7-8
            将文件中的数据进行排序,变成以下的数据:
                1-2-4-7-8-9
        */


        //1.读取数据
        FileReader fr = new FileReader("myio\\a.txt");
        StringBuilder sb = new StringBuilder();
        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("-");//2-1-9-4-7-8

        ArrayList<Integer> list = new ArrayList<>();
        for (String s : arrStr) {
            int i = Integer.parseInt(s);
            list.add(i);
        }
        Collections.sort(list);
        System.out.println(list);
        //3.写出
        FileWriter fw = new FileWriter("myio\\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();





    }
}
package com.itheima.mytest;


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 {
        /*
            文本文件中有以下的数据:
                2-1-9-4-7-8
            将文件中的数据进行排序,变成以下的数据:
                1-2-4-7-8-9


           细节1:
                文件中的数据不要换行


            细节2:
                bom头
        */
        //1.读取数据
        FileReader fr = new FileReader("myio\\a.txt");
        StringBuilder sb = new StringBuilder();
        int ch;
        while((ch = fr.read()) != -1){
            sb.append((char)ch);
        }
        fr.close();
        System.out.println(sb);
        //2.排序
        Integer[] arr = Arrays.stream(sb.toString()
                .split("-"))
                .map(Integer::parseInt)
                .sorted()
                .toArray(Integer[]::new);
        //3.写出
        FileWriter fw = new FileWriter("myio\\a.txt");
        String s = Arrays.toString(arr).replace(", ","-");
        String result = s.substring(1, s.length() - 1);
        fw.write(result);
        fw.close();


    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/523869.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

30道python自动化测试面试题与答案汇总!

Python是不可或缺的语言,它的优美与简洁令人无法自拔,下面这篇文章主要给大家介绍了关于30道python自动化测试面试题与答案汇总的相关资料,需要的朋友可以参考下 1、什么项目适合做自动化测试&#xff1f; 关键字&#xff1a;不变的、重复的、规范的 1&#xff09;任务测试明…

Collection与数据结构 Stack与Queue(二):队列与Queue

1. 队列 1.1 概念 只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff0c;队列具有先进先出FIFO(First In First Out) 入队列&#xff1a;进行插入操作的一端称为队尾&#xff08;Tail/Rear&#xff09; 出队列&#xff1a;进行删除操作…

JVM内存性能调优思路之:通过GC log、Thread Dump 、Heap Dump分析内存使用说明

文章目录 一. 各日志概述1. Garbage Collection Log - 找到GC规律2. 线程转储(Thread dump) - 分析&#xff08;快照&#xff09;线程状态3. 堆转储(Heap dump) - APP某刻内存使用全貌 二. 命令1. 程序的gc日志2. 线程转储3. 堆转储 概述 在 Java 虚拟机中&#xff0c;(GC) Gar…

C语言分支语句

一、什么是语句 C语句可分为以下五类&#xff1a; 表达式语句 函数调用语句 控制语句 复合语句 空语句 本周后面介绍的是控制语句。 控制语句用于控制程序的执行流程&#xff0c;以实现程序的各种结构方式&#xff0c;它们由特定的语句定义符组成&#xff0c;C语 言有…

测试工程师求职是选自研公司还是选外包公司呢?

大家好&#xff0c; 今天我们一起来聊一聊测试工程师求职是选自研公司&还是选外包公司呢&#xff1f; 今天来谈谈我的个人看法&#xff0c;作为一个在测试岗位上多年的我来说&#xff0c;自研公司比较好&#xff0c;外包公司其实也不会差。各自都有特点特色&#xff0c;根据…

虚拟主机VPS和共享服务器有什么区别?VPS和共享服务器怎么选择,VPS和云服务器区别

今天易极赞小编来跟大家科普一个新的知识“虚拟主机和云服务器有什么区别&#xff1f;”看完这篇文章后你应该就能知道虚拟主机和云服务器哪个更适合你了。 如果你不知道服务器的常见类型有哪些&#xff0c;查看下面这篇文章&#xff1a; 服务器7中常见的类型&#xff0c;服务…

刷力扣中学习使用static,final

. - 力扣&#xff08;LeetCode&#xff09;. - 备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/throne-inheritance/今天在力扣题中第一次使用了static和final&#xf…

Ceph学习 -3.存储简介

文章目录 1.存储简介1.1 存储类型1.1.1 储备知识1.1.2 三种存储1.1.3 块存储1.1.4 文件存储1.1.5 对象存储1.1.6 三种存储之间的关系1.1.7 总结 1.2 Ceph简介1.2.1 官方介绍1.2.2 软件特点1.2.3 基本结构1.2.4 应用场景 1.3 小结 1.存储简介 学习目标&#xff1a;这一节&#x…

Shiny Items VFX for URP

一系列令人惊叹且易于编辑的Shuriken粒子系统和粒子着色器&#xff0c;用于稀有物品、奖励或通电物品 用我的“闪亮物品”包提高你在URP项目中的稀有物品、奖项或电源的吸引力。 该包提供了使用Shuriken粒子系统创建的14个“项目”预制集&#xff0c;以及项目的自定义着色图着色…

PPP-B2b星历下载

目前做PPP-B2b研究比较多&#xff0c;其中PPP-B2b需要北斗的CNAV星历下载链接为&#xff08;例如2024.04.05对应的2024年第097天&#xff09;&#xff1a;数据下载http://www.csno-tarc.cn/datacenter/ephemeris

c++ Constraints 和 concepts介绍

C++20 引入了 Concepts,以改进模板编程的体验。Concepts 是一种用于模板编程的新机制,它允许程序员在编译时对模板参数进行约束和限制,从而提高模板的可读性、可维护性和错误检测能力。 Constraints(约束)是 Concepts 的一部分,它定义了模板参数必须满足的条件。一个约束…

《科技创业月刊》是什么级别的期刊?是正规期刊吗?能评职称吗?

问题解答&#xff1a;问&#xff1a;《科技创业月刊》是什么级别的刊物&#xff1f; 答&#xff1a;省级&#xff0c;主管单位&#xff1a; 湖北省科学技术厅 &#xff1b;主办单位&#xff1a;湖北省科技信息研究院 问&#xff1a;《科技创业月刊》是c刊吗&#xff1f; 答&…

Rustdesk二次编译,新集成AI功能开源Gpt小程序为远程协助助力,全网首发

环境&#xff1a; Rustdesk1.1.9 sciter版 问题描述&#xff1a; Rustdesk二次编译&#xff0c;新集成AI功能开源Gpt小程序为远程协助助力,全网首发 解决方案&#xff1a; Rustdesk二次编译&#xff0c;新集成开源AI功能Gpt小程序&#xff0c;为远程协助助力&#xff0c…

【C++】RapidJSON 设置支持 std::string,防止编译报错

问题 rapidjson 创建 json 数据&#xff0c;使用 std::string 字符串进行赋值&#xff0c;编译时&#xff0c;抱一堆错误 .... rapidjson/include/rapidjson/document.h:690:5: note: candidate expects 0 arguments, 1 provided [build] make[2]: *** [main/CMakeFiles/ma…

2024.4.7

1. 2列火车 #include<myhead.h>pthread_mutex_t m1; pthread_mutex_t m2;void* run(void* arg) {while(1){pthread_mutex_lock(&m1);printf("火车B进入\n");printf("A请等待\n");pthread_mutex_unlock(&m2);sleep(2);} }int main(in…

cookie、session、token的区别

这三者都和维持状态信息有关。比如我们如果在网页进行了一次登录&#xff0c;如果我们希望以后再访问该网页的时候&#xff0c;维持登录信息的话&#xff0c;就需要用到上面的这三种&#xff0c;如果不用的话&#xff0c;那么我们每次都需要携带登录信息到服务器&#xff0c;并…

海纳斯删除广告位

找到文件 vim /var/www/html/home.php 删除代码段 <div class"adleft" id"adleftContainer"><button onclick"closeAd()">关闭</button><a href"https://www.ecoo.top/ad.html" target"_blank">&l…

Android Studio学习16——Activity跳转时的参数传递

传递数据——example 传递对象类型的数据——example 传递 接收 回传数据——example

Docker容器(五)Docker Compose

一、概述 1.1介绍 Docker Compose是Docker官方的开源项目&#xff0c;负责实现对Docker容器集群的快速编排。Compose 是 Docker 公司推出的一个工具软件&#xff0c;可以管理多个 Docker 容器组成一个应用。你需要定义一个 YAML 格式的配置文件docker-compose.yml&#xff0c;…

风险评估在应对网络安全威胁中扮演着重要的角色

如今&#xff0c;IT 安全专家面临各种重大威胁&#xff0c;从勒索软件、网络钓鱼&#xff0c;到对基础设施的攻击&#xff0c;再到对知识产权、客户数据的窃取&#xff1b;从不安全的供应链合作伙伴&#xff0c;再到组织内部人员的恶意行为。同时&#xff0c;随着云计算、远程工…