java 流与文件

来源:互联网 发布:我的世界租服务器淘宝 编辑:程序博客网 时间:2024/05/01 22:32
在java API当中,可以从其中读入一个字节序列的对象称作输入流,而可以向其中写入一个字节序列的对象称作输出流。形象的描述就是你从外部文件中的内容读取到java程序中的是输入流,从java程序到外部文件中的是输出流。

在输入输出流使用的时候,要在使用完毕的时候进行关闭,因为输入输出流占用系统的一定的资源。java的输入输出流有两种职责,一种是从文件和其他更外部的位置获取字节,另一种是将字节组装到更有用的数据类型中。例如:
FileInputStream fin=new FileInputStream("a.txt");
DataInputStream din=new DataInputStream(fin);
double s=din.readDouble();

为了更方便的控制输入输出流,可以在输入输出流中加入过滤功能。加入的位置如下所示:
FileInputStream fin=new FileInputStream("a.txt");
BufferedInputStream bis=new BufferedInputStream(fin);
DataInputStream din=new DataInputStream(bis);
double s=din.readDouble();
假如要读取ZIP文件,可以使用如下方法:
FileInputStream fin=new FileInputStream("a.txt");
ZipInputStream zis=new ZipInputStream(fin);
DataInputStream din=new DataInputStream(zis);

从上面的例子中可以分析出输入流的过滤序列。
下面是一段输入输出流的代码赏析:
第一段,数据单元的实体Bean,含有一些输入输出操作方法:
package stream;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Scanner;

public class Employee {
public static final int NAME_SIZE=40;
public static final int RECORD_SIZE=2*NAME_SIZE+8+4+4+4;
    private String name;
    private Double salary;
    private Date hireDay;
    
public Employee(){
}
public Employee(String n,double s,int year,int month,int day){
name=n;
salary=s;
GregorianCalendar calendar=new GregorianCalendar(year, month-1, day);
hireDay=calendar.getTime();
}

public String getName() {
return name;
}

public Double getSalary() {
return salary;
}

public Date getHireDay() {
return hireDay;
}
public void raiseSalary(double percent){
salary+=salary*percent/100;
}
public String toString(){
return getClass().getName()+"[name="+name+",salary="+salary+",hireDay="
+hireDay+"]";
}
public void writeData(PrintWriter out){
  GregorianCalendar calendar=new GregorianCalendar();
  calendar.setTime(hireDay);
  out.println(name+"|"+salary+"|"+calendar.get(Calendar.YEAR)+"|"
+(calendar.get(Calendar.MONTH)+1)+"|"+calendar.get(Calendar.DAY_OF_MONTH));
}
public void readData(Scanner in){
String line=in.nextLine();
String[] tokens=line.split("\\|");
name=tokens[0];
salary=Double.parseDouble(tokens[1]);
int y=Integer.parseInt(tokens[2]);
int m=Integer.parseInt(tokens[3]);
int d=Integer.parseInt(tokens[4]);
GregorianCalendar calendar=new GregorianCalendar(y, m-1,d);
hireDay=calendar.getTime();
}
public void writeData(DataOutput out) throws IOException{
DataIO.writeFixedString(name, NAME_SIZE, out);
out.writeDouble(salary);
GregorianCalendar calendar=new GregorianCalendar();
calendar.setTime(hireDay);
out.writeInt(calendar.get(Calendar.YEAR));
out.writeInt(calendar.get(Calendar.MONTH)+1);
out.writeInt(calendar.get(Calendar.DAY_OF_MONTH));
}
public void readData(DataInput in) throws IOException{
name=DataIO.readFixedString(NAME_SIZE, in);
salary=in.readDouble();
int y=in.readInt();
int m=in.readInt();
int d=in.readInt();
GregorianCalendar calendar=new GregorianCalendar(y, m-1, d);
hireDay=calendar.getTime();
}
}

DataIO这个类里面包含了读写固定长度的数据单元
package stream;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

public class DataIO {
    public static String readFixedString(int size,DataInput in)throws IOException{
     StringBuilder b=new StringBuilder(size);
     int i=0;
     boolean more=true;
     while(more&i<size){
     char ch=in.readChar();
     i++;
     if(ch==0)more=false;
     else b.append(ch);
     }
     in.skipBytes(2*(size-i));
     return b.toString();
    }
    
    public static void writeFixedString(String s,int size,DataOutput out) throws IOException{
     for(int i=0;i<size;i++){
     char ch=0;
     if(i<s.length())ch=s.charAt(i);
     out.writeChar(ch);
     }
    }
}

下面是两种输入数出流的运用:
1.文本输入输出流:
package stream;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Scanner;

public class TextFileTest {
   
private static Employee[] readData(Scanner in){
int n=in.nextInt();
in.nextLine();
Employee[] employees=new Employee[n];
for(int i=0;i<n;i++){
employees[i]=new Employee();
employees[i].readData(in);
}
return employees;
}
private static void writeData(Employee[] employees,PrintWriter out)throws IOException{
out.println(employees.length);
for(Employee e:employees){
e.writeData(out);
}
}
public static void main(String[]args){
Employee[] staff=new Employee[3];
staff[0]=new Employee("Carl Cracker",7500,1987,12,15);
staff[1]=new Employee("Harry Hacker",5000,1989,10,1);
staff[2]=new Employee("Tony Tester",4000,1990,3,15);
try {
PrintWriter out=new PrintWriter("employee.dat");
writeData(staff,out);
out.close();
Scanner in=new Scanner(new FileReader("employee.dat"));
Employee[] newstaff=readData(in);
in.close();
for(Employee e:newstaff){
System.out.println(e);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

2.RandomFile方式的
package stream;

import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;

public class RandomFileTest {

public static void main(String[]args){
Employee[] staff=new Employee[3];
staff[0]=new Employee("Carl Cracker",7500,1987,12,15);
staff[1]=new Employee("Harry Hacker",5000,1989,10,1);
staff[2]=new Employee("Tony Tester",4000,1990,3,15);
try {
DataOutputStream out=new DataOutputStream(new FileOutputStream("employee.dat"));
for(Employee e:staff)e.writeData(out);
out.close();
RandomAccessFile in=new RandomAccessFile("employee.dat", "r");
int n=(int) (in.length()/Employee.RECORD_SIZE);
Employee[] newstaff=new Employee[n];
for(int i=n-1;i>=0;i--){
newstaff[i]=new Employee();
in.seek(i*Employee.RECORD_SIZE);
newstaff[i].readData(in);
}
in.close();
for(Employee e:newstaff){
System.out.println(e);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

分别运行这两种输入数流,可以很轻松的发现它们产生文件内容的区别 



原创粉丝点击