Java字节流-InputStream与OutputStream

目录

1、字节流

1.1 InputStream

1.1.1 输入流读取方式1:

1.1.2 输入流读取方式2:

1.1.3 输入流读取方式3:

1.1.4 输入流读取方式4:

1.2 OutputStream

1.2.1 输出流写出方式1:

1.2.2 输出流写出方式2:

1.1.3 输出流写出方式3:

1.3 字节流文件拷贝

1.3.1 字节输入输出流综合使用

1.3.2 字节流拷贝文件实现1

1.3.3 字节流拷贝文件实现2

1.4 字节流的异常处理

1.5 字节缓冲流

1.5.1 缓冲流


1、字节流

什么是字节流

    计算机中都是二进制数据,一个字节是8个2进制位.字节可以表示所有的数据,比如文本,音频,视频.图片,都是作为字节存在的.也就是说字节流处理的数据非常多。

在文本文件中存储的数据是以我们能读懂的方式表示的。而在二进制文件中存储的数据是用二进制形式表示的。我们是读不懂二进制文件的,因为二进制文件是为了让程序来读取而设计的。例如,Java的源程序(.java源文件)存储在文本文件中,可以使用文本编辑器阅读,但是Java的类(字节码文件)存储在二进制文件中,可以被Java虚拟机阅读。二进制文件的优势在于它的处理效率比文本文件高。

   我们已经知道File对象封装的是文件或者路径属性,但是不包含向(从)文件读(写)数据的方法。为了实现对文件的读和写操作需要学会正确的使用Java的IO创建对象。

字节流的抽象基类:

   输入流:java.io.InputStream

   输出流:java.io.OutputStream

特点:

      字节流的抽象基类派生出来的子类名称都是以其父类名作为子类名的后缀。

      如:FileInputStream, ByteArrayInputStream等。

说明:

      字节流处理的单元是一个字节,用于操作二进制文件(计算机中所有文件都是二进制文件)

1.1 InputStream

案例:读取"c:/a.txt"文件中的所有内容并在控制台显示出来。

注意:事先准备一个a.txt并放到c:/下,不要保存中文。

      a, 使用read()方法实现。

      b, 使用int read(byte[] b)方法实现。

写代码读取"c:/a.txt"文件中的所有的内容并在控制台显示出来

实现:

查看api文档

InputStream 有read方法,一次读取一个字节,OutputStream的write方法一次写一个int。发现这两个类都是抽象类。意味着不能创建对象,那么需要找到具体的子类来使用。

通过查看api文档,找到了FileInputStream类,该类正是我们体验Io流的一个输入流。

实现;显示指定文件内容。

明确使用流,使用哪一类流?使用输入流,FileInputStream

第一步:

1:打开流(即创建流)

第二步:

2:通过流读取内容

第三步:

3:用完后,关闭流资源

显然流是Java中的一类对象,要打开流其实就是创建具体流的对象,由于是读取硬盘上的文件,应该使用输入流。所以找到了InputStream类,但是InputStream是抽象类,需要使用它的具体实现类来创建对象就是FileInputStream。通过new 调用FileInputStream 的构造方法来创建对象。发现FileInputStream的构造方法需要指定文件的来源。查看构造方法,可以接受字符串也可以接受File对象。我们通过构建File对象指定文件路径。

使用流就像使用水管一样,要打开就要关闭。所以打开流和关闭流的动作是比不可少的。如何关闭流?使用close方法即可,当完成流的读写时,应该通过调用close方法来关闭它,这个方法会释放掉十分有限的操作系统资源.如果一个应用程序打开了过多的流而没有关闭它们,那么系统资源将被耗尽.

   如何通过流读取内容?

查找api文档通过read方法,查看该方法,发现有返回值,并且是int类型的,该方法一次读取一个字节(byte)

1.1.1 输入流读取方式1:

read方法()

一次读取一个字节,读到文件末尾返回-1.

仔细查看api文档发现read方法如果读到文件的末尾会返回-1。那么就可以通过read方法的返回值是否是-1来控制我们的循环读取。

/**

     * 根据read方法返回值的特性,如果独到文件的末尾返回-1,如果不为-1就继续向下读。

     * */

