国内最全IT社区平台 联系我们 | 收藏本站
华晨云阿里云优惠2
您当前位置:首页 > php开源 > php教程 > Java之------IO加强

Java之------IO加强

来源:程序员人生   发布时间:2016-06-13 11:36:27 阅读次数:2540次

RandomAccessFile

1、随机访问文件,本身具有读写的方法

new RandomAccessFile()以后,若文件不存在会自动创建,存在则不创建。——该类其实内部既封装了字节输入流,又封装了字节输出流。

该类若用write()方法写整数,每次只写它的最后1个字节。而采取writeInt()方法,则可把1个整数完全地写入。 

2、通过skipBytes(int x),seek(int x)来到达随机访问

通过seek方法设置数据的指针就能够实现对文件数据的随机读写。InputStream中的skip()方法只能从头往后跳,不能反向;而seek()方法可双向随意定位。

3、数据修改方面的特点

用RandomAccessFile类可以实现数据的修改,固然文件中的数据1般要有规律,以方便在编程时能够进行定位,让数据写对地方。 而用“流”实现数据修改时,则通常需要把数据从流读到数组当中,在数组中进行数据修改,然后再把修改后的数组

再重新写到流中。 


序列化

★ 序列化

将1个对象寄存到某种类型的永久存储器上称为保持。如果1个对象可以被寄存到磁盘或磁带上,或可以发送到另外1台机器并寄存到存储器或磁盘上,那末这个对象就被称为可保持的。(在Java中,序列化、持久化、串行化是1个概念。)
java.io.Serializable接口没有任何方法,它只作为1个“标记者”,用来表明实现了这个接口的类可以斟酌串行化。类中没有实现Serializable的对象不能保存或恢复它们的状态。 

★ 对象图

当1个对象被串行化时,只有对象的数据被保存;方法和构造函数不属于串行化流。如果1个数据变量是1个对象,那末这个对象的数据成员也会被串行化。树或对象数据的结构,包括这些子对象,构成了对象图。

★ 瞬时 transient

避免对象的属性被序列化。

Address.java

