IO(打印流、序列流、ObjectStream、管道流、RandomAccessFile、DataStream、ByteArrayStream)
2013-06-20 14:08
253 查看
IO包中扩展功能的流对象:基本都是装饰设计模式。
——————————————————————————————————
打印流
打印流:该打印流提供了打印方法,可以将各种是数据类型的数据原样打印
字节打印流:PtintStream
构造函数:参数类型:1、File对象;2、字符串路径;3、字节输出流
前两个都JDK1.5版本才出现。而且在操作文本文件时,可指定字符编码了。
当目的是一个字节输出流时,如果使用的println方法,可以在printStream对象上加入一个true参数。这样对于println方法可以进行自动的刷新,而不是等待缓冲区满了再刷新。最终print方法都将具体的数据转成字符串,而且都对IO异常进行了内部处理。
既然操作的数据都转成了字符串,那么使用PrintWriter更好一些。因为PrintWrite是字符流的子类,可以直接操作字符数据,同时也可以指定具体的编码。
字符打印流:PrintWrtier
构造函数:参数类型:1、File对象;2、字符串路径;3、字节输出流;4、字符输出流
1和2可以加入编码,3和4加入true时自动刷新
——————————————————————————————————
序列流
SequenceInputStream
构造函数:1、Enumeration(枚举);2、两个字节读取流。
1、在Vector存储多个字节读取流对象,用Enumeration(枚举)中转作为参数传递给合并流。
就可以把Vector中的多个读取流对象按合并成一个读取流SequenceInputStream。
2、就是把两个读取流对象变成一个读取流SequenceInputStream
分割文件:
原理是在循环获取输出流的循环体中创建读取流对象,写入数据,关闭流,用计数器命名输入流封装的文件。
合并原理:多个读取流对应一个输出流。
切割原理:一个读取流对应多个输出流。
——————————————————————————————————
ObjectStream
对象的序列化:将一个具体的对象进行持久化存储到可以长期保存数据的介质当中,如硬盘、光盘、U盘子类
注意:静态数据不能被序列化,因为静态数据不在堆内存中,是存储在静态方法区中。
如何将非静态的数据不进行序列化?
用transient 关键字修饰此变量即可。被transient修饰的变量就算在标记前序列化的值重新导入,也会回到默认值。一个变量在标记前建立对象序列化后,修改类,给这个类的这个变量加上transient后重新导入对象,这个变量的值不会导入
序列化的对象必须要有对应的class在包中或者导入才能那个加载
Serializable接口:用于启动对象的序列化功能,可以强制让指定类具备序列化功能。
Serializable接口中没有方法,这种接口称为标记接口。
Serializable给类加上一个UID号,其对象在序列化时都有一个ID标识与类的UID想匹配。
对象在序列化后与之对应的类可能发生改变,类发生改变后,重新编译时,UID也会变化。与序列化的对象UD就会不匹配。UID是通过类中的成员算出开的。
ID的作用就是告诉虚拟机这个对象是哪个类的对象。
也就是说一个对象要想序列化,他的类必须实现Serializable接口。
ObjectInputStream与ObjectOutputStream
用于对象持久化的存储和读取,相对应使用
管道流
管道流:管道读取流和管道写入流可以像管道一样对接上,管道读取流就可以读取管道写入流写入的数据。
管道流:需要多线程使用,因为单线程,先执行read,会发生死锁,因为read方法是阻塞式的,没有数据的read方法会让线程等待。
——————————————————————————————————
RandomAccessFile
RandomAccessFile:
该类不算IO体系中的子类,而是直接继承自Object。但是他是IO包中的成员,因为他具备读写功能;它内部封装了一个数组,而且通过指针对数组的元素进行操作。
完成读写的原理就是内部封装了字节读取流和写入流。
构造方法:
RandomAccessFile(File file, String mode) :创建从中读取和向其中写入(可选)的随机访问文件流,该文件由 File 参数指定。
RandomAccessFile(String name, String RandomAccessFile(File file, String mode) :创建从中读取和向其中写入(可选)的随机访问文件流,该文件由 File 参数指定。
RandomAccessFile(String name, String mode) :创建从中读取和向其中写入(可选)的随机访问文件流,该文件具有指定名称。 ) :创建从中读取和向其中写入(可选)的随机访问文件流,该文件具有指定名称。
通过构造方法可以看出,该类只能操作未见(局限性)
而且操作文件还有模式mode:"r","rw","rws","rwd"
"r":只读 :不会创建文件,只会去读取一个已存在的文件,文件不存在,抛异常
"rw":读写:操作的文件不存在,会自动创建。如果存在则也不会覆盖
方法摘要:
void write(byte[] b) :将 b.length 个字节从指定 byte 数组写入到此文件,并从当前文件指针开始。
void write(byte[] b, int off, int len) :将 len 个字节从指定 byte 数组写入到此文件,并从偏移量 off 处开始。
void write(int b) :向此文件写入指定的字节。
int read() :从此文件中读取一个数据字节。
int read(byte[] b) :将最多 b.length 个数据字节从此文件读入 byte 数组。
int read(byte[] b, int off, int len) :将最多 len 个数据字节从此文件读入 byte 数组。
String readLine() :从此文件读取文本的下一行。
long getFilePointer() :返回此文件中的当前偏移量。
long length():返回此文件的长度。
void seek(long pos) :设置到此文件开头测量到的文件指针偏移量,在该位置发生下一个读取或写入操作。如果文件数据是有规律的就比较容易获取想要的数据
int skipBytes(int n):跳过指定的字节数,不过只能往后跳,不能往前跳。
可以通过getFilePointer方法获取指针位置,同时可以通过seek方法改变指针位置,跳过指定的字节位置,进行写入,或者在指定的位置写入数据(覆盖原位置上的数据)。
用法:数据的分段写入(即下载工具的断点续传和多线程)
——————————————————————————————————
DataStream
DataInputStream与DataOutputStream
可以用于操作基本数据类型的数据的流对象
用DataOutputStream的方法writerXXX时,按照不同数据类型写入到文件中,当用DataInputStream获取文件时,用readXXX方法读取,顺序必须和写入顺序一样,否则乱码。
数据存储后用TXT打开是乱码,因为记事本跟虚拟机的编码不同。
用writerXXX和readXXX读写基本数据类型免去强转的麻烦
——————————————————————————————————
ByteArrayStream
操作直接数组的流对象
ByteArrayInputStream:在构造时需要就诶收数据源,为字节数组。
ByteArrayOutputStream:在构造时,不用定义数据目的,因为该对象已经内部封装了可变长度的字节数组,这就是目的。
因为这两个流对象都操作数组,并没有使用系统资源,所以不用关闭流。
ByteArrayOutputStream内部封装的是一个自动增长的缓冲区数组。
数组的操作只有设置和获取,相当于流操作的写和读。用流的思想操作数组。
同理:
CharArrayReader与CharArrayWriter
StringReader与StringReader
——————————————————————————————————
打印流
打印流:该打印流提供了打印方法,可以将各种是数据类型的数据原样打印
字节打印流:PtintStream
构造函数:参数类型:1、File对象;2、字符串路径;3、字节输出流
前两个都JDK1.5版本才出现。而且在操作文本文件时,可指定字符编码了。
当目的是一个字节输出流时,如果使用的println方法,可以在printStream对象上加入一个true参数。这样对于println方法可以进行自动的刷新,而不是等待缓冲区满了再刷新。最终print方法都将具体的数据转成字符串,而且都对IO异常进行了内部处理。
既然操作的数据都转成了字符串,那么使用PrintWriter更好一些。因为PrintWrite是字符流的子类,可以直接操作字符数据,同时也可以指定具体的编码。
字符打印流:PrintWrtier
构造函数:参数类型:1、File对象;2、字符串路径;3、字节输出流;4、字符输出流
1和2可以加入编码,3和4加入true时自动刷新
BufferedReader bffr = new BufferedReader(new InputStreamReader(System.in)); //BufferedWriter bffw = new BufferedWriter(new OutputStreamWriter(System.out)); PrintWriter pw = new PrintWriter(System.out); String line = null; while((line=bffr.readLine())!=null) { if(line.equals("over")) break; //bffw.write(line); //bffw.newLine(); //bffw.flush(); pw.println(line); pw.flush(); } }
——————————————————————————————————
序列流
SequenceInputStream
构造函数:1、Enumeration(枚举);2、两个字节读取流。
1、在Vector存储多个字节读取流对象,用Enumeration(枚举)中转作为参数传递给合并流。
就可以把Vector中的多个读取流对象按合并成一个读取流SequenceInputStream。
2、就是把两个读取流对象变成一个读取流SequenceInputStream
{ Vector<InputStream> v = new Vector<InputStream>(); v.add(new FileInputStream("a.txt")); v.add(new FileInputStream("b.txt")); v.add(new FileInputStream("c.txt")); Enumeration<InputStream> en = v.elements(); SequenceInputStream sis = new SequenceInputStream(en); FileOutputStream fos = new FileOutputStream("0.txt"); byte[] buf = new byte[1024*1024]; int num = 0; while((num=sis.read(buf))!=-1) { fos.write(buf,0,num); } sis.close(); fos.close(); }
分割文件:
原理是在循环获取输出流的循环体中创建读取流对象,写入数据,关闭流,用计数器命名输入流封装的文件。
{ //关联一个需要分割的文件 FileInputStream fis = new FileInputStream("c:\\008_007.jpg"); FileOutputStream fos = null; byte[] buf = new byte[1024*1024]; int len =0; int count = 1; while ((len=fis.read(buf))!=-1) { fos = new FileOutputStream("c:\\"+count+".part"); fos.write(buf,0,len); fos.close(); count++; } fis.close(); }
合并原理:多个读取流对应一个输出流。
切割原理:一个读取流对应多个输出流。
——————————————————————————————————
ObjectStream
对象的序列化:将一个具体的对象进行持久化存储到可以长期保存数据的介质当中,如硬盘、光盘、U盘子类
注意:静态数据不能被序列化,因为静态数据不在堆内存中,是存储在静态方法区中。
如何将非静态的数据不进行序列化?
用transient 关键字修饰此变量即可。被transient修饰的变量就算在标记前序列化的值重新导入,也会回到默认值。一个变量在标记前建立对象序列化后,修改类,给这个类的这个变量加上transient后重新导入对象,这个变量的值不会导入
序列化的对象必须要有对应的class在包中或者导入才能那个加载
Serializable接口:用于启动对象的序列化功能,可以强制让指定类具备序列化功能。
Serializable接口中没有方法,这种接口称为标记接口。
Serializable给类加上一个UID号,其对象在序列化时都有一个ID标识与类的UID想匹配。
对象在序列化后与之对应的类可能发生改变,类发生改变后,重新编译时,UID也会变化。与序列化的对象UD就会不匹配。UID是通过类中的成员算出开的。
ID的作用就是告诉虚拟机这个对象是哪个类的对象。
也就是说一个对象要想序列化,他的类必须实现Serializable接口。
ObjectInputStream与ObjectOutputStream
用于对象持久化的存储和读取,相对应使用
public static void writeObj()throws IOException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.txt")); oos.writeObject(new Person("zhangsan",90,"cn")); oos.close(); } public static void readObj()throws Exception { ObjectInputStream ois = new ObjectInputStream(new FileInputStream("object.txt")); Person p = (Person)ois.readObject(); System.out.println(p); ois.close(); }——————————————————————————————————
管道流
管道流:管道读取流和管道写入流可以像管道一样对接上,管道读取流就可以读取管道写入流写入的数据。
管道流:需要多线程使用,因为单线程,先执行read,会发生死锁,因为read方法是阻塞式的,没有数据的read方法会让线程等待。
class myPipedDemo { public static void main(String[] args) throws IOException { PipedOutputStream pos = new PipedOutputStream(); PipedInputStream pis = new PipedInputStream(); pis.connect(pos);//将两个流连接; read r = new read(pis); write w = new write(pos); w.setStr("大范甘迪发生过的风格的风格好似打工是大法官的风格是大法官"); Thread t1 =new Thread(r); Thread t2 =new Thread(w); t1.start(); t2.start(); } } class read implements Runnable//输出流,吧管道流作为参数传递到线程类里面 { PipedInputStream in; read(PipedInputStream in) { this.in=in; } public void run() { try { byte[] num = new byte[10]; int len = 0; while((len=in.read(num))!=-1) { String s = new String(num,0,len); System.out.print(s); } in.close(); } catch (IOException e) { System.out.println("管道输出流失败"); } } } class write implements Runnable//输入流 { PipedOutputStream out; String str; write(PipedOutputStream out) { this.out=out; } public void run() { try { out.write(str.getBytes()); out.close(); } catch (IOException e) { System.out.println("管道输入流失败"); } } void setStr(String str) { this.str = str; } }
——————————————————————————————————
RandomAccessFile
RandomAccessFile:
该类不算IO体系中的子类,而是直接继承自Object。但是他是IO包中的成员,因为他具备读写功能;它内部封装了一个数组,而且通过指针对数组的元素进行操作。
完成读写的原理就是内部封装了字节读取流和写入流。
构造方法:
RandomAccessFile(File file, String mode) :创建从中读取和向其中写入(可选)的随机访问文件流,该文件由 File 参数指定。
RandomAccessFile(String name, String RandomAccessFile(File file, String mode) :创建从中读取和向其中写入(可选)的随机访问文件流,该文件由 File 参数指定。
RandomAccessFile(String name, String mode) :创建从中读取和向其中写入(可选)的随机访问文件流,该文件具有指定名称。 ) :创建从中读取和向其中写入(可选)的随机访问文件流,该文件具有指定名称。
通过构造方法可以看出,该类只能操作未见(局限性)
而且操作文件还有模式mode:"r","rw","rws","rwd"
"r":只读 :不会创建文件,只会去读取一个已存在的文件,文件不存在,抛异常
"rw":读写:操作的文件不存在,会自动创建。如果存在则也不会覆盖
方法摘要:
void write(byte[] b) :将 b.length 个字节从指定 byte 数组写入到此文件,并从当前文件指针开始。
void write(byte[] b, int off, int len) :将 len 个字节从指定 byte 数组写入到此文件,并从偏移量 off 处开始。
void write(int b) :向此文件写入指定的字节。
int read() :从此文件中读取一个数据字节。
int read(byte[] b) :将最多 b.length 个数据字节从此文件读入 byte 数组。
int read(byte[] b, int off, int len) :将最多 len 个数据字节从此文件读入 byte 数组。
String readLine() :从此文件读取文本的下一行。
long getFilePointer() :返回此文件中的当前偏移量。
long length():返回此文件的长度。
void seek(long pos) :设置到此文件开头测量到的文件指针偏移量,在该位置发生下一个读取或写入操作。如果文件数据是有规律的就比较容易获取想要的数据
int skipBytes(int n):跳过指定的字节数,不过只能往后跳,不能往前跳。
可以通过getFilePointer方法获取指针位置,同时可以通过seek方法改变指针位置,跳过指定的字节位置,进行写入,或者在指定的位置写入数据(覆盖原位置上的数据)。
用法:数据的分段写入(即下载工具的断点续传和多线程)
public static void readFile()throws IOException { RandomAccessFile raf = new RandomAccessFile("ran.txt","r"); //调整对象中指针。 //raf.seek(8*1); //跳过指定的字节数 raf.skipBytes(8); byte[] buf = new byte[4]; raf.read(buf); String name = new String(buf); int age = raf.readInt(); System.out.println("name="+name); System.out.println("age="+age); raf.close(); } public static void writeFile_2()throws IOException { RandomAccessFile raf = new RandomAccessFile("ran.txt","rw"); raf.seek(8*0); raf.write("周期".getBytes()); raf.writeInt(103); raf.close(); } public static void writeFile()throws IOException { RandomAccessFile raf = new RandomAccessFile("ran.txt","rw"); raf.write("李四".getBytes()); raf.writeInt(97); raf.write("王五".getBytes()); raf.writeInt(99); raf.close(); }
——————————————————————————————————
DataStream
DataInputStream与DataOutputStream
可以用于操作基本数据类型的数据的流对象
用DataOutputStream的方法writerXXX时,按照不同数据类型写入到文件中,当用DataInputStream获取文件时,用readXXX方法读取,顺序必须和写入顺序一样,否则乱码。
数据存储后用TXT打开是乱码,因为记事本跟虚拟机的编码不同。
用writerXXX和readXXX读写基本数据类型免去强转的麻烦
public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("raf2.txt"); DataInputStream dis = new DataInputStream(fis); byte[] bus = new byte[1024]; int len = dis.read(bus); String str = new String(bus,0,len); System.out.println(str); }
——————————————————————————————————
ByteArrayStream
操作直接数组的流对象
ByteArrayInputStream:在构造时需要就诶收数据源,为字节数组。
ByteArrayOutputStream:在构造时,不用定义数据目的,因为该对象已经内部封装了可变长度的字节数组,这就是目的。
因为这两个流对象都操作数组,并没有使用系统资源,所以不用关闭流。
ByteArrayOutputStream内部封装的是一个自动增长的缓冲区数组。
数组的操作只有设置和获取,相当于流操作的写和读。用流的思想操作数组。
同理:
CharArrayReader与CharArrayWriter
StringReader与StringReader
相关文章推荐
- IO流5(IO包中的其他类,ObjectStream,管道流,RandomAccessFile,DataStream,ByteArrayStream)
- Java基础 管道流 RandomAccessFile DataStream ByteArrayStream 字符编码
- Java基础---Java---IO流-----对象的序列化、管道流、RandomAccessFile、数据类型的流对象DataStream、ByteArrayStream
- Java基础---Java---IO流-----对象的序列化、管道流、RandomAccessFile、数据类型的流对象DataStream、ByteArrayStream
- JAVA基础学习day22--IO流四-对象序列化、管道流、RandomAccessFile、DataStream、ByteArrayStream、转换流的字符编码
- JAVA基础学习(二十二)--IO流四-对象序列化、管道流、RandomAccessFile、DataStream、ByteArrayStream、转换流的字符编码
- IO流__【对象的序列化】【管道流】【RandomAccessFile】【DataStream】【ByteArrayStream等】
- 黑马程序员_IO流四(对象的序列化,管道流,RandomAccessFile,DataStream,ByteArrayStream)
- 黑马程序员_IO流4_(对象的序列化,管道流,RandomAccessFile,DataStream,ByteArrayStream)
- java--io流-打印流,序列流,操作对象,管道流,RandomAccessFile,操作字节数组
- Lesson_for_java_day18--java中的IO流(序列化、ByteArrayStream、DataStream、RandowAccessFile)
- 黑马程序员_十七 【对象序列化】【管道流】【RandomAccessFile 类】等IO其他类
- 黑马程序猿——25,打印流,合并流,对象序列化,管道流,RandomAccessFile
- Java基础——对象序列化+管道流+RandomAccessFile+操作基本数据类型的DataStream等
- 黑马程序员——41,打印流,合并流,对象序列化,管道流,RandomAccessFile
- day21对象流。管道流。RandomAccessFile。DataStream。字节流。常见的编码表。编码解码。联通问题。
- 10.26的总结, 管道流用法, RandomAccessFile, DataStream 有待深入.
- 流。FileInputStream,DataOutputStream,ByteArrayInputStream,RandomAccessFile
- Java基础-打印流和合并流、分割与管道流、RandomAccessFile及其它流
- Java基础--IO-RandomAccessFile/ObjectOutputStream