private static void showContent(String path) throws IOException {

        // 打开流

        FileInputStream fis = new FileInputStream(path);

        int len = fis.read();

        while (len != -1) {

            System.out.print((char)len);

            len = fis.read();

        }

        // 使用完关闭流

        fis.close();

    }

我们习惯这样写:

/**

     * 根据read方法返回值的特性,如果独到文件的末尾返回-1,如果不为-1就继续向下读。

     * */

    private static void showContent(String path) throws IOException {

        // 打开流

        FileInputStream fis = new FileInputStream(path);

        int len;

        while ((len = fis.read()) != -1) {

            System.out.print((char) len);

        }

        // 使用完关闭流

        fis.close();

    }

1.1.2 输入流读取方式2:

使用read(byte[] b) 方法。使用缓冲区(关键是缓冲区大小的确定)

使用read方法的时候,流需要读一次就处理一次,可以将读到的数据装入到字节数组中,一次性的操作数组,可以提高效率。

问题1:缓冲区大小

那么字节数组如何定义?定义多大?

可以尝试初始化长度为5的byte数组。通过read方法,往byte数组中存内容

那么该read方法返回的是往数组中存了多少字节。

/**

     * 使用字节数组存储读到的数据

     * */

    private static void showContent2(String path) throws IOException {

        // 打开流

        FileInputStream fis = new FileInputStream(path);

        // 通过流读取内容

        byte[] byt = new byte[5];

        int len = fis.read(byt);

        for (int i = 0; i < byt.length; i++) {

            System.out.print((char) byt[i]);

        }

        // 使用完关闭流

        fis.close();

    }

问题一: 缓冲区太小:

   数据读取不完.

测试发现问题,由于数组太小,只装了5个字节。而文本的字节大于数组的长度。那么很显然可以将数组的长度定义大一些。例如1024个。

/**

     * 使用字节数组存储读到的数据

     * */

    private static void showContent2(String path) throws IOException {

        // 打开流

        FileInputStream fis = new FileInputStream(path);

        // 通过流读取内容

        byte[] byt = new byte[1024];

        int len = fis.read(byt);

        for (int i = 0; i < byt.length; i++) {

            System.out.print(byt[i]);

        }  

        // 使用完关闭流

        fis.close();

    }

问题二:缓冲区数组有默认值.

测试,打印的效果打印出了很多0,因为数组数组有默认初始化值,所以,我们将数组的数据全部都遍历和出来.现在需要的是取出数组中的部分数据.需要将循环条件修改仔细查看api文档。发现该方法read(byte[] b)返回的是往数组中存入了多少个字节。就是数组实际存储的数据个数。

/**

     * 使用字节数组存储读到的数据

     * */

    private static void showContent2(String path) throws IOException {

        // 打开流

        FileInputStream fis = new FileInputStream(path);

        // 通过流读取内容

        byte[] byt = new byte[1024];

        int len = fis.read(byt);

        for (int i = 0; i <len; i++) {

            System.out.print(byt[i]);

    }

       

        // 使用完关闭流

        fis.close();

    }

总结:

问题一:为什么打印的不是字母而是数字,

       是ascii码。

       如何显示字符,强转为char即可

问题二:注意:回车和换行的问题。

       windows的换车和换行是"\r\n" 对应码表是13和10 。

1.1.3 输入流读取方式3:

使用read(byte[] b,int off,int len)

查看api文档,

b显然是一个byte类型数组,当做容器来使用

off,是指定从数组的什么位置开始存字节

len,希望读多少个

其实就是把数组的一部分当做流的容器来使用。告诉容器,从什么地方开始装要装多少。

/**

     * 把数组的一部分当做流的容器来使用

     * read(byte[] b,int off,int len)

     */

    private static void showContent3(String path) throws IOException {

        // 打开流

        FileInputStream fis = new FileInputStream(path);

        // 通过流读取内容

        byte[] byt = new byte[1024];

        // 从什么地方开始存读到的数据

        int start = 5;

       

        // 希望最多读多少个(如果是流的末尾,流中没有足够数据)

        int maxLen = 6;

        // 实际存放了多少个

        int len = fis.read(byt, start, maxLen);

        for (int i = start; i < start + maxLen; i++) {

            System.out.print((char) byt[i]);

        }

        // 使用完关闭流

        fis.close();

    }