package io.serializable; import java.io.Serializable; public class Address implements Serializable { //静态变量是不会被序列化的。对非静态变量,1般情况下都会被序列化,但如果声明成transient型则不会。 transient int num;//瞬时变量---该变量是不会被序列化的---不会出现在对象图中的 private String name; private int age; private String tel; public Address(String name, int age, String tel) { super(); this.name = name; this.age = age; this.tel = tel; } public Address(int num, String name, int age, String tel) { super(); this.num = num; this.name = name; this.age = age; this.tel = tel; } @Override public String toString() { return "Address [num=" + num + ", name=" + name + ", age=" + age + ", tel=" + tel + "]"; } }
SerializableDemo.java

package io.serializable; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; public class SerializableDemo { public static void main(String[] args) throws Exception { //demo1(); demo2(); } private static void demo2() throws FileNotFoundException, IOException, ClassNotFoundException { //对象序列化---输出,写 OutputStream fout = new FileOutputStream("a.txt"); ObjectOutputStream out = new ObjectOutputStream(fout); out.writeObject( new Address(1,"aa",23,"13588888888")); out.writeObject( new Address(2,"bb",24,"13566666666")); out.writeObject( new Address(3,"cc",23,"13577777777")); out.writeObject( new Address(4,"dd",25,"13599999999")); out.close(); //反序列化----读 InputStream fin = new FileInputStream("a.txt"); ObjectInputStream in = new ObjectInputStream(fin); System.out.println( in.readObject() ); System.out.println( in.readObject() ); System.out.println( in.readObject() ); System.out.println( in.readObject() ); } private static void demo1() throws FileNotFoundException, IOException, ClassNotFoundException { //对象序列化---输出,写 OutputStream fout = new FileOutputStream("a.txt"); ObjectOutputStream out = new ObjectOutputStream(fout); out.writeObject( new Address("aa",23,"13588888888")); out.writeObject( new Address("bb",24,"13566666666")); out.writeObject( new Address("cc",23,"13577777777")); out.writeObject( new Address("dd",25,"13599999999")); out.close(); //反序列化----读 InputStream fin = new FileInputStream("a.txt"); ObjectInputStream in = new ObjectInputStream(fin); System.out.println( in.readObject() ); System.out.println( in.readObject() ); System.out.println( in.readObject() ); System.out.println( in.readObject() ); } }

缓冲输入输出流
(BufferedInputStream和BufferedOutputStream)

方式1:

DataInputStream in = new DataInputStream( new BufferedInputStream( new FileInputStream("Test.txt") );
方式2:

DataInputStream in = new DataInputStream( new FileInputStream("Test.txt") );
方式3:

BufferedInputStream in = new BufferedInputStream( new DataInputStream( new FileInputStream("Test.java") );

☆示例测试技术总结:方案1是最优的

1)有buffer比没有更快;

2)buffer放在中间层包装比放在外层更快;

3)按行或按块操作 比 按字节或字符操作更快(用Object流操作的速度 比 字节字符方式 更快)

4)缓冲区要结合流才可使用,在流的基础上对流的功能进行了增强。

package io.buffer; import java.io.BufferedInputStream; import java.io.DataInputStream; import java.io.FileInputStream; public class BufferedStreamDemo { public static void main(String[] args) { try { //test1(); //test2(); test3(); } catch (Exception e) { e.printStackTrace(); } } private static void test1() throws Exception { long t1 = System.currentTimeMillis(); DataInputStream din = new DataInputStream(new BufferedInputStream( new FileInputStream("b.txt"))); String str = null; while ((str = din.readLine()) != null) { System.out.println(str); } long t2 = System.currentTimeMillis(); System.out.println("方式1运行时间(毫秒):" + (t2 - t1)); } private static void test2() throws Exception { long t1 = System.currentTimeMillis(); DataInputStream din = new DataInputStream( new FileInputStream("b.txt")); String str = null; while ((str = din.readLine()) != null) { System.out.println(str); } long t2 = System.currentTimeMillis(); System.out.println("方式2运行时间(毫秒):" + (t2 - t1)); } private static void test3() throws Exception { long t1 = System.currentTimeMillis(); BufferedInputStream bin = new BufferedInputStream( new DataInputStream( new FileInputStream("b.txt")) ); byte buf[] = new byte[20]; int n=0; while ((n = bin.read(buf)) != ⑴) { System.out.println(new String(buf,0,n)); } long t2 = System.currentTimeMillis(); System.out.println("方式3运行时间(毫秒):" + (t2 - t1)); } }


转换流
(InputStreamReader和OutputStreamWriter)

★转换流功能1:充当字节流与字符流之间的桥梁

需求:摹拟英文聊天程序,要求:
     (1) 从键盘录入英文字符,每录1行就把它转成大写输出到控制台;
     (2) 保存聊天记录到字节流文件。

 要求1的设计分析:

1)需要从键盘接收录入,得用System.in,它是字节输入流InputStream;
2)需要处理字符,可以自己把字节强转成字符,也能够用字符流;
3)需要类似readLine的功能,而这个方法在字符流BufferedReader中有(而且该类有缓冲增速)。
综上,采取转换流把字节流转成字符流处理比较公道,即便用InputStreamReader

 要求2的设计分析:

1)需要把字符数据按行保存到字节流文件 ;
2)字符流采取BufferedWriter比较适合,由于它有newLine方法且能实现高效;
3)字节流文件,得采取FileOutputStream。
综上,采取转换流把字符流转成字节流处理比较公道,即便用OutputStreamWriter

