java IO流基础 万字详解(从拷贝文件到模拟上传头像)

简介: java万字详解篇之IO流,非常详细,适合小白快速入门上手以及初学者查缺补漏。

 目录

一、前言:

二、IO流简介:

       1.什么是IO流?

       2.IO流能干什么?

       3.IO流的分类:

       4.IO流体系:

三、字符流读写文件:

       1.普通字符流读取文件:

               前言:        

               ①以单个字符读取:      

               代码演示(耐心全部看完!):

               ②以字符数组读取:

               代码演示:

       2.普通字符流写入文件:

               ①按单个字符写入:

               代码演示:

               ②按字符数组写入:

               代码演示:

               ③按字符串写入:

               代码演示:

       3.字符流拷贝文件:

               前言:

               IO流拷贝的核心六部曲(全文背诵!):

               ①以单个字符拷贝:

               代码演示:

               ②以字符数组拷贝:

               代码演示:

       4.字符缓冲流(高效字符流):

               ①字符缓冲流介绍:

               ②字符缓冲流的普通用法:

               代码演示:

               ③字符缓冲流的特有用法:

               代码演示:

四、字节流读写文件:

       1.前言:

       2.普通字节流用法:

               ①一次读写一个字节数组:            

               代码演示:

       3.高效字节流用法:

               ①前言

               ②write重载方法:

               代码演示:

五、IO流模拟上传头像系统:

六、完结撒❀ + 给自己打广告:


一、前言:

       大家好,今天给大家带来一篇详解javaIO流基础的博文(将来会出javaIO流进阶的内容分享,准备放在java进阶专栏),适合小白,初学者0基础学习或者查缺补漏,我会从字符流读写文件,字节流读写文件,高效字符流拷贝文件,以及高效字节流拷贝图片一一进行代码演示,特别注意:注释内容也是重点,(注释内容也是重点,注释内容也是重点)。不要眼高手低,跟着up一块儿练习,看完就能上手javaIO流。学习IO流基础需要有一定的javaSE基础,尤其是file类和Exception类。我之后会陆续出一系列专门讲javaSE基础的文章,把javaSE基础篇全讲一遍。所有文章都会适时补充完善,良工不示人以朴。PS:使用IEDA讲解,点击目录可以跳转。

二、IO流简介:

       1.什么是IO流?

       流是一种抽象概念,它代表了数据的无结构化传递。按照流的方式进行输入输出,数据被当成无结构的字节序或字符序列。从流中取得数据的操作称为提取操作,而向流中添加数据的操作称为插入操作。用来进行输入输出操作的流就称为IO流。换句话说,IO流就是以流的方式进行输入输出的,即数据像流体一样连绵不绝进行传输。

       I 即Input,输入。O 即Output,输出。

       2.IO流能干什么?

       IO流可以在本地磁盘和网络上对数据进行传输,比如说,字符流可以向一个空的文本文件中写入数据,或是从一个未知文本文件中读取数据,还可以进行文件的拷贝。而字节流则常用于拷贝图片。

       3.IO流的分类:

       关于IO流的分类,up认为一张图片便可清晰直观地解释,如图:

image.png

       4.IO流体系:

       不多bb,还是直接上图片!如图:

       首先是字符流:

image.png

        然后是字节流:

image.png

三、字符流读写文件:

       1.普通字符流读取文件:

               前言:        

               使用普通字符流来读取文件(FileReader)时,共有两种方式,分别是①以单个字符读取,②以字符数组读取,两种方式大同小异,因此up会重点把第一种详细讲好,第二种就没那么难了。        使用普通字符流来写入文件(FileWriter)时,一共有三种方式,分别是①以单个字符写入,②以字符数组写入,③以字符串形式写入,由于三种方式大同小异,up还是重点讲解第一种方式

               ①以单个字符读取:      

              步骤:

              1) 创建字符输入流对象,关联数据源文件 (建议第一步就抛出父类异常IOException)

              2) 定义变量,记录读取到的内容

              3) 循环读取,只要条件满足就一直读,并将读取到的内容赋值给变量

              4) 释放资源。(为防止遗忘,最好先释放资源。)

              读取方法:

               需要调用Reader类中的read() 方法:

               int read(): 每次读取一个字符,返回该字符对应的ASCII码值(整数), 若达到流的末尾,返回-1。如果有对ASCII码相关知识不了解的话,可以参考up之前写的博文:

https://blog.csdn.net/TYRA9/article/details/127197154?spm=1001.2014.3001.5501

               但由于Reader类是抽象类,因此需要多态的方式来实例化其子类。Reader类的常用子类是FileReader类。其构造方法为:

              public FileReader(String pathName) 需要传入要读取文件路径的字符串形式,来获取字符输入流对象。

               代码演示(耐心全部看完!):

               在代码演示前,先声明一点,因为我们现在要以单个字符的形式去读取文件,所以首先我们要有一个能读取的文件!eg(演示):up在D:/JAVA/ IDEA/ file文件夹下创建了一个1.txt文件,注意路径没必要和我一样,但你一定得知道你创建的文本文件的路径(建议用绝对路径)。如图:

image.png

               我们在1.txt文件中先写入01234进行测试,如图:

image.png          

   好的,接下来上代码,演示如何以单个字符形式读取文本文件1.txt:我们先在charactercurrent包下创建一个AsSingleCharacter类来作为演示类,r

image.png

                AsSingleCharacter类代码如下:

packageknowledge.iocurrent.charactercurrent;
importjava.io.FileReader;
importjava.io.Reader;
importjava.io.IOException;//虽然IDEA会自动导包,但是小心使得万年船,别忘了导包!!!/*** 字符流读数据*      Reader类中的方法*          int read():         每次读取一个字符,返回该字符对应的ASCII码值(整数),*                              若达到流的末尾,返回-1**       FileReader类的构造方法*          public  FileReader(String pathName)*          ①根据传入的字符串形式的路径,获取字符输入流对象*          ②注意因为Reader类是抽象类,所以需要通过多态的方式来实例化它的子类。*/publicclassAsSingleCharacter {
publicstaticvoidmain(String[] args) throwsIOException {
//1. 创建字符输入流对象,关联数据源文件。Readerreader=newFileReader("D:\\JAVA\\IDEA\\file\\1.txt");
//2.定义变量,记录读取到的内容。intdata;
/*因为不知道循环次数,所以要用while循环来实现*///3.循环读取,只要条件满足就一直读,并将读取到的内容赋值给变量/*while (r.read() != -1) {int data = r.read();System.out.println(data);}如果你这样写的话,每次循环开始前都会先在括号中执行read()方法,然后在循环体中又执行了一次,结果就是每次循环相当于执行两次read()方法,导致输出结果会事与愿违。*//* 正确写法如下: */while ((data=reader.read()) !=-1) {  //赋值表达式的值,就等于赋值后变量的值。System.out.println(data);
        }