案例:测试skip方法

通过Io流,读取"c:/a.txt"文件中的第9个字节到最后所有的内容并在控制台显示出来。

分析:其实就是要跳过文件中的一部分字节,需要查找API文档。可以使用skip方法skip(long n),参数跟的是要跳过的字节数。

我们要从第9个开始读,那么要跳过前8个即可。

/**

     * skip方法

     *

     * */

    private static void showContent4(String path) throws IOException {

        // 打开流

        FileInputStream fis = new FileInputStream(path);

        // 通过流读取内容

        byte[] byt = new byte[1024];

        fis.skip(8);

        int len = fis.read(byt);

        System.out.println(len);

        System.out.println("**********");

        for (int i = 0; i < len; i++) {

            System.out.println((char) byt[i]);

        }

        // 使用完关闭流

        fis.close();

    }

1.1.4 输入流读取方式4:

使用缓冲(提高效率),并循环读取(读完所有内容).

总结:读完文件的所有内容。很显然可以使用普通的read方法,一次读一个字节直到读到文件末尾。为了提高效率可以使用read(byte[] byt);方法就是所谓的使用缓冲提高效率。我们可以读取大文本数据测试(大于1K的文本文件.)

/**

     * 使用字节数组当缓冲

     * */

    private static void showContent5(String path) throws IOException {

        FileInputStream fis = new FileInputStream(path);

        byte[] byt = new byte[1024];

        int len = fis.read(byt);

        System.out.println(len);

        String buffer = new String(byt, 0, len);

        System.out.print(buffer);

    }

注意:如何将字节数组转成字符串? 可以通过创建字符串对象即可。

发现:一旦数据超过1024个字节,数组就存储不下。

如何将文件的剩余内容读完?

我们可以通过通过循环保证文件读取完。

/**

     * 使用字节数组当缓冲

     * */

    private static void showContent7(String path) throws IOException {

        FileInputStream fis = new FileInputStream(path);

        byte[] byt = new byte[1024];

        int len = 0;

        while ((len = fis.read(byt)) != -1) {

            System.out.println(new String(byt, 0, len));

        }

    }

1.2 OutputStream

字节输出流

案例:

   1,写代码实现把"Hello World!"写到"c:/a.txt"文件中。

      a, c:/a.txt不存在时,测试一下。

      b, c:/a.txt存在时,也测试一下。

      要写两个版本:

      a, 使用write(int b) 实现。

      b, 使用write(byte[] b) 实现。

   2,在已存在的c:/a.txt文本文件中追加内容:“Java IO”。

显然此时需要向指定文件中写入数据。

使用的就是可以操作文件的字节流对象。OutputStream。该类是抽象类,需要使用具体的实现类来创建对象查看API文档,找到了OutputStream的实现类FileOutputStream 创建FileOutputStream 流对象,必须指定数据要存放的目的地。通过构造函数的形式。创建流对象时,调用了系统底层的资源。在指定位置建立了数据存放的目的文件。

流程:

   1:打开文件输出流,流的目的地是指定的文件 

   2:通过流向文件写数据

   3: 用完流后关闭流

1.2.1 输出流写出方式1:

使用write(int b)方法,一次写出一个字节.

在C盘下创建a.txt文本文件

import java.io.FileOutputStream;

import java.io.IOException;

public class IoTest2 {

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

        String path = "c:\\a.txt";

        writeTxtFile(path);

    }

    private static void writeTxtFile(String path) throws IOException {

        // 1:打开文件输出流,流的目的地是指定的文件

        FileOutputStream fos = new FileOutputStream(path);

        // 2:通过流向文件写数据

        fos.write('j');

        fos.write('a');

        fos.write('v');

        fos.write('a');

        // 3:用完流后关闭流

        fos.close();

    }

}

当c盘下的a.txt不存在会怎么样?

测试:将c盘下的a.txt文件删除,发现当文件不存在时,会自动创建一个。

注意:使用write(int b)方法,虽然接收的是int类型参数,但是write 的常规协定是:向输出流写入一个字节。要写入的字节是参数 b 的八个低位。b 的 24 个高位将被忽略。