package io.transfer; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; public class TranStreamDemo { public static void main(String[] args) throws IOException { //输入 InputStream in = System.in; InputStreamReader isr = new InputStreamReader(in); BufferedReader br = new BufferedReader(isr); //输出 OutputStream out = new FileOutputStream("chat.txt"); OutputStreamWriter osw = new OutputStreamWriter(out); BufferedWriter bw = new BufferedWriter(osw); String line = null; while( (line=br.readLine())!=null){ if("over".equals(line)){//养成好的代码习惯:调用String中的方法时,把常量字符串放在前面,避免变量为null而致使异常 break; } System.out.println( line.toUpperCase() ); bw.write(line); bw.newLine(); bw.flush();//字符流是带缓冲的,必须刷缓冲 } } }

★转换流功能2:字符编码转换

采取FileWriter以默许方式编码
    FileOutputStream+默许编码表

采取转换流以默许方式编码
   OutputStreamWriter + FileOutputStream + 默许编码表

采取转换流以指定编码方式编码
   OutputStreamWriter + FileOutputStream +指定编码表

采取转换流以指定编码方式解码
   InputStreamReader + FileInputStream +指定编码表

package io.transfer; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; public class TranStreamDemo2 { public static void main(String[] args) { try { //readTextDecoding1(); //readTextDecoding2(); writeTextEncoding(); } catch (IOException e) { e.printStackTrace(); } } private static void writeTextEncoding() throws IOException { //第1种: FileWriter+默许编码表 FileWriter fw = new FileWriter("files\\w_utf⑻.txt");//该文件的编码由平台(如MyEclipse或dos窗口)定,不1定是utf⑻ fw.write("每天进步1点点..."); fw.close(); //第2种: OutputStreamWriter+默许编码表 OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("files\\w_utf⑻_2.txt"));//该文件的编码由平台(如MyEclipse或dos窗口)定,不1定是utf⑻ osw.write("第天进步1点点...");//牛耳 osw.close(); //第3种: OutputStreamWriter+指定编码表 OutputStreamWriter osw2 = new OutputStreamWriter(new FileOutputStream("files\\w_utf⑻_3.txt"),"utf⑻");//该文件的编码1定是utf⑻,由于是我们自己指定的 osw2.write("第天进步1点点..."); osw2.close(); } private static void readTextDecoding1() throws IOException { FileReader fr = new FileReader("files\\utf⑻.txt");//采取默许编码表解码 char[] cbuf = new char[10]; int len=0; while( (len=fr.read(cbuf))!=⑴){ String str = new String(cbuf,0,len); System.out.print(str); } fr.close(); } private static void readTextDecoding2() throws IOException { //InputStreamReader isr = new InputStreamReader(new FileInputStream("files\\gbk.txt"));//如果不指定编码表,则是采取默许的 //用转换流自己指定解码表----只要文件的编码表和这里指定的解码表相同,就不会出现乱码 //InputStreamReader isr = new InputStreamReader( new FileInputStream("files\\gbk.txt"), "gbk"); //ok //InputStreamReader isr = new InputStreamReader( new FileInputStream("files\\utf⑻.txt"), "gbk");//乱码 InputStreamReader isr = new InputStreamReader( new FileInputStream("files\\utf⑻.txt"), "utf⑻");//ok char[] cbuf = new char[20]; int len = isr.read(cbuf); String str = new String(cbuf,0,len); System.out.println(str); isr.close(); } }


打印流

(PrintStream和PrintWriter)

★打印流的特点:

1)只有输出没有输入。PrintStream是字节打印流,PrintWriter是字符打印流。
2)能够方便地打印各种数据“值表示情势”,提供了1系列的打印功能(只有它有,其它流都没有。)
3)和其他输出流不同,它永久不会抛出IOException异常(构造方法除外),异常内部解决且设置了内部标志。
4)可创建具有自动刷新的功能,可以使用带换行符的println()方法。
5)(在构造方法中)可以指定字符集编码的。

package io.print; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; //System.out就是PrintStream类型 public class PrintStreamDemo { public static void main(String[] args) { try { demo1(); demo2(); for(int i=0;i<10;i++){ System.out.println(i); } } catch (IOException e) { e.printStackTrace(); } } //把System.out的输出目的地从屏幕更改到日志文件 private static void demo2() throws IOException { FileOutputStream fout = new FileOutputStream("log.txt"); PrintStream out = new PrintStream(fout, true); System.setOut(out); } private static void demo1() throws IOException { // PrintStream out = new PrintStream("print.txt"); //out.write()只写入1个字节的信息,如果参数大于1个字节的范围,那末实际上只会写入最后1个字节的数据 //out.write(97); out.write(353);//最后1个字节是97,因此写入的是1个字符'a'----写入的是值的表现情势 //System.out.write(353);//输出'a' //System.out.flush(); out.println(345);//把参数转换成字符串输出 //上1句等价于out.write( String.valueOf(i) ) //※总之,PrintStream中用write()输出的是字节数据且每次只输出1个字节,而print()输出的是数据的值的表现情势即转换成字符串输出。 //JSP中的out对象就是这类类型。要输出字节数据如图片声明等2进制格式则必须用write(),而输出页面数据(字符)则要用print()或println() } }

★关于打印流的自动刷新