//3.释放资源        //为防止遗忘,最好先释放资源reader.close();
    }
}

image.gif

               输出结果①_1:

image.png                        

没问题对应了01234的ASCII码值,48~52,这时候可以就要有小伙伴儿们问了,为啥我不能把01234怎么读取的就怎么输出,而只能输出它们的ASCII码值呢?

               这个问题非常容易,只需要将输出语句中System.out.println(data);改为System.out.println((char) data); 就可以了。我们来看一下输出结果:

image.gif编辑

               接下来我们对1.txt中的内容进行更改

image.png

               我们在01234后面加上了ABCDE和abcde,来测试一下它们的ASCII码值,注意先将输出语句中的(char)强制类型转化给去掉。

               输出结果①_2:

image.png

               可以看到,在原来的48~52下面,又多输出了65~69和97~101,即A~E和a~e分别对应的ASCII码值。 当然我们也可以再次把输出语句中的强制类型转化再加上,看看输出结果如何:

image.png

               准确输出了它们的字符形式!

               注意,这时候我们可以将println改成print(即每次输出不再换行),来看看输出效果:

               输出结果①_3:

image.png

               也符合我们预期,这时候可能就要有小伙伴儿们问了:你tm输出这一堆有什么**用啊?还不如换行输出看着整洁呢?

               别着急,重点来了,我们对1.txt文件本身先做一下手脚,如图:

image.png

               我们分别在4和E后面输入一个键盘上的Enter键,即我们平时所说的回车键。然后我们在强制类型转化的输出语句下输出.

               输出结果①_4:

image.png

               嗯,是不是整洁了许多,但是又有小伙伴儿们要问了:你tm耍我呢,这有啥看的?快**别卖关子了,你到底要说啥

               哎,别着急,现在我们再次把输出语句的强制类型转换(char)给去掉,并且把print语句再还原成println语句,下面就是见证奇迹的时刻(bushi)

               输出结果①_5:

image.png

               发现没! 在ASCII码值52和69的后面,凭空出现了13和10两个没见过的ASCII码值,那么,这到底是怎么回事呢?

               注意,52和69就是 4 和 E 分别对应的ASCII码值,而我们之前不正是在4和E后面输入了Enter键吗?所以说,多出的两个字符一定和敲下的那个回车键有关系,好奇心旺盛的up立刻去查询的ASCII码表,如图:

image.png

               经过查询我们发现,ASCII码值1310对应的字符分别叫做Line FeedCarriage Return,那么这俩是啥意思呢,我直接把网易翻译结果给小伙伴儿们看看:

image.png

               (重点)没错,ASCII码13对应的字符Carriage Return就是回车符,而ASCII码11对应的字符Line   Feed就是换行符。所以说明什么: 我们在输入Enter键的时候,达到的效果是:先输入一个回车符\r , 然后再输入一个换行符\n。其实,在不同操作系统中,输入Enter键所达到的效果都不一样,在Windows是'\r\n', 在Linux是'\n', 而在MacOS是'\r'。这就能解释我们为什么会得到这样的输出结果了。

               ②以字符数组读取:

               以单个字符的形式读取文件要是会了,这个就是小菜一碟了。老规矩,还是先把步骤和读取方法给大家说一下:

               步骤:

              1) 创建字符输入流对象,关联数据源文件 (建议第一步就抛出父类异常IOException)

              2) 定义变量,记录读取到的内容

               3) 循环读取,只要条件满足就一直读,并将读取到的内容赋值给变量

               4) 释放资源。(为防止遗忘,最好先释放资源。)

              读取方法:

              char[] charArray = new char[3];          //定义了一个初始长度为3 的字符数组

              int len = reader.read(charArray);          //该方法可以读取指定个数的字符你所定义的字符数组中,然后返回读取到的有效字符数

               代码演示:

               老规矩,我们先创建一个文本文件来模拟要读取的文件,up在D:/JAVA /IDEA/ file/ 文件夹下创建了一个2.txt文件,(自由创建,但一定要保证你能找到这个文件),建议用绝对路径。

image.png

               然后我们在2.txt文件中写入一些东西,如图,up写入了一句诗:

image.png

               然后我们在charactercurrent包下创建一个AsCharArray类,用作代码演示,如图:

image.png

                好的,如下是AsCharArray类的代码(一定要认真看注释):