1.2.2 输出流写出方式2:

使用write(byte[] b),就是使用缓冲.提高效率.

上述案例中的使用了OutputStram 的write方法,一次只能写一个字节。成功的向文件中写入了内容。但是并不高效,如和提高效率呢?是否应该使用缓冲,根据字节输入流的缓冲原理,是否可以将数据保存中字节数组中。通过操作字节数组来提高效率。查找API文档,在OutputStram类中找到了write(byte[] b)方法,将 b.length 个字节从指定的 byte 数组写入此输出流中。

如何将字节数据保存在字节数组中,以字符串为例,”hello , world” 如何转为字节数组。显然通过字符串的getBytes方法即可。

public class IoTest2 {

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

        String path = "c:\\a.txt";

        writeTxtFile(path);

    }

    private static void writeTxtFile(String path) throws IOException {

        // 1:打开文件输出流,流的目的地是指定的文件

        FileOutputStream fos = new FileOutputStream(path);

        // 2:通过流向文件写数据

        byte[] byt = "java".getBytes();

        fos.write(byt);

        // 3:用完流后关闭流

        fos.close();

    }

}

1.1.3 输出流写出方式3:

追加

仔细查看a.txt文本文件发现上述程序每运行一次,老的内容就会被覆盖掉。,那么如何不覆盖已有信息,能够往a.txt里追加信息呢。查看API文档,发现FileOutputStream类中的构造方法中有一个构造可以实现追加的功能FileOutputStream(File file, boolean append)  第二个参数,append - 如果为 true,则将字节写入文件末尾处,而不是写入文件开始处

private static void writeTxtFile(String path) throws IOException {

        // 1:打开文件输出流,流的目的地是指定的文件

        FileOutputStream fos = new FileOutputStream(path,true);

        // 2:通过流向文件写数据

        byte[] byt = "java".getBytes();

        fos.write(byt);

        // 3:用完流后关闭流

        fos.close();

    }

1.3 字节流文件拷贝

1.3.1 字节输入输出流综合使用

通过字节输出流向文件中写入一些信息,并使用字节输入流把文件中的信息显示到控制台上。

public class IoTest3 {

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

        String path = "c:\\b.txt";

        String content = "hello java";

        writeFile(path, content);

        readFile(path);

    }

    public static void writeFile(String path, String content)

            throws IOException {

        // 打开文件输出流

        FileOutputStream fos = new FileOutputStream(path);

        byte[] buffer = content.getBytes();

        // 向文件中写入内容

        fos.write(buffer);

        // 关闭流

        fos.close();

    }

    public static void readFile(String path) throws IOException {

        FileInputStream fis = new FileInputStream(path);

        byte[] byt = new byte[1024];

        int len = 0;

        while ((len = fis.read(byt)) != -1) {

            System.out.println(new String(byt, 0, len));

        }

        // 关闭流

        fos.close();

    }

}

注意输出流的细节:

上述案例中我们将输入流和输出流进行和综合使用,如果尝试将输出流换成文本文件就可以实现文件的拷贝了.

什么是文件拷贝?很显然,先开一个输入流,将文件加载到流中,再开一个输出流,将流中数据写到文件中。就实现了文件的拷贝。

分析:

第一步:需要打开输入流和输出流

第二步:读取数据并写出数据

第三步:关闭流

public class IoTest3 {

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

        String srcPath = "c:\\a.txt";

        String destPath = "d:\\a.txt";

        copyFile(srcPath, destPath);

    }

    public static void copyFile(String srcPath, String destPath)

            throws IOException {

    }

}

1.3.2 字节流拷贝文件实现1

读一个字节写一个字节read 和write

public class IoTest3 {

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

        String srcPath = "c:\\a.txt";

        String destPath = "d:\\a.txt";

        copyFile(srcPath, destPath);

    }

    public static void copyFile(String srcPath, String destPath)

            throws IOException {

        // 打开输入流,输出流

        FileInputStream fis = new FileInputStream(srcPath);

        FileOutputStream fos = new FileOutputStream(destPath);

        // 读取和写入信息

        int len = 0;

        while ((len = fis.read()) != -1) {

            fos.write(len);

        }

        // 关闭流

        fis.close();

        fos.close();

    }

}

