javaee论坛

普通会员

225648

帖子

334

回复

348

积分

楼主
发表于 2019-11-18 08:54:01 | 查看: 1376 | 回复: 0

当输出流的目的,和输入流的源是内存时,这样的流称之为内存流。(就是将数据写入RAM)

2.2内存流的构造方法ByteArrayInputStream(bytebuf[]);创建一个ByteArrayInputStream并把指定该输入流的数据源buf[]。ByteArrayOutputStream();创建一个ByteArrayOutputStream并把分配一个32字节(默认大小)的缓冲区。ByteArrayOutputStream(intsize);创建一个ByteArrayOutputStream并分配自定size字节的缓冲区。2.3读取内存数据和写入到内存数据2.3.1读取内存数据try{StringtestContent="ABCDEFG";//程序运行的时候这数据本身就在内存,ByteArrayInputStreambais=newByteArrayInputStream(testContent.getBytes());//创建内存输入流,指定要读取的数据byte[]intread;while((read=bais.read())!=-1){//和普通流读取字节是一样的(也可以嵌套管道)System.out.println((char)read);}bais.close();//关闭流,释放内存资源}...2.3.2写入数据到内存(主要)try{StringtestContent="ABCDEFG";ByteArrayOutputStreambaos=newByteArrayOutputStream();//创建内存输出流,把数据写入到内存中baos.write(testContent.getBytes());//和普通的输出流写输入一样,(也可以嵌套管道)baos.flush();baos.close();}...2.4ByteArrayOutputStream常用方法:toByteArray(),toString()toByteArray()方法;是将ByteArrayOutputStream对象所写入到内存的数据转换成byte[]返回。toString()方法;是将ByteArrayOutputStream对象所写入到内存的数据转换成String返回。

提示:内存流除了ByteArrayInputStream与ByteArrayOutputStream主要处理字节数据之外,对应的还有:

CharArrayReader与CharArrayWriter主要处理字符数组。StringReader与StringWriter主要处理字符串。

使用方式大同小异。

3.打印流(了解)

在整个IO包中,打印流是输出信息最方便的类,主要包括字节打印流(PrintStream)和字符打印流(PrintWriter)。打印流提供了非常方便的打印功能,可以打印任何的数据类型。如:小数、整数、字符串等。

PrintStream和PrintWriter都属于输出流,分别针对输出字节和字符。

PrintStream和PrintWriter提供了重载的print()、println()方法用于多种数据类型的输出。

PrintStream和PrintWriter不会抛出异常,用户通过检测错误状态获取错误信息。

PrintStream和PrintWriter有自动flush功能。

3.1打印流构造方法PrintStream字节打印流PrintStream(OutputStreamout);获得指定输出流的字节打印流对象。PrintStream(OutputStreamout,booleanauotflush);获得指定输出流的字节打印流对象。autoflush是否自动刷新。PrintStream(OutputStreamout,booleanauotflush,Stringencoding);获得指定输出流的字节打印流对象。autoflush是否自动刷新。encoding指定字符编码。等…PrintWriter字符打印流PrintWriter(OutputStreamout);获得指定输出流的字符打印流对象。PrintWriter(OutputStreamout,booleanautoflush);获得指定输出流的字符打印流对象。autoflush是否自动刷新。PrintWriter(Writerout);获得指定字符输出流的字符打印流对象。PrintWriter(Writerout,booleanautoflush);获得指定字符输出流的字符打印流对象。autoflush是否自动刷新。等…3.2打印流的常用操作:print(),println()

print();不带换行的打印输出。

try{Filefile=newFile("test.txt");FileOutputStreamfos=newFileOutputStream(file);PrintWriterps=newPrintWriter(fos,true);ps.print("天青色等烟雨,");ps.print("而我在等你。");ps.print("炊烟袅袅升起,");ps.print("晕开了结局。");ps.close();}...

效果:

println();每打印出一行数据后,执行换行。

try{Filefile=newFile("test.txt");FileOutputStreamfos=newFileOutputStream(file);PrintWriterps=newPrintWriter(fos,true);ps.println("天青色等烟雨,");ps.println("而我在等你。");ps.println("炊烟袅袅升起,");ps.println("晕开了结局。");ps.close();}...

效果:

4.对象流(了解)4.1对象流

​ObjectInputStreamObjectOutputStream类分别是InputStream和OutputStream的子类,对象输出流使用writeObject(Objectobj)方法,将一个对象obj写入到一个文件,使用readObject()读取一个对象。

用的少,因为数据库用途大

构造方法:

ObjectInputStream(InputStreamin)ObjectOutputStream(OutputStreamout)

代码示例:

将对象写入文件:

//'序列化'的对象写入文件OutputStreamoutputStream=newFileOutputStream(file);ObjectOutputStreamobjectOutputStream=newObjectOutputStream(outputStream);objectOutputStream.writeObject(Objectobj);objectOutputStream.close();

从文件读取对象:

//序列化读取对象InputStreaminputStream=newFileInputStream(file);ObjectInputStreamobjectInputStream=newObjectInputStream(inputStream);Objectobj=objectInputStream.readObject();objectInputStream.close();

注意:当使用对象流写入或者读取对象的时候,必须保证该对象是序列化的,这样是为了保证对象能够正确的写入文件,并能够把对象正确的读回程序。

什么是对象序列化?

4.2对象序列化

​所谓的对象的序列化就是将对象转换成二进制数据流的一种实现手段,通过将对象序列化,可以方便的实现对象的传输及保存。在Java中提供了ObejctInputStream和ObjectOutputStream这两个类用于序列化对象的操作。用于存储和读取对象的输入输出流类,要想实现对象的序列化需要实现Serializable接口,但是Serializable接口中没有定义任何的方法,仅仅被用作一种标记,以被编译器作特殊处理。

packagecom.yztc.main;importjava.io.Serializable;//实现了Serializable接口。序列化publicclassStudentimplementsSerializable{//由编译器自动生成,用来解决不同的版本之间的序列化问题。privatestaticfinallongserialVersionUID=-79485540193100816L;privateintage;privateStringname;publicintgetAge(){returnage;}publicvoidsetAge(intage){this.age=age;}publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicStudent(){super();}publicStudent(intage,Stringname){this.age=age;this.name=name;}}4.3transient一旦变量被transient修饰,变量将不再是对象持久化(写到磁盘里持久保存)的一部分,该变量内容在序列化后无法获得访问。transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。被transient关键字修饰的成员变量不再能被序列化。静态变量不管是否被transient修饰,均不能被序列化。5.RandomAccessFile类

RandomAccessFile类可以说是Java语言中功能最为丰富的文件访问类,它提供了众多的文件访问方法。RandomAccessFile类支持“随机访问”方式,可以跳转到文件的任意位置处读写数据。在要访问一个文件的时候,不想把文件从头读到尾,而是希望像访问一个数据库一样地访问一个文本文件,这时,使用RandomAccessFile类就是最佳选择。

RandomAccessFile对象类有个位置指示器,指向当前读写处的位置,当读写n个字节后,文件指示器将指向这n个字节后的下一个字节处。刚打开文件时,文件指示器指向文件的开头处,可以移动文件指示器到新的位置,随后的读写操作将从新的位置开始。RandomAccessFile在数据等长记录格式文件的随机(相对顺序而言)读取时有很大的优势,但该类仅限于操作文件,不能访问其它的IO设备,如网络、内存映像等。

以读写的方式打开一个文件时,如果文件不存在,程序会自动创建此文件。

有关RandomAccessFile类中的成员方法及使用说明请参阅JDK文档。常见API如下:

方法名描述voidclose();关闭此随机访问文件流并释放与该流关联的所有系统资源。longgetFilePointer();返回此文件中的当前偏移量。longlength();返回此文件的长度。read函数集从文件读voidseek(longpos);设置到此文件开头测量到的文件指针偏移量,在该位置发生下一个读取或写入操作。intskipBytes(intn)尝试跳过输入的n个字节以丢弃跳过的字节。write函数集往文件写setLength(long)设置文件大小(设置临时文件)5.1RandomAccessFile类的构造方法newRandomAccessFile(f,“rw”);//读写方式newRandomAccessFile(f,“r”);//只读方式5.2向文件中记忆写入数据Filefile=newFile("accessFile");RandomAccessFileraf=newRandomAccessFile(file,"rw");//以下向raf文件中写数据raf.writeInt(20);//占4个字节raf.writeDouble(8.236598);//占8个字节raf.writeShort(395);//占2个字节raf.writeUTF("这是一个UTF字符串");//这个长度写在当前字符串指针的前两个字节处,可用readShort()读取raf.writeBoolean(true);//占1个字节raf.writeLong(2325451l);//占8个字节raf.writeUTF("又是一个UTF字符串哈哈");raf.writeFloat(35.5f);//占4个字节raf.writeChar('a');//占2个字节raf.close();22.4.3从文件中读取随机记忆的文件内容Filefile=newFile("accessFile");RandomAccessFileraf=newRandomAccessFile(file,"rw");System.out.println(raf.readInt());//读取Int数据,指针会往后移动4字节System.out.println(raf.readDouble());//读取Double数据,指针会往后移动8字节System.out.println(raf.readUTF());//读取字符串,指针会移到该字符串后raf.skipBytes(3);//跳过3个字节,也就是跳过上面例子的boolen和short值。System.out.println(raf.readLong());//读取long值shortreadShort=raf.readShort();//读取字符串的长度System.out.println("目前指针处的字符串长度为="+readShort);raf.skipBytes(readShort);//跳过该字符串System.out.println(raf.readFloat());//读取float值System.out.println(raf.readChar());//读取char值//longlength=raf.length();//System.out.println("文件的总字节数为:"+length);//longfilePointer=raf.getFilePointer();//当前指针的位置,定位到哪个字节了。//System.out.println("目前字节指针定位在:"+filePointer);//raf.seek(4);//直接定位到第4个字节处。6装饰者模式装饰者和被装饰者拥有共同的抽象基类。装饰者必须持有被装饰者的引用(父类的引用)装饰者可以在被装饰者的行为之前/或之后,加上自己的行为,以达到功能拓展的目的。6.1装饰者模式的定义

​扩展类功能,(继承也能做到)。但是相比继承,装饰者模式是动态地将责任(扩展功能)附加到对象上,比继承更有弹性。

6.2装饰者模式的特点装饰者和被装饰对象有相同的超类型。可以用一个或多个装饰者包装一个对象。因为装饰者和被装饰者具有相同的类型,所以任何需要原始对象的场合,可以用装饰过的对象代替。装饰者可以在所委托被装饰者的行为之前/或之后,加上自己的行为,以达到特定的目的。对象可以在任何时候被装饰,所以可以在运行时动态地、不限量地用你喜欢的装饰者来装饰对象。6.3用装饰者解决问题

  比如开车起步问题:

普通司机(CommonDriver)正常起步。新手司机(NewDriver)起步老是会熄火。老司机(竞技车手)(OldDriver)狂踩油门加速起步。6.4代码

定义被装饰者能被扩展的行为Car.java(汽车接口)

publicinterfaceCar{publicabstractvoidstarting();//起步行为}

被装饰者抽象类Driver.java(司机的抽象类)

publicabstractclassDriverimplementsCar{protectedStringdescription="未知的司机";publicStringgetDescription(){returndescription;}}

被装饰者具体类CommonDriver.java(普通司机)

publicclassCommonDriverextendsDriver{publicCommonDriver(){description="普通司机";}@Overridepublicvoidstarting(){System.out.println("起步中...CommonDriver");}}

装饰者抽象类:OtherDriver.java(非普通司机)

publicabstractclassOtherDriverextendsDriver{protectedDriverdriver;publicOtherDriver(Driverdriver){this.driver=driver;}@Overridepublicvoidstarting(){driver.starting();}}

具体装饰者类一:OldDriver.java

publicclassOldDriverextendsOtherDriver{publicOldDriver(Driverdriver){super(driver);description="老司机";}//老司机扩展的代码privatevoidsuperStarting(){System.out.println("油门踩到底...OldDriver");System.out.println("松离合,放手刹...OldDriver");}@Overridepublicvoidstarting(){superStarting();//在被装饰者代码之前扩展代码super.starting();//被装饰者代码}}

具体装饰者类一:NewDriver.java

publicclassNewDriverextendsOtherDriver{publicNewDriver(Driverdriver){super(driver);description="新手司机";}privatevoidlowStaring(){System.out.println("熄火了...NewDriver");System.out.println("又熄火了...NewDriver");}@Overridepublicvoidstarting(){lowStaring();super.starting();}}

测试:

publicstaticvoidmain(String[]args){CommonDrivercommonDriver=newCommonDriver();System.out.println(commonDriver.getDescription());commonDriver.starting();System.out.println("******************");OldDriveroldDriver=newOldDriver(commonDriver);//对普通司机装饰System.out.println(oldDriver.getDescription());oldDriver.starting();System.out.println("******************");NewDrivernewDriver=newNewDriver(commonDriver);//对普通司机装饰System.out.println(newDriver.getDescription());newDriver.starting();}

结果:(控制台输出)

普通司机起步中...CommonDriver<hr/>老司机油门踩到底...OldDriver松离合,放手刹...OldDriver起步中...CommonDriver<hr/>新手司机熄火了...NewDriver又熄火了...NewDriver起步中...CommonDriver6.5装饰者模式缺点

​会在设计中加入大量的小类,如果过度使用,会让程序变得复杂。

6.6装饰者模式在JDK中的运用

Java当中的IO是运用了装饰者模式的最典型的例子。下面是一个简单的例子,通过BufferedReader对象来装饰InputStreamReader对象:

BufferedReaderinput=newBufferedReader(newInputStreamReader(System.in));//System.in是一个InputStream对象课后练习将D盘的一张图片存入内存中,然后再把内存中的图片数据存入到E盘中。publicstaticvoidcopyPhoto(){Filefile=newFile("1.jpg");Filefile2=newFile("1/1.jpg");try(RandomAccessFileraf=newRandomAccessFile(file,"rw");ByteArrayOutputStreambaos=newByteArrayOutputStream();){byte[]b=newbyte[1024];intread=-1;while((read=raf.read(b))!=-1){baos.write(b,0,read);}System.out.println("写入内存完成");byte[]byteArray=baos.toByteArray();//ByteArrayInputStreambais=newByteArrayInputStream(byteArray);RandomAccessFileraf1=newRandomAccessFile(file2,"rw");raf1.write(byteArray);raf1.close();System.out.println("写入盘中");}catch(FileNotFoundExceptione){e.printStackTrace();}catch(IOExceptione){e.printStackTrace();}}publicstaticvoidmain(String[]args){copyPhoto();}

2.在D盘新建一个十年.txt文件,并把《十年》的歌词存入该文件中。然后编写一个程序,结合学过的IO流知识将文件的内容读入到程序中,并使用打印流将《十年》的歌词打印到控制台!

publicstaticvoidprint(){Filefile=newFile("shinian.txt");try(RandomAccessFileraf=newRandomAccessFile(file,"rw");ByteArrayOutputStreambaos=newByteArrayOutputStream();){byte[]b=newbyte[1024];intread=-1;//PrintWriterpw=newPrintWriter(baos);while((read=raf.read(b))!=-1){baos.write(b,0,read);Stringstring=baos.toString();System.out.println(string);//pw.println(string);}//pw.close();}catch(FileNotFoundExceptione){e.printStackTrace();}catch(IOExceptione){e.printStackTrace();}}publicstaticvoidmain(String[]args){print();}

3.编写一个程序,使用RandomAccessFile将一段文字写入到一个名为text.dat的文件中,然后使用RandomAccessFile对象将写入的文字读出来并打印到屏幕上。

publicstaticvoidreadWrite(){Stringcontent="想你的夜,如果你再看我们一眼";Filefile=newFile("text.dat");if(!file.exists()){try(RandomAccessFileraf=newRandomAccessFile(file,"rw");){raf.write(content.getBytes());//raf.writeUTF(content);System.out.println("写入完毕");}catch(FileNotFoundExceptione){e.printStackTrace();}catch(IOExceptione){e.printStackTrace();}}else{try{RandomAccessFileraf1=newRandomAccessFile(file,"r");intread=-1;byte[]b=newbyte[1024];while((read=raf1.read(b))!=-1){Stringstring=newString(b,0,read);System.out.println(string);}raf1.close();}catch(FileNotFoundExceptione){e.printStackTrace();}catch(IOExceptione){e.printStackTrace();}}}publicstaticvoidmain(String[]args){readWrite();}

4.把一个mp3文件截取为3个文件。

/*publicstaticvoidmain(String[]args){Filefrom=newFile("D/ggh.mp3");intn=8;//截取3段cupFiles(from,n);}*//***将一个File平均截取为n段**@paramfrom*@paramn*//*privatestaticvoidcupFiles(Filefrom,intn){longstart=0;longend=0;for(inti=1;i<=n;i++){if(i==n){end=from.length();}else{end=start+from.length()/n;}Fileto=formatFile(from,i);booleancupFile=Main.cupFile(from,start,end,to);System.out.println(i+"复制完成了?:"+cupFile);start=end;}}publicstaticFileformatFile(Filefile,intnum){Stringname=file.getName();intlastIndexOf=name.lastIndexOf('.');StringnewName=newStringBuffer().append(name).insert(lastIndexOf,num).toString();returnnewFile(file.getParentFile(),newName);}*//****@paramfrom*@paramstart*01024204830724096*@paramend*5000*@paramto*@return*//*publicstaticbooleancupFile(Filefrom,longstart,longend,Fileto){try{RandomAccessFileraf=newRandomAccessFile(from,"r");BufferedOutputStreamfos=newBufferedOutputStream(newFileOutputStream(to));raf.seek(start);byte[]b=newbyte[1024];longsum=0;intlen=0;//每次要求读的个数while(true){longk=(end-start)-sum;//剩余需要读的字节数if(k<b.length){len=(int)k;}else{len=b.length;}intread=raf.read(b,0,len);fos.write(b,0,read);sum+=read;if(sum>=end-start){break;}}returntrue;}catch(FileNotFoundExceptione){e.printStackTrace();}catch(IOExceptione){e.printStackTrace();}returnfalse;*/

您需要登录后才可以回帖 登录 | 立即注册

触屏版| 电脑版

技术支持 历史网 V2.0 © 2016-2017