• 1. 其他过滤流LineNumberInputStream:主要用于对文本文件的处理,提供了行号控制功能。 已经被LineNumberReader取代 PushBackInputStream:在编译程序的词法分析阶段,经常要超前读入一个字节以界定当前词的属性,然后再将该字节退回(因为下面的处理可能还会用到该字节)。 PushBackInputStream就提供了这样的能力,它提供了一个方法将刚刚读入的字节退回到输入流中去。 PrintStream:其作用是将Java语言中的不同类型的数据以字符表示形式输出到相应的输出流中去。 不产生异常。可自动flush。通过checkError()检查错误。
  • 2. 对象流1、对象的持续性(Persistence) 能够纪录自己的状态以便将来再生的能力,叫对象的持续性。 2、对象的串行化(Serialization) 对象通过写出描述自己状态的的数值来记录自己的过程叫串行化。串行化的主要任务是写出对象实例变量的数值,如果变量是另一个对象的引用,则引用的对象也要串行化。这个过程是递归的。 3、 对象流 能够输入输出对象的流称为对象流。 可以将对象串行化后通过对象输入输出流写入文件或传送到其它地方。
  • 3. 要串行化一个对象,必须与一定的对象输出/输入流联系起来,通过对象输出流将对象状态保存下来(将对象保存到文件中,或者通过网络传送到其他地方) ,再通过对象输入流将对象状态恢复。 类ObjectOutputStream和ObjectInputStream分别继承了接口ObjectOutput和ObjectInput,将数据流功能扩展到可以读写对象,前者用writeObject()方法可以直接将对象保存到输出流中,而后者用readObject()方法可以直接从输入流中读取一个对象。 从某种意义来看,对象流与数据流是相类似的,也具有过滤流的特性。利用对象流来输入/输出对象时,也不能单独使用,需要与其他的流连接起来。
  • 4. 一个保存和读取对象的示例: class Student implements Serializable { public long s_id; public String name; public int age; public String msg; public Student(long s_id,String name,int age,String msg) { this.s_id=s_id; this.name=name; this.age=age; this.msg=msg; } }
  • 5. 将对象写入文件: import java.io.FileOutputStream; import java.io.ObjectOutputStream; import java.io.Serializable; public class Object_demo { public static void main(String args[]) { Student stu=new Student(20000101, "张三", 26, "学员"); try { FileOutputStream fo = new FileOutputStream("e:/data.obj"); ObjectOutputStream so = new ObjectOutputStream(fo); so.writeObject(stu); System.out.println("对象成功写入文件!"); so.close(); } catch(Exception e) { System.out.println(e) ; } } }
  • 6. 在文件中读取对象: import java.io.FileInputStream; import java.io.ObjectInputStream; public class Object_demo_r { public static void main(String args[]) { Student stu=null; try { FileInputStream fi = new FileInputStream("e:/data.ser"); ObjectInputStream si = new ObjectInputStream(fi); stu = (Student)si.readObject(); si.close(); } catch(Exception e) { System.out.println(e); } System.out.println("ID: "+stu.s_id+"\nname:"+stu.name+"\nage:"+stu.age+"\nmsg:"+stu.msg); } }
  • 7. 以上这个程序需要注意以下几点: 1、我们所要保存的对象的类,必须实现接口: Serializable。 这个接口里面没有定义任何方法,它相当于是一个标记,用来表示这个类是可以被序列化的。 2、保存对象的文件是data.obj 这个文件格式是系统不能够识别的,我们可以将文件格式改成我们所常用的txt或者doc,但是运行之后我们打开这个文件就会发现,保存在文件内的是一堆乱码。 所以说,这个一般使用于网络数据传输,或者对象的持续性,但是不能用于数据的持久化。
  • 8. 定制对象的串行化:当一个对象串行化时,如果希望该对象的某些属性不被保存,可以通过在类定义中重写readObject()和WriteObject()方法来实现。 我们可以在上面的Student类中加入如下类似的方法: private void writeObject(ObjectOutputStream out) throws IOException { out.writeInt(s_id); … // out.defaultWriteObject() } private void readObject(ObjectInputStream in) throws IOException { id = in.readInt(); … // in.defaultReadObject() }
  • 9. 串行化只能保存对象的非静态成员变量(实例变量),而不能保存任何成员方法和静态成员变量,并且保存的只是变量的值,对于变量的任何修饰符都不能保存。 对于某些类型的对象,其状态是瞬时的,这样的对象是无法保存其状态的,如Thread对象或流对象。对于这样的成员变量,必须用transient关键字标明,否则编译器将报错。任何用transient关键字标明的成员变量,都不会被保存。 另外,串行化可能涉及将对象存放到磁盘上或在网络上发送数据,这时会产生安全问题。对于一些需要保密的数据,不应保存在永久介质中(或者不应简单地不加处理地保存下来),为了保证安全,应在这些变量前加上transient关键字。
  • 10. 管道流传送输入流应该连接到传送输出流;传送输入流会提供要写入传送输出流的所有数据字节。通常,数据由某个线程从 PipedInputStream 对象读取,并由其他线程将其写入到相应的 PipedOutputStream。不建议对这两个对象尝试使用单个线程,因为这样可能会死锁该线程。传送输入流包含一个缓冲区,可在缓冲区限定的范围内将读操作和写操作分离开。 管道输入/输出流可以用两种方式进行连接: 1)在构造方法中进行连接 PipedInputStream(PipedOutputStream pos); PipedOutputStream(PipedInputStream pis); 2)通过各自的connect()方法连接 在类PipedInputStream中, connect(PipedOutputStream pos); 在类PipedOutputStream中, connect(PipedInputStream pis);
  • 11. 在实际开发中,管道流使用的并不多,所以就不多做介绍了,下面给出一个管道流的简单示例: import java.io.IOException; import java.io.PipedInputStream; import java.io.PipedOutputStream; public class Pip_demo { public static void main(String args[]) throws IOException { byte b1 = 12, b2 = 13; PipedInputStream pis = new PipedInputStream(); PipedOutputStream pos = new PipedOutputStream(pis); System.out.println("PipedInputStream");
  • 12. try { pos.write(b1); pos.write(b2); System.out.println((byte)pis.read()); System.out.println((byte)pis.read()); } finally { pis.close(); pos.close(); } } }
  • 13. 内存读写流为了支持在内存上的I/O,java.io中提供了类 ByteArrayInputStream ByteArrayOutputStream StringBufferInputStream ByteArrayInputStream可以从指定的字节数组中读取数据。 ByteArrayOutputStream中提供了缓冲区可以存放数据(缓冲区大小可以在构造方法中设定,缺省为32),可以用write()方法向其中写入数据,然后用toByteArray()方法将缓冲区中的有效字节写到字节数组中去。size()方法可以知道写入的字节数;reset()可以丢弃所有内容。 StringBufferInputStream与ByteArrayInputStream相类似,不同点在于它是从字符缓冲区StringBuffer中读取16位的Unicode数据,而不是8位的字节数据。 (已被StringReader取代)
  • 14. 顺序输入流 java.io中提供了类SequenceInputStream,使应用程序可以将几个输入流顺序连接起来,让程序员看起来就像是一个比较长的流一样。顺序输入流提供了将多个不同的输入流统一为一个输入流的功能,这使得程序可能变得更加简洁。如: FileInputStream f1,f2; String s; f1 = new FileInputStream("file1.txt"); f2 = new FileInputStream("file2.txt"); SequenceInputStream fs = new SequenceInputStream(f1, f2); DataInputStream ds = new DataInputStream(fs); while( (s = ds.readLine()) != null ) System.out.println(s);
  • 15. 字符流在JDK1.1之前,java.io包中的流只有普通的字节流(以byte为基本处理单位的流),这种流对于以16位的Unicode码表示的字符流处理很不方便。从JDK1.1开始, java.io包中加入了专门用于字符流处理的类,它们是以Reader和Writer为基础派生的一系列类。 同类InputStream和OutputStream一样,Reader和Writer也是抽象类,只提供了一系列用于字符流处理的接口。它们的方法与类InputStream和OutputStream类似,只不过其中的参数换成字符或字符数组。 Reader和Writer是所有字符流的父类。
  • 16. Reader类void close()  void mark(int readAheadLimit)  boolean markSupported() :  int read()  int read(char[] cbuf)  int read(char[] cbuf, int off, int len)  boolean ready()  void reset()  long skip(long n)
  • 17. Writer类 void close()  void flush()  void write(char[] cbuf)  void write(char[] cbuf, int off, int len)  void write(int c)  void write(String str)  void write(String str, int off, int len)
  • 18. InputStreamReader和OutputStreamWriter InputStreamReader和OutputStreamWriter是java.io包中用于处理字符流的最基本的类,用来在字节流和字符流之间作为中介:从字节输入流读入字节,并按编码规范转换为字符;往字节输出流写字符时先将字符按编码规范转换为字节。使用这两者进行字符处理时,在构造方法中应指定一定的平台规范,以便把以字节方式表示的流转换为特定平台上的字符表示。 InputStreamReader(InputStream in); //缺省规范 InputStreamReader(InputStream in, String enc); //指定规范enc OutputStreamWriter(OutputStream out); //缺省规范 OutputStreamWriter(OutputStream out, String enc); //指定规范enc
  • 19. 如果读取的字符流不是来自本地时(比如网上某处与本地编码方式不同的机器),那么在构造字符输入流时就不能简单地使用缺省编码规范,而应该指定一种统一的编码规范"ISO 8859_1",这是一种映射到ASCII码的编码方式,能够在不同平台之间正确转换字符。 比如说: InputStreamReader ir= new InputStreamReader( is, "8859_1" ); 具体实例就不给出了,和过滤流类似,嵌套一个基础流。然后使用对应的读写方法即可。
  • 20. 字符缓冲流 同样的,为了提高字符流处理的效率,java.io中也提供了缓冲流BufferedReader和BufferedWriter。其构造方法与BufferedInputStream和BufferedOutputStream相类似。另外,除了read()和write()方法外,它还提供了整行字符处理方法: public String readLine(): BufferedReader的方法,从输入流中读取一行字符,行结束标志为‘\n’、‘\r’或两者一起。 public void newLine(): BufferedWriter的方法,向输出流中写入一个行结束标志,它不是简单的换行符'\n’或‘\r’,而是系统定义的行隔离标志(line separator)。
  • 21. 下面是一个综合的示例: import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.FileInputStream; import java.io.OutputStreamWriter; public class ir_ow_demo { public static void main(String[] args) { try { //读取文件 BufferedReader ir=new BufferedReader(new InputStreamReader(new FileInputStream("e:/goods.txt"))); //写入文件 BufferedWriter iw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("e:/demo.txt")));
  • 22. String str=null; try { while((str=ir.readLine())!=null) { System.out.println(str); iw.write(str+"\r\n"); } } catch (IOException e) { e.printStackTrace(); } try { iw.close(); ir.close(); } catch (IOException e) { e.printStackTrace(); } } catch (FileNotFoundException e) { e.printStackTrace(); } } }
  • 23. 一些其他的字符流CharArrayReader CharArrayWriter对字符数组进行处理LineNumberReader: 行处理字符流 PrintWriter: 打印字符流FileReader FileWriter对文本文件进行处理StringReader StringWriter对字符串进行处理FilterReader FilterWriter过滤字符流PipedReader PipedWriter管道字符流
  • 24. 随机访问文件 对于FileInputStream/FileOutputStream、FileReader/FileWriter来说,它们的实例都是顺序访问流,即只能进行顺序读/写。而类RandomAccessFile则允许对文件内容同时完成读和写操作,它直接继承object,并且同时实现了接口DataInput和DataOutput,提供了支持随机文件操作的方法: readXXX()或writeXXX(): 如ReadInt(), ReadLine(), WriteChar(), WriteDouble()等。  int skipBytes(int n):将指针向下移动若干字节 length():返回文件长度 long getFilePointer():返回指针当前位置 void seek(long pos):将指针调到所需位置
  • 25. 在生成一个随机文件对象时,除了要指明文件对象和文件名之外,还需要指明访问文件的模式。 RandomAccessFile(File file, String mode) RandomAccessFile(String name, String mode) mode 的取值: "r" 只读. 任何写操作都将抛出IOException。 "rw" 读写. 文件不存在时会创建该文件,文件存在时,原文件内容不变,通过写操作改变文件内容。 "rws" 同步读写. 等同于读写,但是任何写操作的内容都被直接写入物理文件,包括文件内容和文件属性。 "rwd" 数据同步读写. 等同于读写,但任何内容写操作都直接写到物理文件,但对文件属性内容的修改不是这样。
  • 26. 小结在Java中有数据传输的地方都用到I/O流(通常是文件、网络、内存和标准输入输出等)。 InputStream 和OutputStream是所有字节流的父类(只有RandomAccessFile类是一个例外),read和write是它们最基本的方法,读写单位是字节。 Reader 和Writer是所有字符流的父类,read和write是它们最基本的方法,读写单位是字符。 在众多的流对象中,并不是每一种都单独使用,其中过滤流的子类在数据的传输过程中需要套接其他基础流。
  • 27. File, File(Input/Output)Stream, RandomAccessFile是处理本地文件的类。 Data(Input/Output)Stream是一个过滤流的子类,借此可以读写各种基本数据,在文件和网络中经常使用。如: readByte, writeBoolean等。 Buffered(Input/Output)Stream的作用是在数据送到目的之前先缓存,达到一定数量时再送到目的,以减少阻塞次数。 Piped(Input/Output)Stream适合与一个处理的输出作为另一个处理的输入的情况。
  • 28. 金山游侠:游戏存档作弊器 根据用户输入的数字,修改指定数字的值 比如: 游戏中人物金钱数为:2342 用户输入 搜索>2342 程序分析程序得到5个结果 编号:shortIntLong12342-34523452345234523202342-3456345633002342修改指定的值:update 2 9999999 保存save
  • 29. 十六进制编辑专家:黑客工具 打开一个exe可执行文件,对其进行修改和编辑, 以达到想要的效果 比如软件破解,查看机密数据,修改程序5AFBD6C800可视化文本C8 FB C8 FB 00 Asdf??..sdsf?sdf?? 43asd/ ????FB 00 C8 00 00 5AFBD6C800监视数字(int)2341100-45634305AFBD6C800转化为 二进制00101001110001011011