文本文件在计算机中是以二进制形式存在的,可以通过io流来拷贝,那么图片能不能拷贝呢?视频呢?音频呢?

public class IoTest3 {

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

        String srcPath = "c:\\.jpg";

        String destPath = "d:\\.jpg";

        copyFile(srcPath, destPath);

    }

    public static void copyFile(String srcPath, String destPath)

            throws IOException {

        // 打开输入流,输出流

        FileInputStream fis = new FileInputStream(srcPath);

        FileOutputStream fos = new FileOutputStream(destPath);

        // 读取和写入信息

        int len = 0;

        while ((len = fis.read()) != -1) {

            fos.write(len);

        }

        // 关闭流

        fis.close();

        fos.close();

    }

}

测试统统通过,所以字节流可以操作所有的文件。只是发现程序很慢,需要很长时间。特别是拷贝音频和视频文件时。

为什么?因为每次读一个字节再写一个字节效率很低。很显然这样效率低下的操作不是我们想要的。有没有更快更好的方法呢,是否可以使用缓冲区来提高程序的效率呢。

1.3.3 字节流拷贝文件实现2

使用字节数组作为缓冲区

public static void copyFile2(String srcPath, String destPath)

            throws IOException {

        // 打开输入流,输出流

        FileInputStream fis = new FileInputStream(srcPath);

        FileOutputStream fos = new FileOutputStream(destPath);

        // 读取和写入信息

        int len = 0;

        // 使用字节数组,当做缓冲区

        byte[] byt = new byte[1024];

        while ((len = fis.read(byt)) != -1) {

            fos.write(byt);

        }

        // 关闭流

        fis.close();

        fos.close();

    }

问题1: 使用缓冲(字节数组)拷贝数据,拷贝后的文件大于源文件.

测试该方法,拷贝文本文件,仔细观察发现和源文件不太一致。

打开文件发现拷贝后的文件和拷贝前的源文件不同,拷贝后的文件要比源文件多一些内容问题就在于我们使用的容器,这个容器我们是重复使用的,新的数据会覆盖掉老的数据,显然最后一次读文件的时候,容器并没有装满,出现了新老数据并存的情况。

所以最后一次把容器中数据写入到文件中就出现了问题。

如何避免?使用FileOutputStream 的write(byte[] b, int off, int len)

b 是容器,off是从数组的什么位置开始,len是获取的个数,容器用了多少就写出多少。

public static void copyFile2(String srcPath, String destPath)

            throws IOException {

        // 打开输入流,输出流

        FileInputStream fis = new FileInputStream(srcPath);

        FileOutputStream fos = new FileOutputStream(destPath);

        // 读取和写入信息

        int len = 0;

        // 使用字节数组,当做缓冲区

        byte[] byt = new byte[1024];

        while ((len = fis.read(byt)) != -1) {

            fos.write(byt, 0, len);

        }

        // 关闭流

        fis.close();

        fos.close();

    }

使用缓冲拷贝视频,可以根据拷贝的需求调整数组的大小,一般是1024的整数倍。发现使用缓冲后效率大大提高。

1.4 字节流的异常处理

上述案例中所有的异常都只是进行了抛出处理,这样是不合理的。所以上述代码并不完善,因为异常没有处理。

当我们打开流,读和写,关闭流的时候都会出现异常,异常出现后,后面的代码都不会执行了。假设打开和关闭流出现了异常,那么显然close方法就不会再执行。那么会对程序有什么影响?

案例:

public class IoTest4 {

    public static void main(String[] args) throws IOException,

            InterruptedException {

        String path = "c:\\b.txt";

        readFile(path);

    }

    private static void readFile(String path) throws IOException,

            InterruptedException {

        FileInputStream fis = new FileInputStream(path);

        byte[] byt = new byte[1024];

        int len = fis.read(byt);

        System.out.println(new String(byt, 0, len));

        // 让程序睡眠,无法执行到close方法。

        Thread.sleep(1000 * 10);

        fis.close();

    }

}