packageknowledge.iocurrent.charactercurrent;
importjava.io.FileNotFoundException;
importjava.io.FileReader;
importjava.io.IOException;
importjava.io.Reader;
/***  //步骤:**  1) 创建字符输入流对象,关联数据源文件(建议第一步就抛出父类异常IOException)**  2) 定义变量,记录读取到的内容**  3) 循环读取,只要条件满足就一直读,并将读取到的内容赋值给变量**  4) 释放资源。(为防止遗忘,最好先释放资源。)**  //读取方法:*  char[] charArray = new char[3];   //定义了一个初始长度为3 的字符数组*  int data = reader.read(charArray);**/publicclassAsCharArray {
publicstaticvoidmain(String[] args) throwsFileNotFoundException, IOException {
//1.创建字符输入流对象,关联数据源文件(建议第一步就抛出父类异常IOException)Readerreader=newFileReader("D:\\JAVA\\IDEA\\file\\2.txt");
//2.定义变量,记录读取到的内容char[] charArray=newchar[3];   //定义了一个初始长度为3 的字符数组inti1=reader.read(charArray);//第一次读取/*字符串的底层,其实就是一个字符数组,所以此处会将字符数组中的内容自动拼接成字符串*/System.out.println("👴看看第一次读到了些啥:");
System.out.println(charArray);
System.out.println("第一次读取到的有效字符数是:"+i1);     //有效字符数3System.out.println("--------------------------");
inti2=reader.read(charArray);//第二次读取System.out.println("👴看看第二次读到了些啥:");
System.out.println(charArray);
System.out.println("第二次读取到的有效字符数是:"+i2);     //有效字符数3System.out.println("--------------------------");
inti3=reader.read(charArray);//第三次读取System.out.println("👴看看第三次读到了些啥:");
System.out.println(charArray);
System.out.println("第三次读取到的有效字符数是:"+i3);     //有效字符数3System.out.println("--------------------------");
inti4=reader.read(charArray);//第四次读取System.out.println("👴看看第四次读到了些啥:");
System.out.println(charArray);
System.out.println("第四次读取到的有效字符数是:"+i4);     //有效字符数3System.out.println("--------------------------");
inti5=reader.read(charArray);//第五次读取System.out.println("👴看看第五次读到了些啥:");
System.out.println(charArray);
System.out.println("第五次读取到的有效字符数是:"+i5);     //有效字符数3System.out.println("--------------------------");
inti6=reader.read(charArray);//第六次读取System.out.println("👴看看第六次读到了些啥:");
System.out.println(charArray);
System.out.println("第六次读取到的有效字符数是:"+i6);     //有效字符数1System.out.println("=========================================");
/*发现没有? 第六次用charArray这个数组来读时,输出结果为”。度秋“,而且有效字符数是1,这说明每次3个3个的读取,其实本质是将读取到的内容覆盖掉数组中原本的内容,但因为我们创建的2.txt文本文件中,一共16个字符,所以第六次读取时,仅能读到最后的句号“。”这一个字符了,所以仅能覆盖掉第一个内容,即“几度秋”变成了“。度秋” .*//*用While循环优化以上代码;*///3.循环读取,只要条件满足就一直读,并将读取到的内容赋值给变量//定义一个字符数组//define a variable which can record the number of valid characterintcount;
while ((count=reader.read(charArray)) !=-1) {
/**可以将读取到的内容转换成字符串,并打印出来,这里利用了String的一个特别构造* */StringcharString=newString(charArray, 0, count);
/** 该构造方法需要传入字符数组名, 起始索引, 以及有效字符数(特别注意这个有效字符数)* (String这个构造器中三个参数的作用:)the function of three parameter*   ①charArray : 表示要使用的数组(用这个数组来读取内容)*   ②0 : 表示起始索引*   ③len : 表示 要操作的字符 的个数*   //注意:如果这里只传入数组名,那么会全部转化,即像原来一样:*     当文件中的剩余字符数小于既定数组长度时能覆盖几个覆盖几个。* */System.out.println(charString);
System.out.println(count);
        }
//4.释放资源// 一定要记得释放reader.close();
    }
}
/*** 总结*      ①利用字符输入流的r.read(字符数组);的方法按字符数组读取文件时,数组内的内容每次都会被*      重新覆盖(覆盖范围是既定的数组的长度) ,若剩余有效符数小于既定数组长度,则能覆盖几个覆盖几个*      ,剩下的还是上次覆盖的内容。*      ②空格对文件的影响还是很大的*      ③同一个字符输入流读文件对象 在读取文件时是一定的,即读到哪儿就算那儿,倘若已经读到了流的末尾,*      再读一遍就需要创建新的读文件对象了,(其实有更好的方法,我们在IO流进阶中再进行讲解),*      这是因为当前字符流相当于已经读完了。*/

image.gif

               输出结果②_1:

image.pngimage.png

                输出结果②_1解读:

               (其实注释里说得已经很详细了,这里再说一遍就是怕有些头铁娃只看代码,不看注释。

               我们先定义了一个长度为3的字符数组,也就是说每次都读取3个字符,由于字符串的底层,其实就是一个字符数组,所以此处会自动将字符数组中的内容拼接成字符串。 我们之前在2.txt文件中输入的“闲云潭影日悠悠,物换星移几度秋。”共16个字符,所以前五次读取的结果都是返回3个有效字符,而第六次用charArray这个数组来读时,输出结果为”。度秋“ ,而且有效字符数是1,这说明每次3个3个的读取,其实本质是将读取到 的内容覆盖掉数组中原本的内容,所以第六次读取时,仅能读到最后的句号“。”这一个字符了, 所以仅能覆盖掉第一个内容,即“几度秋”变成了“。度秋” .

               同理也能说明,为什么我们在分割线下面用了while循环来优化代码后,啥都没有读到,同一个字符输入流读文件对象 在读取文件时是一定的,即读到哪儿就算那儿,倘若已经读到了流的末尾,再读一遍就需要创建新的读文件对象了,(其实有更好的方法,我们以后会在IO流进阶中再进行讲解,这篇万字详解只针对基础部分,根本目的是为了让小白快速上手和初学者查缺补漏的),这是因为当前字符流相当于已经读完了。

               为了不让我们写得while循环代码读了个寂寞,我们在2.txt文本文件下增加一些内容,如图:(特别注意我们之前说过,在windows下一个Enter键相当于\r\n两个字符

image.png

       注意,由于多加了字符,所以之前的第六次读取的  “。度秋”  就会变成  “” ,因为加上\r\n就是三个字符啦。

       输出结果②_2:

image.png

               输出结果②_1解读:

               注意看,首先是第六次的输出结果确实如我们所料,变成了“。”  其次是我们用循环读取的结果,最后一次是“。”,而不是“。自流”.  这就是因为我们所用的String构造器的原因,如果在String构造器中你只传入数组名,而不传入起始索引和有效字符数的话,输出结果就是“。自流”了.   如图:

image.png

       2.普通字符流写入文件:

               ①按单个字符写入:

              步骤:

               创建字符输出流对象,关联目的地文件。(建议第一步就抛出父类异常IOException)

               将目标数据写入到目的地文件中。

               释放资源      

              写入方法:

               需要调用Writer类中的void write(int ch) 方法,该方法返回值为void类型,因此不需要作接收,使用该方法需要传入一个字符(别忘了加单引号) ,达到的效果就是可以一次写入一个字符。因为Writer类是抽象类,所以我们使用多态的方式初始化它的子类。Writer类的常用子类是FileWriter类。其构造方法为:

               public FileWriter(String pathname) ,该构造器需要传入 目的地文件的路径 的 字符串形式,以获取字符输出流对象。

               代码演示:

               老规矩,我们先创建一个空的文本文件来模拟要写入的文件,up在D:/JAVA /IDEA/ file/ 文件夹下创建了一个3.txt文件,(自由创建,但一定要保证你能找到这个文件),建议用绝对路径。如图:

image.png

               然后我们看一下3.txt中的内容,一开始就是空的,如图:

image.png        

 俗话说的好:“地上种了菜,就不易长草” 。我们赶紧想办法给它写入点东西,直接输进去多普通啊,咱好歹是个程序猿,得,IO输出流直接搞定。

               我们现在在charactercurrent包下,创建一个WriteData1类用作演示类,代码如下:

packageknowledge.iocurrent.charactercurrent;
importjava.io.FileWriter;
importjava.io.IOException;
importjava.io.Writer;
/*** 字符流写数据* Writer类中的方法:*      void write(int ch)                             一次写一个字符*     *  FileWriter类中的构造方法 :*      public FileWriter(String pathname)          根据传入的字符串形式的路径,获取字符输出流对象*/publicclassWriteData1 {
publicstaticvoidmain(String[] args) throwsIOException {
//1.创建字符输出流对象,关联目的地文件Writerwriter=newFileWriter("D:\JAVA\IDEA\file\3.txt");
//2.将目标数据写入到目的地文件中writer.write(' ');  //写入一个空格writer.write(' ');
writer.write(' ');
writer.write(' ');
writer.write(' ');
writer.write(' ');
writer.write('滕');
writer.write('王');
writer.write('阁');
writer.write('\n');
//3.释放资源writer.close();
    }
}
/*summary://注意①, 调用write方法会覆盖文件中原有的内容//注意②, 若部分write方法被注释掉,那么再次运行时,其内容也会被覆盖*/

image.gif

               代码运行效果:

image.png

               可以看到我们创建的3.txt文件下成功输入了内容:滕王阁

               这里要注意一点就是,如果文件中原本就有内容,那么输入流写入文件时会对文本中的内容进行覆盖。 举个栗子:

               如图,当我们3.txt文件中本来就有内容时:

image.png    

此时 我们再次运行就又会得到:

image.png

               没错,这就是需要注意的一个点。

               ②按字符数组写入:

              步骤:

               创建字符输入流对象,关联目的地文件。(建议第一步就抛出父类异常IOException)

               将目标内容写入到目的地文件中

               释放资源

              写入方法:

               先创建一个字符型数组,并在数组中输入你想输入的内容,然后调用Write类中的方法:       void write(char[] c, int index, int len)         一次写一个指定的字符数组,需要传入数组名起始索引,和有效字符的总长度

               注意,这个方法也可以是        void write (char[] c),        即只传入数组名,这个方法会将数组中的全部内容都写进去。

               获取输出流对象的方式与前面以单个字符写入时相同,这里就不再赘述了,以下同理。

               代码演示:

              老规矩, 欸,这次没有老规矩了!我们就在之前创建的3.txt下继续操作。理由就是up想整点儿私货(bushi)。看一下我们3.txt目前的状况,如图:

image.png

               好的,我们还是在charactercurrent包下创建一个WriteData2类,用作我们的演示类,如图:

image.png

                WriteData2类代码如下:

packageknowledge.iocurrent.charactercurrent;
importjava.io.FileWriter;
importjava.io.IOException;
importjava.io.Writer;
/*** 字符流写数据* Writer类中的方法:*      void write(char[] c, int index, int len)       一次写一个指定的字符数组**  FileWriter类中的构造方法 :*      public FileWriter(String pathname)          根据传入的字符串形式的路径,获取字符输出流对象*/publicclassWriteData2 {
publicstaticvoidmain(String[] args) throwsIOException {//这里直接就抛出了父类异常//1.创建字符输出流对象,关联目的地文件Writerwriter=newFileWriter("D:\\JAVA\\IDEA\\file\\3.txt");
//2.将目标数据写入到目的地文件中writer.write(' ');  //写入一个空格writer.write(' ');
writer.write(' ');
writer.write(' ');
writer.write(' ');
writer.write(' ');
writer.write('滕');
writer.write('王');
writer.write('阁');
writer.write('\n');
/*这里我们把之前WriteData1类中的代码拷贝过来,因为write() 方法会覆盖原有的内容,而up为了整点儿私活,肯定不能让它随便就给覆盖了,如何让它留下?把之前写入原有内容的代码复制粘贴过来不就行了。*//*这里我们创建两个数组,把两个写入方法都给大家演示一遍,其中:charArray1用于演示  void write(char[] c, int index, int len)charArray2用于演示  void write(char[] c)*/char[] charArray1= {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '(', '唐', ')', '嘿'};
char[] charArray2= {'王', '勃', '\n'};
writer.write(charArray1, 0, 12);
writer.write(charArray2);
//3.释放资源writer.close();
    }
}
/*summary://注意①, 调用write方法会覆盖文件中原有的内容//注意②, 若部分write方法被注释掉,那么再次运行时,其内容也会被覆盖*/

image.gif

               看一下运行效果:

image.png

               嗯,非常完美。

              ③按字符串写入:

              步骤:(其实三种写入方法步骤都差不多,重复写属实有凑字数嫌疑(bushi))

               创建字符输出流对象,关联目的地文件。(建议第一步就抛出父类异常IOException)

               将目标内容写入到目的地文件中

               释放资源

              写入方法:

               与上述写入方式大同小异,此处直接调用write (String str)  方法就🆗了,eg:write("我写代码两年半");

               代码演示:

               老规矩,好吧,我们这次也继续在3.txt文本文件下操作,同时把之前写入内容的代码拷贝过来,以防止就有内容被新的写入语句写入的内容覆盖。我们在charactercurrent包下创建WriteData3类,用作演示,代码如下:

packageknowledge.iocurrent.charactercurrent;
importjava.io.FileWriter;
importjava.io.IOException;
importjava.io.Writer;
/*** 字符流写数据* Writer类中的方法:*      void write(String str)                         一次写一个字符串**  FileWriter类中的构造方法 :*      public FileWriter(String pathname)          根据传入的字符串形式的路径,获取字符输出流对象*/publicclassWriteData3 {
publicstaticvoidmain(String[] args) throwsIOException {//这里直接就抛出了父类异常//1.创建字符输出流对象,关联目的地文件Writerwriter=newFileWriter("D:\\JAVA\\IDEA\\file\\3.txt");
//2.将目标数据写入到目的地文件中writer.write(' ');  //写入一个空格writer.write(' ');
writer.write(' ');
writer.write(' ');
writer.write(' ');
writer.write(' ');
writer.write('滕');
writer.write('王');
writer.write('阁');
writer.write('\n');
/*这里我们把之前WriteData1类中的代码拷贝过来,因为write() 方法会覆盖原有的内容,而up为了整点儿私活,肯定不能让它随便就给覆盖了,如何让它留下?把之前写入原有内容的代码复制粘贴过来不就行了。*//*这里我们创建两个数组,把两个写入方法都给大家演示一遍,其中:charArray1用于演示  void write(char[] c, int index, int len)charArray2用于演示  void write(char[] c)*/char[] charArray1= {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '(', '唐', ')', '嘿'};
char[] charArray2= {'王', '勃', '\n'};
writer.write(charArray1, 0, 12);
writer.write(charArray2);
/*好的,接下来是演示以字符串形式写入:*/writer.write("滕王高阁临江渚,佩玉鸣鸾罢歌舞。\n");
writer.write("画栋朝飞南浦云,珠帘暮卷西山雨。\n");
writer.write("闲云潭影日悠悠,物换星移几度秋。\n");
writer.write("阁中帝子今何在?槛外长江空自流。");
//3.释放资源writer.close();
    }
}
/*summary://注意①, 调用write方法会覆盖文件中原有的内容//注意②, 若部分write方法被注释掉,那么再次运行时,其内容也会被覆盖*/

image.gif

               OK,来看一下最终的效果图:

image.png

               呃,好吧,就是和大家分享一首up喜欢的诗。你们要是有兴趣也可以试着把滕王阁序整篇写入到一个文本文件里。hahah(bushi) 。废号少说,我们接着继续讲解:

       3.字符流拷贝文件:

               前言:

               其实,所谓字符流拷贝文件,无非就是把我们前面的字符流读取和字符流写入给放一块儿了,结合起来使用,先用字符输入流读取XX文件的内容,再用字符输出流把读取到的XX文件中的内容写入到另一个YY文件,可不就叫拷贝么!所以,只要你前面的读取和写入扎扎实实走了一遍,这里的拷贝就tm简单地一塌糊涂!

               IO流拷贝的核心六部曲(全文背诵!):

               1)创建字符(字节)输入流对象,关联数据源文件

               2)创建字符(字节)输出流对象,关联目的地文件

               3)定义变量,记录读取到的内容

               4)循环读取,只要条件满足就一直读,并将读取到的内容赋值给变量

               5)将读取到的数据写入到 目的地文件中

               6)释放资源。

               ①以单个字符拷贝:

               步骤:

               上面核心六部曲

               代码演示:

               我们试着将 ”3.txt“ 中的滕王阁诗拷贝到 ”拷贝到这里.txt" 中,如图:

image.png

               注意看“拷贝到这里来.txt” 大小0kb, 是空的,点击后也是空空如也:

image.png

               然后我们还是先在character包下创建一个演示类:CopyAsSingleCharacter类,如图,:

image.png

               CopyAsSingleCharacter类代码如下:

packageknowledge.iocurrent.charactercurrent;
importjava.io.*;//*式的导包可以一次性导入一个包中所有的引用类,只是会降低编译速度,但是不影响运行速度。/**IO流拷贝文件核心六步曲1.创建字符输入流对象,关联数据源文件2.创建字符输出流对象,关联目的地文件3.定义变量,记录读取到的内容4.循环读取,只要条件满足就一直读,并将读取到的内容赋值给变量5.将读取到的数据写入到  目的地文件中6.释放资源。* */publicclassCopyAsSingleCharacter {
//通过字符流拷贝文件,一次拷贝一个字符 eg: 将a.txt -> b.txt 中publicstaticvoidmain(String[] args) throwsIOException {
//1. 创建字符输入流对象,关联数据源文件Readerreader=newFileReader("D:\\JAVA\\IDEA\\file\\3.txt");
//2. 创建字符输出流对象,关联目的地文件Writerwriter=newFileWriter("D:\\JAVA\\IDEA\\file\\拷贝到这里来.txt");
//3. 定义变量,记录读取到的内容intdata;
/*此处不需要赋初值,因为整数型默认是0*///4. 循环读取(用while),只要条件满足就一直读,并将读取到的内容赋值给变量。while ((data=reader.read()) !=-1)  //赋值表达式的值就是赋值后变量的值。        {
//5. 将读取到的数据写入到  目的地文件中writer.write(data);
        }
/*写入方法是如何实现的呢?为什么传入的是一个int类型的值?因为去查看JDK17的API就会发现,write方法写入一个字符, 需要传入的形参就是int类型,只不过将底层的实现细节隐藏了而已,这也是面向对象编程的特点。*///6.释放资源//但凡是IO流都要记得释放资源reader.close();
writer.close();
    }
}
/** 如果目的地文件不存在, 程序会自动创建*/

image.gif

                好的,看一下运行之后的效果:

image.png

                Perfect!

               ②以字符数组拷贝:

               步骤:

               还是上面核心六部曲 ,只不过读写部分是按字符数组读写罢了。字符数组上面也已经较为详细的讲过了,还没把握的小伙伴儿们可以跳转回去看看。

               代码演示:

               我们试着将 “3.txt” 文本文件中的滕王阁诗拷贝到 "拷贝到这里来2.txt" 文件中来,但这次是以字符数组的形式。我们先创建一个目的地文件,如图:

image.png

然后,我们在charactercurrent包下创建一个CopyAsCharArray类,用作拷贝的演示类,如图:

image.png

               来看下CopyAsCharArray类的代码演示:

packageknowledge.iocurrent.charactercurrent;
importjava.io.Reader;
importjava.io.FileReader;
importjava.io.Writer;
importjava.io.FileWriter;
importjava.io.IOException;
/**** IO流拷贝文件核心六步曲:*      1.创建字符输入流对象,关联数据源文件*      2.创建字符输出流对象,关联目的地文件*      3.定义变量,记录读取到的内容*      4.循环读取,只要条件满足就一直读取,并将读到的内容赋值给变量*      5.将读取到的数据写入到  目的地文件中*      6.释放资源*/publicclassCopyAsCharArray {
publicstaticvoidmain(String[] args) throwsIOException{
// 1.创建字符输入流对象,关联数据源文件Readerr=newFileReader("D:\\JAVA\\IDEA\\file\\3.txt");
// 2.创建字符输出流对象,关联目的地文件Writerw=newFileWriter("D:\\JAVA\\IDEA\\file\\拷贝到这里来2.txt");
char[] cArray=newchar[1024];
/*所定义数组的长度最好是1024的整数倍。*/// 3.定义变量,记录读取到的内容intlen;
// 4.循环读取,只要条件满足就一直读取,并将读到的内容赋值给变量while ((len=r.read(cArray)) !=-1)
        {
// 5.将读取到的内容写入到目的地文件中w.write(cArray, 0, len);     //这个方法重载我们在之前的以字符数组的形式写入那里讲过噢        }
System.out.println("给👴看看数组成什么样儿了:\n");
System.out.println(cArray);
System.out.println(""+cArray);
/*如果输出语句中写作了 “” + cArray, 那么打印出的cArray就只是它的地址值,所以此处应该分开写。*/// 6.释放资源r.close();
w.close();
    }
}

image.gif

               运行结果:

image.png                                

               后面那一长串尾巴是cArray中没内容的空字符。 来看一下运行效果:

image.png

成功将滕王阁诗又拷贝到了 "拷贝到这里来2.txt"  文件中。  

       4.字符缓冲流(高效字符流):

               ①字符缓冲流介绍:

               字符缓冲流,又叫做高效字符流字符缓冲流自带有缓冲区,大小为8192个字符,也就是16KB。 (即字节数:16*1024 == 8192*2) ---->(Unicode编码一个中文或英文字符都是 占两个字节)。

               ②字符缓冲流的普通用法:

               使用字符缓冲流来拷贝文件时,依然遵循经典的IO流拷贝文件核心六部曲,因此为什么我强调要把IO流拷贝文件核心六部曲全文背诵?因为太经典了!几乎可以可以做到一招通吃。但是,与之前有差异的地方在于在创建高效字符输入流对象时,并不是直接传入数据源文件的路径了,而是要传入一个普通的字符输入流对象,而我们知道,普通读文件对象在创建时传入的就是数据源文件的路径了,因此,可以概括为:创建高效字符输入流对象需要传入一个‘已经关联数据源文件的普通字符输入流对象’。仔细品味这句话,高效字符输出流也是同理。一下子看不懂也没有关系,毕竟都是带抽象,没上手过纯纯天书,还是直接举个栗子直观一点:

//声明:以下是仅作差异演示的代码段,并不完整,完整代码在之后的代码演示中会有//1.我们先创建一个普通字符输入流对象Readerreader=newFileReader("Test/1.txt");
//2.好,有了普通字符输入流对象后,我们就可以创建高效字符输入流对象了。BufferedReaderbufferedReader=newBufferedReader(reader);
//这样我们就得到了一个高效字符输入流对象。//其实,实际开发中往往采用链式编程优化代码,如下:BufferedWriterbufferedWriter=newBufferedWriter(newFileWriter("Test/2.txt"));
//说白了就是把1. 2. 两步合起来了,看着简洁直观。

image.gif

               好的,看完这波带栗子,小伙伴儿应该会好理解一丢丢了。

               代码演示:

               我们先创建一个数据源文件,up是在D:/JAVA/IDEA/file/a文件夹下创建了一个“高效字符流滴数据源文件.txt” 文本文件。

image.png

               接着我们在该源文件下输入一些东西,如图:

image.png 

我们再创建一个空的目的地文件,up是在D:/JAVA/IDEA/file/a文件夹下创建了一个“高效字符流滴目的地文件.txt” 文本文件。如图:

image.png

OK,准备工作做完后我们在charactecurrent包下,buffered包下创建一个OrdinaryUse类,如图:

image.png

               OrdinaryUse类代码如下:

packageknowledge.iocurrent.charactercurrent.buffered;
importjava.io.IOException;
importjava.io.FileWriter;
importjava.io.FileReader;
importjava.io.BufferedWriter;
importjava.io.BufferedReader;
/**** 特点:*      ①字符缓冲流(高效字符流)    自带有缓冲区,大小为8192个字符,也就是16KB。*      (即字节数:16*1024 == 8192*2) (Unicode一个中或英文字符都是  占两个字节)②需注意,高效字符输入流与之前有差异的地方在于,*   在创建高效字符输入流对象时,并不是直接传入数据源文件的路径了,而是要传入一个*   普通的字符输入流对象,而我们知道,普通读文件对象在创建时传入的就是数据源文件*   的路径了,因此,可以概括为:创建高效字符输入流对象需要传入一个‘已经关联数据*   源文件的普通字符输入流对象’。*/publicclassOrdinaryUse {
publicstaticvoidmain(String[] args) throwsIOException{
//需求:使用高效字节流拷贝文件。//1.创建(高效)字符输入流对象,关联数据源文件(此处直接采用链式编程)BufferedReaderbufferedReader=newBufferedReader(newFileReader("D:\\JAVA\\IDEA\\file\\a/高效字符流滴数据源文件.txt"));
//2.创建(高效)字符输出流对象,关联目的地文件(此处直接采用链式编程)BufferedWriterbufferedWriter=newBufferedWriter(newFileWriter("D:/JAVA/IDEA/file/a/高效字符流滴目的地文件.txt"));
//3.定义变量,记录读取到的内容intlen;
//4.循环读取,只要条件满足就一直读取,并将读取到的内容赋值给变量while ((len=bufferedReader.read()) !=-1)
        {
//5.将读取到的数据写入到目的地文件中。bufferedWriter.write(len);                      //此处为单个字符写入        }
//6.释放资源bufferedReader.close();
bufferedWriter.close();
    }
}
/*Notice:这里的while循环,表面上看着就像六部曲的一次读写一个字符,但底层实际是按字符数组读取的。*/

image.gif

               看一下运行效果如何:

image.png  

very good。成功拷贝到了目的地文件中。

               ③字符缓冲流的特有用法:

               BufferedReader类中的方法:

               public String readLine() : 一次读取一行数据并返回读取到的内容,读不到返回null,

               该方法可以用String类型的变量作接收。

               BufferedWriter类中的方法:

               public void newLine: 根据当前操作系统给出相应的换行符 (注释中有详解)

               代码演示:

               准备工作: 这次我们就不再创建新的文本文件了,我们就直接拿来主义,用刚刚创建的两个文件算了。绝不是因为我懒!我们先把“高效字符流地数据源文件.txt” 中的内容改一下,如图:

image.png

               🆗,我们还是在charactecurrent包下,buffered包下创建一个UniqueUse类,如图:

image.png

               UniqueUse类代码如下:

packageknowledge.iocurrent.charactercurrent.buffered;
importjava.io.BufferedReader;
importjava.io.BufferedWriter;
importjava.io.FileReader;
importjava.io.FileWriter;
importjava.io.IOException;
//注意独有方法的返回值类型/** 字符缓冲流独有拷贝方式  ————  一次读取一行数据*      分类:*          BufferedReader: 字符缓冲输入流(也叫高效字符输入流)*              成员方法:*                  public String readLine() :  一次读取一行数据并返回读取到的内容,读不到返回null*          BufferedWriter: 字符缓冲输出流(也叫高效字符输出流)*              成员方法:*                  public void newLine: 根据当前操作系统给出相应的换行符*                                          windows操作系统:        /r/n*                                          mac操作系统:            /r*                                          unix / Linux操作系统:     /n*  */publicclassUniqueUse {
publicstaticvoidmain(String[] args) throwsIOException{ //还是直接抛出父类异常IOException//需求: 实现高效字符流的独特用法:System.out.println("给👴好好看注释");
//1.创建(高效)字符输入流对象,关联数据源文件BufferedReaderbufferedReader=newBufferedReader(newFileReader("D:\\JAVA\\IDEA\\file\\a\\高效字符流滴数据源文件.txt"));
//2.创建(高效)字符输出流对象,关联目的地文件BufferedWriterbufferedWriter=newBufferedWriter(newFileWriter("D:\\JAVA\\IDEA\\file\\a\\高效字符流滴目的地文件.txt"));
//3.定义变量,记录读取到的内容Stringlen;
//4.循环读取,只要条件满足就一直读取,并将读到的数据赋值给变量while ((len=bufferedReader.readLine()) !=null)
        {
//5.将读取到的数据写入到 目的地文件中bufferedWriter.write(len);
bufferedWriter.newLine();
//千万别忘记换行/*Δ注意:若不写bufferedWriter.newLine();文件中的内容同样可以拷贝成功,但是,全部在一行。所以newLine() 这行代码是个容易忽略但不可忽略的小细节*/        }
//6.释放资源  (最好提前写上,以防粗心忘记)bufferedReader.close();
bufferedWriter.close();
    }
}
/** 特别注意(重要) :*      ①字符流只能拷贝纯文本文件!*      ②拷贝文件内容时 ,并不会考虑目的地文件中的内容,*      而是直接根据数据源文件中的内容进行重新覆盖*      (这个我们之前其实说过了,再强调一下是怕大家忘了)*//** 还有一个小细节:*    如果数据源文件中最后无换行,目的地文件拷贝后会因为newLine()加一个换行*    但如果数据源文件最后有换行,由于循环体中最后还加了一个换行,所以拷贝后目的地文件就与数据源文件一致了* */

image.gif

               来看一下运行效果:                                

image.png 

可以看到我们目的地文件中的《登幽州台歌》 已经被换成了《春江花月夜》,陈子昂大喜(bushi)。

四、字节流读写文件:

       1.前言:

               由于字符流再怎么牛逼也只能拷贝文本文件,因此我们想拷贝非纯文本文件时,就得需要用到字节流。记住,IO流拷贝文件核心六部曲是根本,万变不离其宗,所以你应该能猜到我想说什么了。字节流和字符流在用法上基本大同小异,因此,字符流那块儿你整明白儿了,这里就压根儿不是个事儿。

               拷贝纯文本文件使用字符流,拷贝其他(视频,图片,音频等)文件 使用字节流。

       2.普通字节流用法:

               ①一次读写一个字节数组:            

              步骤:

               仍是IO流拷贝核心六部曲但字节流。

               代码演示:

               我们试着利用普通字节流去拷贝一份图片。我们先随便找一张图片,然后把它放在指定目录,up仍是放在了D:/JAVA/IDEA/file/a文件夹下,如图:

image.png

               然后是up随便找的一张普普通通的图片,因为教学演示嘛,朴实无华才更实用,如图:

image.png

               好的,我们试试能不能用字节流在该目录下拷贝一份相同的“我是拷贝滴.png”图片。在bytecurrent包下创建OrdinaryByteCurrent类作为演示类,如图:

image.png

              OrdianryByteCurrent类的代码如下:

packageknowledge.iocurrent.bytecurrent;
importjava.io.IOException;
importjava.io.InputStream;
importjava.io.OutputStream;
importjava.io.FileInputStream;
importjava.io.FileOutputStream;
/*IO流拷贝文件核心六步曲:1.创建字节输入流对象,关联数据源文件对象2.创建字节输出流对象,关联目的地文件对象3.定义变量,记录读取到的内容4.循环读取,只要条件满足就一直读,并将读取到的内容赋值给变量5.将读取到的数据写入到  目的地文件中6.释放资源。*//*** 字节流的用法:*      FileInputStream: 普通字节输入流,用来读取数据的*          成员方法:*              public int read(byte[] b) :*                  一次读取一个字节数组,将读取到的内容存入到字节数组中*                  并返回读取到的有效字节数,读不到返回-1**      FileOutputStream: 普通字节输出流,用来写出数据的*          成员方法:*              public void write(byte[] b,int index, int len) :*                  一次写入一个指定的字节数组,需要传入数组名,起始索引,有效长度*/publicclassOrdinaryByteCurrent {
publicstaticvoidmain(String[] args) throwsIOException {
//需求: 学会使用普通字节流的的读写方法,试着拷贝一份图片吧。//1.创建字节输入流对象,关联数据源文件//记得传入正确的路径!InputStreaminputStream=newFileInputStream("D:/JAVA/IDEA/file/a/1.png");
//2.创建字节输出流对象,关联目的地文件OutputStreamoutputStream=newFileOutputStream("D:/JAVA/IDEA/file/a/我是拷贝滴.png");
//3.定义变量,记录读取到的内容byte[] b=newbyte[1024];    //建议定义的数组长度为1024的整数倍intlen;
//4.循环读取,只要条件满足就一直读,并将读取到的内容赋值给变量while ((len=inputStream.read(b)) !=-1)
/*细节:这里如果一不小心写成了read()后果: read 了个寂寞*/        {
//5.将读取到的数据写入到 目的地文件中outputStream.write(b, 0, len);
        }
//6.释放资源(建议直接写到最后,以防忘记释放)inputStream.close();
outputStream.close();
    }
}

image.gif

               看一下代码的运行效果:

image.png

成功拷贝过来了,甚至连右边的大小都一模一样,牛不牛逼?我们在点开“我是拷贝滴.png” 看看情况如何:

image.png

               不能说大体相似,只能说是一模一样!

       3.高效字节流用法:

               ①前言

              高效字节流的用法与高效字符流的用法一致。

               即高效字节流和普通字节流差异的地方在于:

               高效字节流在创建字节输入流对象时,不再是直接传入数据源文件的路径,而是传入一个 已经关联了数据源文件路径的 普通字节输入流对象。在创建高效字节输出流时也是同理。这里我们还是像之前高效字符流一样,先拿代码段给大家示范一下:

//声明:一下代码只是暂且作为片段给大家举个栗子,并不是完整代码
//1.创建普通字节流读文件对象,关联数据源文件。
    InputStream inputStream = new FileInputStream("Test2/1.jpg");
//2.创建高效字节流读文件对象。
    BufferedInputStream bufferedInputStream  = new BufferedOutputStream(inputStream);
//3.当然了,实际开发中,我们往往将1.2.步合并,也就是之前说到的所谓链式编程了
    BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("Test2/2.jpg"));

image.gif

               ②write重载方法:

               还记得刚刚我们的普通字节流是怎么拷贝的来不?我们是以一次读写一个字节数组来拷贝的,其实write类的重载方法很多,up截了个图给小伙伴儿们看看:

image.png

                仔细看,普通字节流那块儿我们用到不就是中间的重载方法吗?那么字节缓冲流演示里,我们就换换口味,这次我们选用write(int b) 这个重载方法,该方法本质是一次写入一个字节

               代码演示:

               老规矩,我们还是先随便找个要拷贝的图片,放在既定的文件目录下,如图:

image.png

               up也是随便找了一张普普通通的图片,毕竟是做演示,还是效率和实用更重要!如图:

image.png

好的,我们试试能不能用字节流在该目录下拷贝一份相同的“我是拷贝滴2.jpg”图片。在bytecurrent包下创建EfficientByteCurrent类作为演示类,如图:                                

image.png

               EffeciveByteCurrent类的代码如下:                

packageknowledge.iocurrent.bytecurrent;
importjava.io.BufferedInputStream;
importjava.io.BufferedOutputStream;
importjava.io.FileInputStream;
importjava.io.FileOutputStream;
importjava.io.IOException;
//*// * IO流拷贝文件核心六步曲// *         1.创建字符(节)输入流对象,关联数据源文件对象// *         2.创建字符(节)输出流对象,关联目的地文件对象// *         3.定义变量,记录读取到的内容// *         4.循环读取,只要条件满足就一直读,并将读取到的内容赋值给变量// *         5.将读取到的数据写入到  目的地文件中// *         6.释放资源。(怕忘记可提前写,同时在这之前记得进行异常处理)/** 特点:*      字节缓冲流有自己的缓冲区,大小为8192个字节(注意是字节噢,不是字符),也就是8kb*/publicclassEffectiveByteCurrent {
publicstaticvoidmain(String[] args) throwsIOException{
//1.创建高效字节输入流对象,关联数据源文件(链式编程)BufferedInputStreambufferedInputStream=newBufferedInputStream(newFileInputStream("D:\\JAVA\\IDEA\\file\\a\\2.jpg"));
//2.创建高效字节输出流对象,关联目的地文件(链式编程)BufferedOutputStreambufferedOutputStream=newBufferedOutputStream(newFileOutputStream("D:/JAVA/IDEA/file/a/我是拷贝滴2.jpg"));
//3.定义变量,记录读取到的内容。intdata;
//4.循环读取,只要条件满足就一直读,并将读到的内容赋值给变量。while ((data=bufferedInputStream.read()) !=-1)
        {
//5.将读取到的数据写入到 目的地文件中bufferedOutputStream.write(data);
        }
/*write()有很多重载方法,但是这里我们把重载方法选为了write(int len),即一次写入一个字节*///6.关闭资源 (建议提前写,小心使得万年船)bufferedInputStream.close();
bufferedOutputStream.close();
    }
}
/*** Summary(总结)*      拷贝纯文本文件使用字符流,拷贝其他(视频,图片,音频等)文件  使用字节流。*/

