|
IO流简介IO是什么Java中的IO流是用于处理数据输入和输出的核心机制。通过应用IO流可以使Java程序能够与外部世界(如磁盘文件、网络、硬件设备等)进行数据交互。IO流的全称为输入/输出流(Input/OutputStream),它是Java编程语言中用于数据传输的一种抽象模型。流可以被想象为数据的连续流动,就像水通过管道一样,数据通过流从一个地方流向另一个地方。应用场景IO流在Java开发中几乎无处不在,任何涉及到数据读写的地方都会用到IO流。常见的应用场景包括文件读写、网络通信、数据持久化等IO流的分类IO流的分类可以从多个维度进行理解按流的方向:可以分为输入流InputStream)和输出流(FileOutputStream)按流的功能:可以分为节点流和处理流按数据处理单元:可以分为字节流(以字节读写为基本单位)和字符流(以字符读写为基本单位)流的超类类型在Java中,输入输出(IO)流的超类主要有两类,分别对应于字节流和字符流.字节流(ByteStreams)java.io.InputStream:所有字节输入流的超类。定义了从源读取字节的基本方法java.io.OutputStream:所有字节输出流的超类。定义了向目的地写入字节的基本方法字符流(CharacterStreams)java.io.Reader:字符输入流的超类,定义了从源读取字符的基本方法java.io.Writer:字符输出流的超类,定义了向目的地写入字符的基本方法这些超类提供了基本的读写操作,而它们的子类则实现了特定的读写功能,例如从文件读取、向网络套接字写入、数据的缓冲等。例如:字节流的具体实现包括:FileInputStream和FileOutputStream:用于读写文件。BufferedInputStream和BufferedOutputStream:提供缓冲,从而提高读写效率。ObjectInputStream和ObjectOutputStream:用于对象的序列化和反序列化。…字符流的具体实现包括:FileReader和FileWriter:用于读写文本文件。BufferedReader和BufferedWriter、PrintWriter:提供字符缓冲,提高读写效率。InputStreamReader和OutputStreamWriter:用于在字节流和字符流之间转换。…这些类构成了JavaIO流的层次结构,允许开发者根据不同的需求选择合适的流类型来进行数据的读写操作。字节文件流应用简介文件流是用来连接我们的程序与文件之间的"管道",用来读写文件中的数据。核心API文件流是继承自InputStream和OutputStream的流对象,其分类为:文件输入流java.io.FileInputStream:读取文件数据的流文件输出流java.io.FileOutputStream:写入文件数据的流文件输出流应用java.io.FileOutputStream输出流对象用于向文件中写入数据,对象构建通常会借助如下两个构造方法:FileOutputStream(Stringpath)创建文件输出流对指定的path路径表示的文件进行写操作,如果该文件不存在则将其创建出来FileOutputStream(Filefile)创建文件输出流对指定的file对象表示的文件进行写操作,如果该文件不存在则将其创建出来案例packageio;importjava.io.File;importjava.io.FileNotFoundException;importjava.io.FileOutputStream;importjava.io.IOException;//API(工具-用于解决什么问题,怎么解决问题)publicclassFOSDemo01{publicstaticvoidmain(String[]args)throwsIOException{//1.构建一个文件输出流对象//1)创建文件对象Filefile=newFile("jsd/2406/fos.dat");//jsd/2406/是目录//2)获取文件对象的目录结构Fileparent=file.getParentFile();//jsd/2406/System.out.println(parent);//3).假如目录不存在则创建目录mkdirs();if(!parent.exists()){//parent.exists()假如返回true表示存在parent.mkdirs();//创建多层目录System.out.println("文件不存在,创建成功");}//4)创建文件输出流对象(用于向文件写数据-二进制)//构建对象方法1//FileOutputStreamfos1=newFileOutputStream("jsd/2406/fos.dat");//构建对象方法2FileOutputStreamfos2=newFileOutputStream(file);//5)向文件中写入数据fos2.write(3);//这里的3表示10进制数据,3的二进制数据为00000011//00011(10进制)//00102//00113//01004//01015fos2.write(4);fos2.write(5);System.out.println("数据写入OK");//6)释放资源(关闭流对象)fos2.close();}}12345678910111213141516171819202122232425262728293031323334353637383940文件输入流应用java.io.FileInputStream文件输入流对象用于从文件中读取数据,常用构造方法有:FileInputStream(Stringpath)基于给定的路径对应的文件创建文件输入流FileInputStream(Filefile)基于给定的File对象所表示的文件创建文件输入流案例packageio;importjava.io.FileInputStream;importjava.io.FileNotFoundException;importjava.io.IOException;/***自己实践:*构建文件输入流FileInputStream对象,并基于此对象*从jsd/2406/fos.dat文件中读数据到程序中并输出。*/publicclassFISDemo01{publicstaticvoidmain(String[]args)throwsIOException{//1.构建文件输入流对象FileInputStreamfis=newFileInputStream("jsd/2406/fos.dat");//2.读取数据//inta=fis.read();//读取一个字节//intb=fis.read();//intc=fis.read();//intd=fis.read();//System.out.println("a="+a+";b="+b+";c="+c+";d="+d);intn=0;while((n=fis.read())!=-1){System.out.println(n);}//3.关闭流对象(水龙头有打开是不是也会有关闭,否则浪费资源)fis.close();//流对象关闭后会释放内存}}123456789101112131415161718192021222324252627282930文件的复制实践复制文件的原理就是使用文件输入流从原文件中陆续读取出每一个字节,然后再使用文件输出流将字节陆续写入到另一个文件中完成的。案例1packageio;importjava.io.File;importjava.io.FileInputStream;importjava.io.FileOutputStream;importjava.io.IOException;/***实现文件复制*将当前目录中的a.png文件复制一份出来生成一个b.png文件*/publicclassFileCopyDemo01{publicstaticvoidmain(String[]args)throwsIOException{//一、实现思路//1.读文件内容(a.png)//2.将读取的内容写到b.png中//二、代码实现//1.构建文件输入流、输出流对象FileInputStreamfis=newFileInputStream("a.png");//这个文件需要存在FileOutputStreamfos=newFileOutputStream("b.png");//这个文件不存在会自动创建//2.读写数据(复制)intn=-1;while((n=fis.read())!=-1){//读取数据,n为读到的数据,-1表示读取到文件尾fos.write(n);//将读取的数据写入到b.png文件中}//3.关闭流对象fis.close();fos.close();}}12345678910111213141516171819202122232425262728293031323334块读写操作实践块读:一次性读取一组字节的方式InputStream中定义了块读的方法intread(byte[]data)一次性读取给定字节数组总长度的字节量并存入到该数组中。返回值为实际读取到的字节数。如果返回值为-1表示本次没有读取到任何字节已经是流的末尾了块写:一次性写出一组字节的方式OutputStream中定义了块写的方法voidwrite(byte[]data)一次性将给定数组中所有字节写出voidwrite(byte[]data,intoffset,intlen)一次性将data数组中从下标offset处开始的连续len个字节一次性写出案例实现:文件复制packageio;importjava.io.FileInputStream;importjava.io.FileOutputStream;importjava.io.IOException;/***实现文件复制*将当前目录中的a.png文件复制一份出来生成一个b.png文件*/publicclassFileCopyDemo02{publicstaticvoidmain(String[]args)throwsIOException{//一、实现思路//1.读文件内容(a.png)//2.将读取的内容写到b.png中//二、代码实现//1.构建文件输入流、输出流对象FileInputStreamfis=newFileInputStream("a.png");//这个文件需要存在FileOutputStreamfos=newFileOutputStream("b.png");//这个文件不存在会自动创建//2.读写数据(复制)//2.1定义数组用于临时存储读取到数据byte[]data=newbyte[1024];//这里数组的大小是自定义//2.2循环读取数据intlength=-1;while((length=fis.read(data))!=-1){//这里数组大小是1024,所以最多一次读取1024个字节,length表示读取的字节数fos.write(data,0,length);//读了多少写多少,0表示起始位置,length表示写入的字节数}//3.关闭流对象fis.close();fos.close();}}12345678910111213141516171819202122232425262728293031323334文本数据操作对于FileInputStream和FileOutputStream提供的方法只能读写字节数据,对于文本数据如何操作呢?案例1:写文本数据packageio;importjava.io.File;importjava.io.FileOutputStream;importjava.io.IOException;importjava.nio.charset.StandardCharsets;/***文本数据的写操作实现*/publicclassWriteStringDemo01{publicstaticvoidmain(String[]args)throwsIOException{Stringstr="我爱Java";//构建文件输出流对象FileOutputStreamfos=newFileOutputStream("./f1.txt");//写字符数据byte[]data=str.getBytes(StandardCharsets.UTF_8);fos.write(data);str="HelloTedu";fos.write(str.getBytes(StandardCharsets.UTF_8));//释放资源fos.close();}}123456789101112131415161718192021222324案例2:读文本数据packageio;importjava.io.File;importjava.io.FileInputStream;importjava.io.IOException;publicclassReadStringDemo01{publicstaticvoidmain(String[]args)throwsIOException{//1.构建文件输入流对象//方式1://Filefile=newFile("./f1.txt");//longsize=file.length();//FileInputStreamfis=newFileInputStream(file);//方式2:FileInputStreamfis=newFileInputStream("./f1.txt");//2.读取文件内容(将数据读取到字节数组中)//byte[]data=newbyte[(int)size];byte[]data=newbyte[fis.available()];//fis.available()获取流中有效字节数intlen=fis.read(data);//3.将字节数组内容转换为字符串并输出Stringstr=newString(data,0,len);System.out.println(str);//4.关闭流fis.close();}}1234567891011121314151617181920212223242526字节缓冲流应用处理流概述处理流是JavaIO流体系中的一类重要的流,它们是在已经存在的流(称为基础流或节点流)之上构建的,为这些流添加额外的功能,而不改变原流本身。处理流的主要目的是为了增强或改变流的行为,比如提供缓冲、转换数据类型、序列化等等。应用特征处理流的典型特征是它们自身并不直接连接到物理的输入/输出设备,而是“装饰”在其他流之上,利用这些流进行数据的读写,并在此基础上提供附加服务。处理流的实例通常会把读写操作委托给底层的流,同时可能对数据进行一些预处理或后处理。处理流可以串联使用,即一个处理流的输出可以作为另一个处理流的输入,形成流的链式结构。例如,可以先使用BufferedInputStream对FileInputStream进行包装,然后再用其它处理流包装这个缓冲流。字节缓冲流Java中的缓冲流是一种处理流,有java.io.BufferedInputStream和BufferedOutputStream其作用就是加快读写效率,通常缓冲流的应用最终要链接在低级流上。缓冲字节输出流BufferedOutputStream(OutputStreamout)实例化一个缓冲字节输出流并链接在指定的字节输出流上。默认缓冲区大小8kb(内部维护的byte[]buf数组长度8192)BufferedOutputStream(OutputStreamout,intsize)实例化一个指定缓冲区大小的缓冲字节输出流并链接在指定的字节输出流上。缓冲字节输入流BufferedInputStream(InputStreamin)实例化一个缓冲字节输入流并链接在指定的字节输入流上。默认缓冲区大小8kb(内部维护的byte[]buf数组长度8192)BufferedInputStream(InputStreamin,intsize)实例化一个指定缓冲区大小的缓冲字节输入流并链接在指定的字节输入流上。应用案例分析packageio;importjava.io.*;/***基于缓冲流实现文件复制*/publicclassFileCopyDemo03{publicstaticvoidmain(String[]args)throwsIOException{//1.构建输入输出流对象(缓冲流增强文件流)BufferedInputStreambis=newBufferedInputStream(//处理流(这个流对象内置一个缓冲区-byte[])newFileInputStream("./a.png"));//节点流BufferedOutputStreambos=newBufferedOutputStream(//处理流newFileOutputStream("./c.png"));//节点流//2.读写数据(拷贝)byte[]data=newbyte[16];intlen;while((len=bis.read(data))!=-1){bos.write(data,0,len);}bos.flush();//这里表示刷新缓冲区内容到文件//3.关闭流对象(关闭外层流时,内层流会自动关闭)bis.close();bos.close();}}12345678910111213141516171819202122232425262728对象流应用实践简介Java中的对象流也是一种处理流,有java.io.ObjectInputStream和java.io.ObjectOutputStream两个类型,用于实现对象的读写。也就是对象的序列化(把对象转化为字节)和反序列化(把字节转换为对象)。ObjectOutputStream:用于将Java对象序列化为字节流,以便可以将对象写入文件、网络或其他任何形式的持久存储中。ObjectInputStream:用于从字节流中反序列化Java对象,即将字节流重新转换为Java对象。Serializable接口为了能够被序列化,一个对象所属的类必须实现Serializable接口。Serializable是一个标记接口,不包含任何方法,它的存在仅仅是为了标识一个类是可序列化的。如果尝试序列化一个没有实现Serializable接口的类的对象,将会抛出NotSerializableException异常。应用案例分析设计一个Message对象类型packageio;importjava.io.Serializable;/***消息对象*/publicclassMessageimplementsSerializable{//Serializable只起到一个标识性作用//添加序列化id(序列化时类中没有写序列化id,系统也会基于类中的属性和方法自动生成)//privatestaticfinallongserialVersionUID=1L;//Idea自动生成序列化ID如何进行配置?可以在大模型中去搜索privatestaticfinallongserialVersionUID=8725255648785219540L;/*消息id*/privateIntegerid;/**消息,*假如这个属性不希望系列化,*可以使用transient关键字修饰*/privatetransientStringtitle;/**消息内容*/privateStringcontent;//privateIntegeruserId;//.....publicMessage(){}publicMessage(Integerid,Stringtitle,Stringcontent){this.id=id;this.title=title;this.content=content;}publicIntegergetId(){returnid;}publicvoidsetId(Integerid){this.id=id;}publicStringgetTitle(){returntitle;}publicvoidsetTitle(Stringtitle){this.title=title;}publicStringgetContent(){returncontent;}publicvoidsetContent(Stringcontent){this.content=content;}//alt+insert@OverridepublicStringtoString(){return"Message{"+"id="+id+",title='"+title+'\''+",content='"+content+'\''+'}';}}12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364对象序列化案例实现packageio;importjava.io.BufferedOutputStream;importjava.io.FileOutputStream;importjava.io.IOException;importjava.io.ObjectOutputStream;/***对象流应用*/publicclassObjectOutputStreamDemo01{publicstaticvoidmain(String[]args)throwsIOException{Messagem1=newMessage(1,"传奇老师病了","做了个小手术");//1.构建流对象ObjectOutputStreamoos=newObjectOutputStream(newFileOutputStream("message.txt"));//2.写对象(序列化)oos.writeObject(m1);System.out.println("序列化OK");//3.关闭流对象oos.close();}}123456789101112131415161718192021222324对象反序列化案例实现packageio;importjava.io.FileInputStream;importjava.io.IOException;importjava.io.ObjectInputStream;/***将message.txt文件中的内容进行反序列化*/publicclassObjectInputStreamDemo02{publicstaticvoidmain(String[]args)throwsIOException,ClassNotFoundException{//1.创建流对象ObjectInputStreamois=newObjectInputStream(newFileInputStream("message.txt"));//2.读取对象(反序列化-先读出来的是字节,然后将字节转换对象)Messagemsg=(Message)ois.readObject();System.out.println(msg);//3.关闭资源ois.close();}}1234567891011121314151617181920字符转换流应用字符流在Java中,字符流(CharacterStreams)是用于处理文本数据的一种流类型,其基类是java.io.Reader和java.io.Writer两个抽象类。应用场景?字符流广泛应用于读写文本文件,处理字符串,以及在网络通信中传输文本数据。由于文本文件通常包含人类可读的内容,字符流可以确保正确处理各种字符集和编码,从而避免乱码问题。为什么使用字符流?编码透明性:字符流允许你指定字符编码,因此你可以读写使用不同编码的文本文件,而不需要了解具体的编码细节。字符边界处理:当处理多字节编码(如UTF-8)的字符时,字符流能确保每次读写的都是一个完整的字符,避免字节流中可能出现的字符截断问题(这里其实是乱码)字符流超类java.io.Writer所有字符输入流的超类常用方法voidwrite(intc):写出一个字符,写出给定int值”低16”位表示的字符。voidwrite(char[]chs):将给定字符数组中所有字符写出。voidwrite(Stringstr):将给定的字符串写出voidwrite(char[]chs,intoffset,intlen):将给定的字符数组中从offset处开始连续的len个字符写出java.io.Reader所有字符输出流的超类常用方法intread():读取一个字符,返回的int值“低16”位有效。当返回值为-1时表达流读取到了末尾。intread(char[]chs):从该流中读取一个字符数组的length个字符并存入该数组,返回值为实际读取到的字符量。当返回值为-1时表达流读取到了字符转换流应用在Java中,字符转换流是JavaI/O体系中的一类流,它们实现了字节流和字符流之间的转换。这类流包括InputStreamReader和OutputStreamWriter两个核心类。*InputStreamReader是一个读取字节并使用指定的字符集将其解码为字符的Reader;OutputStreamWriter则是一个接收字符并使用指定的字符集将其编码为字节的Writer。应用场景当你需要从字节流中读取文本数据,并且想要控制使用的字符编码时。当你需要将字符数据写入到字节流中,并指定字符编码时。在网络通信中,当你发送或接收的数据是以字节形式存在,但你希望以字符形式处理时。为什么用它?编码兼容性:不同的系统和文件可能使用不同的字符编码,字符转换流可以让你指定编码,从而正确解析或生成文本。国际化支持:为了支持多种语言和字符集,字符转换流提供了灵活的编码选择,这对于开发国际化应用非常重要。数据完整性:在处理多字节编码的字符时,字节流可能会导致字符被错误地分割,而字符转换流保证了字符的完整性和正确性。应用案例分析和实践OutputStreamWriter应用案例(字符输出转化流应用)两个构造方法:OutputStreamWriter(OutputStreamout,Charsetcs)基于给定的字节输出流以及字符编码创建OSWOutputStreamWriter(OutputStreamout)该构造方法会根据系统默认字符集创建OSW具体应用:通过字符转换流将一些字符串写入到指定文件packageio;importjava.io.FileNotFoundException;importjava.io.FileOutputStream;importjava.io.IOException;importjava.io.OutputStreamWriter;importjava.nio.charset.StandardCharsets;/***通过字符转换流将一些字符串写入到指定文件*/publicclassOutputStreamWriterDemo01{publicstaticvoidmain(String[]args)throwsIOException{//1.构建字符转换输出流对象OutputStreamWriterosw=newOutputStreamWriter(newFileOutputStream("./osw.txt"),StandardCharsets.UTF_8);//2.写数据(字符串)osw.write("你好");//这里不会自动换行osw.write("子千老师");System.out.println("数据写出完毕");//3.关闭流对象osw.close();}}123456789101112131415161718192021222324252627IntputStreamReader应用案例(字符输入转化流应用)构造方法:InputStreamWriter(InputStreamin,Charsetcs)基于给定的字节输入流以及字符编码创建当前转换流InputStreamWriter(InputStreamin)该构造方法会根据系统默认字符集创建当前转换流具体应用案例:基于字符转换流从文件读取字符数据packageio;importjava.io.FileInputStream;importjava.io.FileNotFoundException;importjava.io.IOException;importjava.io.InputStreamReader;importjava.nio.charset.StandardCharsets;/***基于字符转换流从文件读取字符数据*/publicclassInputStreamReaderDemo01{publicstaticvoidmain(String[]args)throwsIOException{//1.创建字符输入转换流对象InputStreamReaderisr=newInputStreamReader(newFileInputStream("./osw.txt"),StandardCharsets.UTF_8);//2.读数据intdata=0;while((data=isr.read())!=-1){System.out.print((char)data);}//3.关闭流对象isr.close();}}1234567891011121314151617181920212223242526字符缓冲流应用简介在Java中,字符缓冲流是用于提高读写性能的一对流,它们包括BufferedReader和BufferedWriter。这些流通过内部缓存机制减少了对底层I/O设备的访问频率,从而提高了读写操作的效率。在字符输出缓冲流应用时,通常会结合PrintWriter一起使用。这个对象可以一次写一行,并且可以自带刷新机制。快速入门实现案例1:PrintWriter不同构造方法应用packageio;importjava.io.*;/***打印流应用*/publicclassPrintWriterDemo01{publicstaticvoidmain(String[]args)throwsFileNotFoundException{//1.构建PrintWriter对象//方式1:需要手动刷新缓冲区或者关闭流PrintWriterpw=newPrintWriter("./pw.txt");//方式2:自动刷新,构造方法中的true表示自动刷新//PrintWriterpw=newPrintWriter(//newFileOutputStream("./pw.txt"),true);//2.写入数据pw.println("hello");pw.println("world");pw.println("Java");//3.关闭流对象pw.close();}}1234567891011121314151617181920212223案例2:自己指定缓冲流packageio;importjava.io.*;publicclassPrintWriterDemo02{publicstaticvoidmain(String[]args)throwsFileNotFoundException{//1.构建打印流对象(装饰模式)PrintWriterprintWriter=newPrintWriter(newBufferedWriter(newOutputStreamWriter(newFileOutputStream("./pw.txt",true))),true);//2.写数据printWriter.println("hello");printWriter.println("Java");//3.关闭流对象printWriter.close();}}123456789101112131415161718案例3:字符输入缓冲流应用packageio;importjava.io.*;importjava.nio.charset.StandardCharsets;/***编写一个程序,能从一个文件中读取数据,一次读取一行,并将读取的内容进行输出*/publicclassBufferedReaderDemo01{publicstaticvoidmain(String[]args)throwsIOException{//1.构建BufferedReader对象BufferedReaderbr=newBufferedReader(newInputStreamReader(newFileInputStream("./src/main/java/io/FISDemo01.java"),StandardCharsets.UTF_8));//2.循环读取文件中数据,读一行,输出一行Stringline=null;while((line=br.readLine())!=null){//readLine用于读取一行System.out.println(line);}//3.关闭流对象br.close();}}123456789101112131415161718192021222324
|
|