在执行该程序的同时我们尝试去删除b.txt文件。如果在该程序没有睡醒的话,我们是无法删除b.txt 文件的。因为b.txt还被该程序占用着,这是很严重的问题,所以一定要关闭流。

目前我们是抛出处理,一旦出现了异常,close就没有执行,也就没有释放资源。那么为了保证close的执行该如何处理呢。

那么就需要使用try{} catch(){}finally{}语句。try中放入可能出现异常的语句,catch是捕获异常对象,fianlly是一定要执行的代码

public class IoTest4 {

    public static void main(String[] args) throws IOException,

            InterruptedException {

        String path = "c:\\b.txt";

        readFile(path);

    }

    private static void readFile(String path) {

        FileInputStream fis = null;

        try {

            fis = new FileInputStream(path);

            byte[] byt = new byte[1024];

            int len = fis.read(byt);

            System.out.println(new String(byt, 0, len));

        } catch (IOException e) {

            // 抛出运行时异常

            throw new RuntimeException(e);

        } finally {

            // close方法放入finally中保证一定会执行

            // 先判断是否空指针

            if (fis != null) {

                try {

                    fis.close();

                } catch (Exception e) {

                    throw new RuntimeException(e);

                }

            }

        }

    }

}

文件拷贝的异常处理:

public static void copyFile(String srcPath, String destPath) {

        FileInputStream fis = null;

        FileOutputStream fos = null;

        try {

            fis = new FileInputStream(srcPath);

            fos = new FileOutputStream(destPath);

            byte[] byt = new byte[1024 * 1024];

            int len = 0;

            while ((len = fis.read(byt)) != -1) {

                fos.write(byt, 0, len);

            }

        } catch (IOException e) {

            throw new RuntimeException(e);

        } finally {

            if (fis != null) {

                try {

                    fis.close();

                } catch (IOException e) {

                    throw new RuntimeException(e);

                }

            }

            if (fos != null) {

                try {

                    fos.close();

                } catch (IOException e) {

                    throw new RuntimeException(e);

                }

            }

        }

    }

注意:

在最后的close代码中可能会有问题,两个close,如果第一个close方法出现了异常,并抛出了运行时异常,那么程序还是停止了。下面的close方法就没有执行到。

那么为了保证close的执行,将第二个放到fianlly中即可。

public static void copyFile(String srcPath, String destPath) {

        FileInputStream fis = null;

        FileOutputStream fos = null;

        try {

            fis = new FileInputStream(srcPath);

            fos = new FileOutputStream(destPath);

            byte[] byt = new byte[1024 * 1024];

            int len = 0;

            while ((len = fis.read(byt)) != -1) {

                fos.write(byt, 0, len);

            }

        } catch (IOException e) {

            throw new RuntimeException(e);

        } finally {

            try {

                if (fis != null) {

                    fis.close();

                }

            } catch (IOException e) {

                throw new RuntimeException(e);

            } finally {

                if (fos != null) {

                    try {

                        fos.close();

                    } catch (IOException e) {

                        throw new RuntimeException(e);

                    }

                }

            }

        }

    }

1.5 字节缓冲流

1.5.1 缓冲流

上述程序中我们为了提高流的使用效率,自定义了字节数组,作为缓冲区.Java其实提供了专门的字节流缓冲来提高效率.

BufferedInputStream和BufferedOutputStream

BufferedOutputStreamBufferedOutputStream类可以通过减少读写次数来提高输入和输出的速度。它们内部有一个缓冲区,用来提高处理效率。查看API文档,发现可以指定缓冲区的大小。其实内部也是封装了字节数组。没有指定缓冲区大小,默认的字节是8192

显然缓冲区输入流和缓冲区输出流要配合使用。首先缓冲区输入流会将读取到的数据读入缓冲区,当缓冲区满时,或者调用flush方法,缓冲输出流会将数据写出。

注意:当然使用缓冲流来进行提高效率时,对于小文件可能看不到性能的提升。但是文件稍微大一些的话,就可以看到实质的性能提升了。

public class IoTest5 {

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

        String srcPath = "c:\\a.mp3";

        String destPath = "d:\\copy.mp3";