image.gif

               看一下代码的执行效果:

image.png

               牛逼,又成了。我们再点开“我是拷贝滴2.jpg”看看情况:

image.png

               艹(双语) ,只能说完全一致。🐂

               🆗,普通字节流和高效字节流用法我们就讲到这里,更多精彩欢迎订阅up。

五、IO流模拟上传头像系统:

               GG,🕊🕊🕊。写到这已经两万多字了,就算你牛逼,你头铁你看到这里还意犹未尽,up也已经“油尽灯枯”,写不动了(bushi)。好吧,由于模拟上传头像的代码较长,而且有一定的逻辑性,因此up准备单独发一篇博文详解,将放在java进阶专栏。现在是10月22日,我会在三天内上传详解IO流模拟上传头像系统的博文,到时候把链接给小伙伴儿们放在这里,大家敬请期待。

2022.10.24已更新:点击查看java IO流进阶 模拟上传头像系统

六、完结撒❀ + 给自己打广告:

               恭喜你,你已经学会了如何上手javaIO流了。全文共2万余字,代码都是up手码的,觉得写得不错就帮up点个赞吧。如果有兴趣学习java反射,up之前写过一篇0基础万字详解java反射的博文,链接放下面了,有兴趣的小伙伴儿们可以看看。

0基础java反射万字详解链接 : 0基础java反射万字详解