只有遇到结束字符(换行符)时才会自动刷新,如在调用其中1个println方法或写入换行符或字节('\n)时会自动刷新输出缓冲区。

package io.print; import java.io.IOException; import java.io.PrintWriter; //演示PrintStream类的自动刷新功能 public class PrintStreamDemo2 { public static void main(String[] args) { try { //demo1(); demo2(); } catch (IOException e) { e.printStackTrace(); } } private static void demo1() throws IOException { //默许不自动刷新的 PrintWriter out = new PrintWriter(System.out); out.print("Hello World");//不会自动刷新 out.println("Hello World");//不会自动刷新 out.flush();//手动刷新 } private static void demo2() throws IOException { //设置自动刷新的 PrintWriter out = new PrintWriter(System.out,true); out.print("Hello World");//不会自动刷新 out.println("Hello World");//会----由于println()内部调用了out.flush() out.print("Hello3 \n");//不会 out.print("Hello3 \r\n");//不会 out.printf("%s", "Hello4");//会 /*总之: * autoFlush - boolean 变量;如果为 true,则 println、printf 或 format 方法将刷新输出缓冲区。 * ---实际上是由于这几个方法中帮我们调用了out.flush()。 */ } }


IO包中的其他流
★字节数组流
    ByteArrayInputStream与ByteArrayOutputStream

package io.array; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; public class ByteArrayStreamDemo { public static void main(String[] args) { String str ="adhjsdhhsd"; ByteArrayInputStream bis = new ByteArrayInputStream(str.getBytes()); ByteArrayOutputStream bos = new ByteArrayOutputStream(); int ch=0; while( (ch=bis.read())!=⑴ ){ bos.write(ch); } System.out.println(bos.toString()); } }
★字符数组流
    CharArrayReader与CharArrayWriter
★字符串流
    StringReader 与 StringWriter

★序列流

    SequenceInputStream  ——对多个流进行合并

将多个流进行逻辑串连(合并变成1个流,操作起来很方便,由于多个源变成了1个源) 

package io.sequence; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.SequenceInputStream; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; public class SequenceInputStreamDemo { public static void main(String[] args) throws IOException { FileInputStream fin1 = new FileInputStream("files\\seq1.txt"); FileInputStream fin2 = new FileInputStream("files\\seq2.txt"); FileInputStream fin3 = new FileInputStream("files\\seq3.txt"); ArrayList<FileInputStream> v = new ArrayList<FileInputStream>(); v.add(fin1); v.add(fin2); v.add(fin3); Enumeration<FileInputStream> en = Collections.enumeration(v); SequenceInputStream sis = new SequenceInputStream(en); //创建输出流---由于要把前3个文件中的内容读取出来合并到 seq4.txt文件 FileOutputStream fos = new FileOutputStream("files\\seq4.txt"); int len = 0; byte buf[] = new byte[10]; while((len=sis.read(buf))!=⑴){ fos.write(buf, 0, len); } fos.close(); sis.close(); } }


IO流知识点小结

1、知识点

a、流是用来处理数据的。

b、处理数据时,1定要先明确数据源与数据目的地(数据汇)。

c、数据源可以是文件、键盘或其他流。

d、数据目的地可以是文件、显示器或其他流。

e、流只是在帮助数据进行传输,并对传输的数据进行处理,比如过滤处理、转换处理等。

2、IO流体系

使用要点:看顶层(父类共性功能),用底层(子类具体对象)。

命名规律:每一个子类的后缀名都是所属体系的父类的名称,很容易辨别所属的体系。

而且每个子类前缀名都是该子类对象的功能体现。

(掌握IO流体系的要点和规律,开发时设计与查找相应的类就容易多了)


IO流的操作规律

1、明确源和目的。

源:InputStream   Reader 1定是被读取的。

目的:OutputStream  Writer 1定是被写入的。

2、处理的数据是不是是纯文本的数据?

是:使用字符流。Reader Writer

否:使用字节流。 InputStream OutputStream

(到这里,两个明确肯定完,就能够肯定出要使用哪一个体系。接下来,就应当明确具体这个体系要使用哪一个具体的对象。【所谓的看顶层】)

3、明确数据所在的装备。

源装备:

键盘(System.in)  

  硬盘(FileXXX)FileReader FileInputStream 

内存(数组)ByteArrayInputStream CharArrayReader StringReader

网络(Socket)

 目的装备:  

显示器(控制台System.out)

   硬盘(FileXXX)FileWriter FileOutputStream

  内存(数组)ByteArrayOutputStream CharArrayWriter StringWriter

  网络(Socket) 

(到这里,具体使用哪一个对象就能够明确了。【所谓的用底层】)

4、明确是不是需要额外功能?

1) 是不是需要高效?缓冲区Buffered (字符与字节各两个)

2) 是不是需要转换?转换流  InputStreamReader OutputStreamWriter

3) 是不是操作基本数据类型? DataInputStream  DataOutputStream