        copyFile(srcPath, destPath);

    }

    public static void copyFile(String srcPath, String destPath)

            throws IOException {

        // 打开输入流,输出流

        FileInputStream fis = new FileInputStream(srcPath);

        FileOutputStream fos = new FileOutputStream(destPath);

        // 使用缓冲流

        BufferedInputStream bis = new BufferedInputStream(fis);

        BufferedOutputStream bos = new BufferedOutputStream(fos);

        // 读取和写入信息

        int len = 0;

        while ((len = bis.read()) != -1) {

            bos.write(len);

        }

        // 关闭流

        bis.close();

        bos.close(); 

}

}

  

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

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

相关文章

代码随想录算法训练营DAY28(记录)|C++回溯算法Part.5|491.递增子序列、46.全排列、47.全排列II

文章目录 491.递增子序列思路伪代码CPP代码优化代码 46.全排列思路伪代码CPP代码 47.全排列IICPP代码 491.递增子序列 力扣题目链接 文章链接&#xff1a;491.递增子序列 视频连接&#xff1a;回溯算法精讲&#xff0c;树层去重与树枝去重 | LeetCode&#xff1a;491.递增子序列…

安装GPT 学术优化 (GPT Academic)@FreeBSD

GPT 学术优化 (GPT Academic)是一个非常棒的项目 可以帮助我们完成中科院的一些日常工作。 官网&#xff1a;GitHub - binary-husky/gpt_academic: 为GPT/GLM等LLM大语言模型提供实用化交互接口&#xff0c;特别优化论文阅读/润色/写作体验&#xff0c;模块化设计&#xff0c;…

win2022服务器apache配置https(ssl)真实环境实验(避坑之作)不依赖宝塔小皮等集成环境

本次实验背景&#xff1a; 完全参考官方 https://cloud.tencent.com/document/product/400/4143 文档流程&#xff0c;没有搞定&#xff0c;于是写下避坑之作。 服务器&#xff1a;腾讯云轻量应用服务器 操作系统&#xff1a; Windows Server 2022 DataCenter 64bit CN apache…

51-41 Stable Video Diffusion,高质量视频生成新时代

23年11月&#xff0c;Stability AI公司公开了稳定视频扩散模型Stable Video Diffusion(SVD)的代码和权重&#xff0c;视频生成迎来了新时代。SVD是一种潜在扩散模型&#xff0c;支持文本生成视频、图像生成视频以及物体多视角3D合成。从工程角度来看&#xff0c;本文主要提出了…

C++如何使用string类

文章目录 为什么要学习string?库中的string关于编码ASCII编码Unicode编码 迭代器Iteratorsstring常用构造接口接口声明与功能说明接口演示 string类对象的容量操作接口声明与功能说明接口演示reverse与resize在不同平台下的扩容与缩容机制 string类对象的访问及遍历操作接口声…

Java项目实现图形验证码(Hutool)

项目架构&#xff1a; 使用SpringCloudmysqlmybatis-plus需要将数据库中的数据导出到Excel文件中 前端为Vue2 业务场景&#xff1a; 登录时使用验证码登录 1.1 打开hutool, 搜索 图片验证码 1.2后端编写生产验证码方法 1.3前端 1.3.1展示验证码 1.3.2 前端方法 1.3.2.1UU…

Django中的数据库优化与ORM性能调优【第169篇—ORM性能调优】

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 Django中的数据库优化与ORM性能调优 在开发基于Django的Web应用程序时&#xff0c;数据库是…

ubuntu 查询mysql的用户名和密码 ubuntu查看username

ubuntu 查询mysql的用户名和密码 ubuntu查看username 文章标签mysqlUbuntu用户名文章分类MySQL数据库 一.基本命令 1.查看Ubuntu版本 $ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 16.04.5 LTS Release: 16.04 Coden…

leetcode-分割链表

题目 面试题 02.04. 分割链表 提示 给你一个链表的头节点 head 和一个特定值 x &#xff0c;请你对链表进行分隔&#xff0c;使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。 你不需要 保留 每个分区中各节点的初始相对位置。 示例 1&#xff1a; 输入&#xff…

linux-centos虚拟机设置固定ip