System.out.println("END-------------------------------------------------------------------------");

目录
相关文章
|
30天前
|
Java
Java“解析时到达文件末尾”解决
在Java编程中,“解析时到达文件末尾”通常指在读取或处理文件时提前遇到了文件结尾,导致程序无法继续读取所需数据。解决方法包括:确保文件路径正确,检查文件是否完整,使用正确的文件读取模式(如文本或二进制),以及确保读取位置正确。合理设置缓冲区大小和循环条件也能避免此类问题。
|
4天前
|
消息中间件 缓存 Java
java nio,netty,kafka 中经常提到“零拷贝”到底是什么?
零拷贝技术 Zero-Copy 是指计算机执行操作时,可以直接从源(如文件或网络套接字)将数据传输到目标缓冲区, 而不需要 CPU 先将数据从某处内存复制到另一个特定区域,从而减少上下文切换以及 CPU 的拷贝时间。
java nio,netty,kafka 中经常提到“零拷贝”到底是什么?
|
8天前
|
存储 安全 Java
如何保证 Java 类文件的安全性?
Java类文件的安全性可以通过多种方式保障,如使用数字签名验证类文件的完整性和来源,利用安全管理器和安全策略限制类文件的权限,以及通过加密技术保护类文件在传输过程中的安全。
|
28天前
|
算法 Java Linux
java制作海报二:java使用Graphics2D 在图片上合成另一个照片,并将照片切割成头像,头像切割成圆形方法详解
这篇文章介绍了如何使用Java的Graphics2D类在图片上合成另一个照片,并将照片切割成圆形头像的方法。
45 1
java制作海报二:java使用Graphics2D 在图片上合成另一个照片,并将照片切割成头像,头像切割成圆形方法详解
|
10天前
|
存储 Java API
Java实现导出多个excel表打包到zip文件中,供客户端另存为窗口下载
Java实现导出多个excel表打包到zip文件中,供客户端另存为窗口下载
22 4
|
12天前
|
Java 数据格式 索引
使用 Java 字节码工具检查类文件完整性的原理是什么
Java字节码工具通过解析和分析类文件的字节码,检查其结构和内容是否符合Java虚拟机规范,确保类文件的完整性和合法性,防止恶意代码或损坏的类文件影响程序运行。
|
12天前
|
Java API Maven
如何使用 Java 字节码工具检查类文件的完整性
本文介绍如何利用Java字节码工具来检测类文件的完整性和有效性,确保类文件未被篡改或损坏,适用于开发和维护阶段的代码质量控制。
|
1月前
|
安全 NoSQL Java
一文搞懂网络通信的基石✅IO模型与零拷贝
【10月更文挑战第1天】本文深入探讨了网络通信中的IO模型及其优化方法——零拷贝技术。首先介绍了IO模型的概念及五种常见类型:同步阻塞、同步非阻塞、多路复用、信号驱动和异步IO模型。文章详细分析了每种模型的特点和适用场景,特别是多路复用和异步IO在高并发场景中的优势。接着介绍了零拷贝技术,通过DMA直接进行数据传输,避免了多次CPU拷贝,进一步提升了效率。最后总结了各种模型的优缺点,并提供了相关的代码示例和资源链接。
一文搞懂网络通信的基石✅IO模型与零拷贝
|
22天前
|
Java
Java开发如何实现文件的移动,但是在移动结束后才进行读取?
【10月更文挑战第13天】Java开发如何实现文件的移动,但是在移动结束后才进行读取?
40 2
|
22天前
|
Java Apache Maven
Java将word文档转换成pdf文件的方法?
【10月更文挑战第13天】Java将word文档转换成pdf文件的方法?
105 1