4) 是不是操作对象(对象序列化)? ObjectInputStream ObjectOutputStream 

5) 需要对多个源合并吗? SequenceInputStream

6) 需要保证数据的表现情势到目的地吗? PrintStream 或 PrintWriter 

(到这里,具体的设计方案就能够明确了。【套接与功能加强】)


IO流的操作规律之设计方案练习

需求1:复制1个文本文件。

1、明确源和目的。

源:InputStream   Reader

目的:OutputStream  Writer

2、处理的数据是不是是纯文本的数据?

源:Reader

目的:Writer

3、明确数据所在的装备。

源:file(硬盘) FileReader fr = new FileReader("a.txt");

目的:file(硬盘) FileWriter fw = new FileWriter("b.txt");

4、明确是不是需要额外功能?

BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));

BufferedWriter bufw = new BufferedWriter(new FileWriter("b.txt"));

需求2:复制1个图片文件。

1、明确源和目的。

源:InputStream   Reader

目的:OutputStream  Writer

2、处理的数据是不是是纯文本的数据?

源:Reader

目的:Writer

3、明确数据所在的装备。

源:file(硬盘) FileReader fr = new FileReader("a.txt");

目的:file(硬盘) FileWriter fw = new FileWriter("b.txt");

4、明确是不是需要额外功能?

BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));

BufferedWriter bufw = new BufferedWriter(new FileWriter("b.txt"));

需求3:读取键盘录入,存储到1个文件中。

1、明确源和目的。

源:InputStream   Reader

目的:OutputStream  Writer

2、处理的数据是不是是纯文本的数据?

源:Reader

目的:Writer

3、明确数据所在的装备。

源:file(硬盘) InputStream in = System.in; 缘由:必须要将键盘录入的字节转成字符。需要将字节-->字符的转换流。InputStreamReader

目的:file(硬盘) FileWriter fw = new FileWriter("b.txt");

4、明确是不是需要额外功能?

InputStreamReader isr = new InputStreamReader(System.in);

FileWriter fw = new FileWriter("a.txt");

高效:BufferedReader bufr = new BufferedReader( isr);

BufferedWriter bufw = new BufferedWriter( fw );

需求4:读取1个文本文件,显示到显示器上。

1、明确源和目的。

源:InputStream   Reader

目的:OutputStream  Writer

2、处理的数据是不是是纯文本的数据?

源:Reader

目的:Writer

3、明确数据所在的装备。

源:file(硬盘) FileReader fr = new FileReader("a.txt");

目的:显示器  OutputStream out = System.out; 缘由:要将字符数据转换成字节输出。输出转换流:OutputStreamWriter

4、明确是不是需要额外功能?

FileReader fr = new FileReader("a.txt");

OutputStreamWriter osw = new OutputStreamWriter(System.out);

高效:BufferedReader bufr = new BufferedReader( fr);

BufferedWriter bufw = new BufferedWriter( osw );

需求5:读取1个文本文件,将文本依照指定的编码表UTF⑻写入到另外一个文件中

1、明确源和目的。

源:InputStream   Reader

目的:OutputStream  Writer

2、处理的数据是不是是纯文本的数据?

源:Reader

目的:Writer

3、明确数据所在的装备。

源:file(硬盘) FileReader fr = new FileReader("a.txt");

目的:file(硬盘) FileOutputStream fout = new FileOutputStream("b.txt")缘由:假定输出时要为字符数据指定编码表。转换流中的参数需要字节流,因此用转换流:FileOutputStream。

4、明确是不是需要额外功能?

FileReader fr = new FileReader("a.txt");

OutputStreamWriter osw = new OutputStreamWriter(fout,”utf⑻”);

高效:BufferedReader bufr = new BufferedReader( fr);

BufferedWriter bufw = new BufferedWriter( osw );



两大例题

文件切割

点击打开链接

字符串截取

点击打开链接



生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠
程序员人生
------分隔线----------------------------
分享到:
------分隔线----------------------------
关闭
程序员人生