环境准备 虚拟机版本&#xff1a;centos7 安装环境&#xff1a;vmware17 1、设置网络连接 虚拟机-设置-网络适配器-NAT模式 2、查看子网信息 编辑-虚拟网络编辑器-NAT模式-NAT设置 查看子网ip和网关ip 下一步要用 3、修改配置文件 vim /etc/sysconfig/network-scripts…

BGP边界网关路由实验(华为)

一&#xff0c;技术简介 BGP&#xff08;边界网关路由协议&#xff09;是一种自治系统&#xff08;AS&#xff09;间的协议&#xff0c;主要用于在不同的AS之间交换路由信息。AS是一个由一组网络设备和路由器组成的网络集合&#xff0c;这些设备可以在一个共同的管理域中协同工…

Netty-NioServerSocketChannel与NioSocketChannel

NioServerSocketChannel NioServerSocketChannel是netty服务端的channel。在ServerbootStrap的bind方法中&#xff0c;通过反射&#xff0c;实例化对象NioServerSocketChannel。   NioServerSocketChannel对象实例化的过程中。 AbstractChannel中实例化channel的id&#xff…

【QT进阶】Qt Web混合编程之QWebEngineView基本用法

往期回顾 【QT入门】Qt自定义控件与样式设计之自定义QTabWidget实现tab在左&#xff0c;文本水平的效果-CSDN博客【QT进阶】Qt Web混合编程之CEF、QCefView简单介绍-CSDN博客 【QT进阶】Qt Web混合编程之VS2019 CEF的编译与使用-CSDN博客 【QT进阶】Qt Web混合编程之QWebEngi…

通过Idea部署Tomcat服务器

1.在idea中创建项目 有maven构建工具就创建maven&#xff0c;没有就正常创建一个普通的java程序 创建普通java项目 2.添加框架 3.配置 Tomcat 注意&#xff1a;创建web项目后我们需要配置tomcat才能运行&#xff0c;下面我们来进行配置。 4.添加部署 回到服务器 5.完善配置 6…

EFK环境搭建(基于K8S环境部署)

目录 一.环境信息二.安装nfs供应商三.安装elasticsearch四.安装kibana组件五.安装fluentd 一.环境信息 1.服务器及k8s版本 IP地址主机名称角色版本192.168.40.180master1master节点1.27192.168.40.181node1node1节点1.27192.168.40.182node2node2节点1.27 2.部署组件版本 序…

Python 数据结构和算法实用指南(二)

原文&#xff1a;zh.annas-archive.org/md5/66ae3d5970b9b38c5ad770b42fec806d 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第四章&#xff1a;列表和指针结构 我们已经在 Python 中讨论了列表&#xff0c;它们方便而强大。通常情况下&#xff0c;我们使用 Python…

近端安全互联样例使用指导

样例介绍 本样例基于rk3568开发板&#xff0c;通过封装openharmony安全子系统deviceauth组件提供的能力&#xff0c;实现了一组可用于设备间快速建立可信认证和连接的接口&#xff0c;通过预先定义关系网&#xff0c;在设备初始化阶段完成端端设备间的认证&#xff0c;构建安全…

ES源码四:网络通信层流程

听说ES网络层很难&#xff1f;今天来卷它&#x1f604; 前言 ES网络层比较复杂&#xff0c;分为两个部分&#xff1a; 基于HTTP协议的REST服务端基于TCP实现的PRC框架 插件化设计的网络层模块&#xff08;NetworkModule&#xff09; 入口还是上一章的创建Node构造方法的地方…

目标检测应用场景—数据集【NO.31】布匹数据集目标检测数据集

写在前面&#xff1a;数据集对应应用场景&#xff0c;不同的应用场景有不同的检测难点以及对应改进方法&#xff0c;本系列整理汇总领域内的数据集&#xff0c;方便大家下载数据集&#xff0c;若无法下载可关注后私信领取。关注免费领取整理好的数据集资料&#xff01;今天分享…

uniapp picker 多列选择器用法

uniapp picker 多列选择器联动筛选器交互处理方法&#xff0c; uniapp 多列选择器 mode"multiSelector" 数据及筛选联动交互处理&#xff0c; 通过接口获取数据&#xff0c;根据用户选择当前列选项设置子列数据&#xff0c;实现三级联动效果&#xff0c; 本示例中处…