JavaIO加强(1)

首先对java中的IO作一个复习:

Java中IO流根据流的方向,流可分为两类:输入流和输出流。

   输入流和输出流又可分为:

       字节流:InputStream(输入)OutputStream(输出

       字符流:Reader (输入) Writer(输出

一个简单的对文件实行读写:

<span style="font-family:Times New Roman;font-size:14px;color:#000000;">package cn.huncu.io.hello;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class Demo1 {

	public static void main(String[] args) {
		//writeDemo();
		readDemo();
	}

	private static void readDemo() {
		File file =new File("files\\a.txt");
		if(!file.exists()){
			System.out.println("文件不存在");
			return ;
		}
		FileInputStream in=null;
		byte[] b=new byte[512];
		try {
			in=new FileInputStream(file);
			in.read(b);
//				for(byte bb:b){这种方式,遇到中文会乱码
//					System.out.print((char)b);
//				}System.out.println();
			String str=new String(b, "utf-8");//解码--指定编码表
			System.out.println(str);
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if(in!=null){
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public static void writeDemo() {
		FileOutputStream out=null;
		String str="你好啊,你叫什么名字? ";
		try {
			out=new FileOutputStream("files/a.txt");
			out.write(str.getBytes("utf-8"));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if(out!=null){
				try {
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

}
</span>


 

                                      RandomAccessFile
    ★随机访问文件,自身具备读写的方法。
        new RandomAccessFile()之后,若文件不存在会自动创建,存在则不创建。——该类其实内部既封装了字节输入流,又封装了字节输出流。
该类若用write()方法写整数,每次只写它的最后一个字节。而采用writeInt()方法,则可把一个整数完整地写入。
   ★通过skipBytes(int x),seek(int x)来达到随机访问。
       通过seek方法设置数据的指针就可以实现对文件数据的随机读写。InputStream中的skip()方法只能从头往后跳,不能反向;而seek()方法可双向随便定位。
   ★数据修改方面的特点
      用RandomAccessFile类可以实现数据的修改,当然文件中的数据一般要有规律,以方 便在编程时能够进行定位,让数据写对地方。
而用“流”实现数据修改时,则通常需要把数据从流读到数组当中,在数组中进行数据修改,然后再把修改后的数组再重新写到流中。

 


    ★ 序列化
        将一个对象存放到某种类型的永久存储器上称为保持。如果一个对象可以被存放到磁盘或磁带上,或者可以发送到另外一台机器并存放到存储器或磁盘上,那么这个对象就被称为可保持的。(在Java中,序列化、持久化、串行化是一个概念。)
        java.io.Serializable接口没有任何方法,它只作为一个“标记者”,用来表明实现了这个接口的类可以考虑串行化。类中没有实现Serializable的对象不能保存或恢复它们的状态。
   ★ 对象图
       当一个对象被串行化时,只有对象的数据被保存;方法和构造函数不属于串行化流。如果一个数据变量是一个对象,那么这个对象的数据成员也会被串行化。树或者对象数据的结构,包括这些子对象,构成了对象图。
   ★ 瞬时 transient
        防止对象的属性被序列化。
序列化和transient演示:

<span style="font-family:Times New Roman;font-size:14px;color:#000000;">package cn.hncu.io.serial;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class SerializableDemo {

	public static void main(String[] args) throws Exception{
		//writeDemo();
		writeDemo2();
		readDemo();
	}
	private static void readDemo() throws Exception{
		ObjectInputStream in = new ObjectInputStream( new FileInputStream("files/persons.txt"));
		//while(in.available()>0){//对象流不能以这种方式来判断是否有数据
		while(true){//对象流的读取,应该用处理异常的方式来判断文件结束
			try {
				Person p = (Person) in.readObject();//到达文件结束,会抛异常
				System.out.println(p);
			} catch (Exception e) {
				System.out.println("文件读取完毕!");
				break;
			}
		}
		
	}

	private static void writeDemo() throws IOException, FileNotFoundException {
		//序列化
		ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("files/persons.txt"));
		out.writeObject( new Person("Jack",24) );
		out.writeObject( new Person("张三",23) );
		out.writeObject( new Person("Rose",25) );
	}
	
	private static void writeDemo2() throws IOException, FileNotFoundException {
		//序列化
		ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("files/persons.txt"));
		out.writeObject( new Person("Jack",24,new MyDate(1995, 1, 1)) );
		out.writeObject( new Person("张三",23,new MyDate(1993, 10, 1)) );
		out.writeObject( new Person("Rose",25,new MyDate(1992, 1, 21)) );
	}

}</span>
<span style="font-family:Times New Roman;font-size:14px;color:#000000;">
</span>

Person类:

<span style="font-family:Times New Roman;font-size:14px;color:#000000;">package cn.hncu.io.serial;

import java.io.Serializable;

public class Person implements Serializable{
	private static final long serialVersionUID = -8696927766135529411L;
	private String name;
	private int age;
	private transient int num; //瞬时变量,不会序列化---如果不想让一个非静态变量序列化,那么就把它定义成瞬时变量
	private static int count=0; //※静态变量是无法序列化
	private MyDate birth;
	
	public Person() {
		num = ++count;
	}

	public Person(String name, int age) {
		this();
		this.name = name;
		this.age = age;
	}

	public Person(String name, int age, MyDate birth) {
		super();
		this.name = name;
		this.age = age;
		this.birth = birth;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public MyDate getBirth() {
		return birth;
	}

	public void setBirth(MyDate birth) {
		this.birth = birth;
	}

	@Override
	public String toString() {
		//return count+":"+name + ", " + age ;
		return num+":"+name + ", " + age +", "+birth;
	}

}
</span>


MyDate类:

<span style="font-family:Times New Roman;font-size:14px;color:#000000;">package cn.hncu.io.serial;

import java.io.Serializable;

public class MyDate implements Serializable{
	private int year, month, day;

	public MyDate() {
		super();
	}

	public MyDate(int year, int month, int day) {
		super();
		this.year = year;
		this.month = month;
		this.day = day;
	}

	public int getYear() {
		return year;
	}

	public void setYear(int year) {
		this.year = year;
	}

	public int getMonth() {
		return month;
	}

	public void setMonth(int month) {
		this.month = month;
	}

	public int getDay() {
		return day;
	}

	public void setDay(int day) {
		this.day = day;
	}

	@Override
	public String toString() {
		return year + "年" + month + "月" + day + "日";
	}

}
</span>

 

注意:ObjectOutputStream类的write(Object obj)不会写静态成员(数据),即非静态数据都会写入对象流中,而如果非静态数据中有部分不想被写入对象流,这时需把定义成瞬时成员变量,如:private transient int age;(该瞬时数据将不被写入对象流中)

       用ObjectOutputStream类的write(Object obj)进行写对象时,其中的参数对象的类必须实现Serializable接口。(把光标定位在类名上,利用“Ctlr+1”,可自动为需序列化的类显式定义SerialVersionID,若自己未显式定义序列化ID,则会默认自动生成一个。 )

缓冲输入输出流

(BufferedInputStream和BufferedOutputStream)

方式一:  DataInputStream in = new DataInputStream(

                                            newBufferedInputStream(

                                                        new FileInputStream("Test.txt")   );

方式二:DataInputStream in = new DataInputStream(

                                                                 new FileInputStream("Test.txt")   );

方式三:BufferedInputStream in = new BufferedInputStream(

                                                       new DataInputStream(

                                                           new FileInputStream("Test.java")  );

在这里我们将对这三种方式读取速度做一个比较,看看哪种方法效率。

代码实现如下:

<span style="font-family:Times New Roman;font-size:14px;color:#000000;">package cn.huncu.io.buffer;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class BufferedStreamDemo {
	private static String FILE_NAME="files/buf.txt";
	public static void main(String[] args) {
		try {
			//demo1();
			//demo2();
			demo3();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	private static void demo3() throws IOException {
		long t1=System.currentTimeMillis();
		BufferedInputStream in=new BufferedInputStream(new DataInputStream(new FileInputStream(FILE_NAME)));
		String str=null;
		//in.readl
		byte[] b=new byte[50];
		int len=0;
		while((len=in.read(b))!=-1){
			System.out.print(new String(b,0,len));
		};
		System.out.println();
		long t2=System.currentTimeMillis();
		System.out.println("程序运行时间为(毫秒):"+(t2-t1));
	}

	
	private static void demo2() throws IOException {
		long t1=System.currentTimeMillis();
		DataInputStream in=new DataInputStream(new FileInputStream(FILE_NAME));
		String str=null;
		//in.readl
		
		while((str=in.readLine())!=null){
			System.out.println(str);
		}
		System.out.println();
		long t2=System.currentTimeMillis();
		System.out.println("程序运行时间为(毫秒):"+(t2-t1));
	}

	
	private static void demo1() throws IOException {
		long t1=System.currentTimeMillis();
		DataInputStream in=new DataInputStream(new BufferedInputStream(new FileInputStream(FILE_NAME)));
		String str=null;
		//in.readl
		while((str=in.readLine())!=null){
			System.out.println(str);
		}
		System.out.println();
		long t2=System.currentTimeMillis();
		System.out.println("程序运行时间为(毫秒):"+(t2-t1));
	}

}
</span>

 

为了保证数据的有效性,我做了多次测试。

第一种方式结果如图:

第二种方式:

第三种方式

小结:

方式一是最优的。

1)有buffer比没有更快;

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

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

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


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值