异常处理
一、异常处理的概念
1.异常的基本概念:
(1)又称例外,是特殊的运行错误对象
(2)java中声明了很多异常类,每个异常类都代表一种运行错误,类中包含:该运行错误的信息和处理错误的方法
(3)每当java程序发生一个可识别的运行错误时,系统都会产生一个相应的该异常类的对象,即产生一个异常
2.错误、异常的分类
(1)错误的分类:错误和异常
错误:致命性的,程序无法处理,Error类是所有错误类的父类
异常:非致命性的,可编制程序捕获和处理,Exception类是所有异常类的父类
(2)异常的分类:检查性异常和非检查性异常
非检查型异常:不期望程序捕获的异常,在方法中不需要声明,编译器也不进行检查。
例如:ArithmeticException(整数除法中除数为0)、NullPionterException(访问对象还没有实例化)、NegativeArraySizeException(创建数组时元素个数为负数)、ArrayIndexOutOfBoundsException(访问数组元素时,数组下标越界)
检查型异常:若被调用方法抛出一个类型为E检查型异常,则调用者必须捕获或者声明抛出E(或E的父类),对此编译器要检查
例如:ArrayStoreException(程序试图向数组中存取错误类型的数据)、FileNotFoundException(试图存取一个并不存在的文件)、IOException(通常的I/O错误)
二、检查型异常的处理:声明抛出或捕获异常
(1)声明抛出异常:不在当前方法内处理异常,可以使用throws子句声明将异常抛出调用方法,如果所有方法都选择抛出此异常,最后java虚拟机(jvm)将捕获它,输出相关错误信息并终止程序
例如:public static void main(String[] args) throws IOException{….
(2)捕获异常:使用try{}catch(){}块,捕获到所发生的异常,并进行相应处理
捕获异常的语法:
try
{
statement //有可能产生异常的代码块
}
catch(exceptiontype name)
{
statement //异常处理语句
}
finally
{
statement //不管try代码段是否异常,这段代码都会被执行,通常用于释放内存以外的其它资源
}
若并列有多个catch语句捕获多个异常,则特殊的异常放前面,一般的异常放在后面
catch块中通常用到两个方法:
getMessage():返回一个字符串,对异常进行描述
printStackTrace():给出方法的调用序列,一直到异常产生的位置
三、生成异常对象的三种方式:由java虚拟机(jvm)生成、由java类库中的某些类生成、在自己写的程序中生成和抛出异常对象
四、声明自己的异常类
1.自定义的所有异常类必须是Exception类的子类
2.声明语法:
public class 自定义异常名extends 超类名(Exception类或其子类)
{
public 自定义异常名() //自定义异常类的构造方法第一句应先调用超类的构造方法
{
Super(“描述异常信息的字符串“);
}
}
输入输出流的概念
一、预定义I/O流类的划分
1.按方向划分:输入流、输出流
2.按分工划分:
(1)节点流:从数据源读入数据或往目标写出数据
(2)处理流:对数据进行某种处理
3.按内容划分:
Ps:java.io包的顶级层次结构:InputStream类、OutputStream类、Reader类、Writer类。这四个类直接继承自Object类,其中前两个为面向字节的流,后两个为面向字符的流
(1) 字符流:专门用于字符数据,源或目标通常为文本文件,实现内部格式和文本文件中的外部格式之间的转换
面向字符的抽象基类:Reader类和Writer类。这两个类是java.io包中的所有字符流的抽象超类,它们的子类又可分为节点流和处理流两大类
灰色为节点流,白色为处理流
*抽象基类Reader的主要方法有:
①abstract void close():关闭输入流,关闭后读取将会产生IOException异常
②int read() :读取输入流下一个字符,如果调用的输入流的下一个字符可读则返回一个整型,文件尾返回-1
③int read(char buffer[ ]):试图读取buffer中的buffer.length个字符,返回实际成功读取的字符数,文件尾返回-1
④abstract int read (char buffer[ ], intoffset, int numChars):试图读取buffer中从buffer[offset]开始的 numChars个字符,返回实际成功读取的字符数,文件尾返回-1
⑤void mark(int numChars):在输入流的当前位置设立一个标志。该输入流在numChars个字符被读取前有效
⑥void reset():设置输入指针到先前设立的标志处
⑦boolean markSupported():该流支持mark()/reset()则返回true
⑧long skip (long numChars):跳过numChars 个输入字符,返回跳过的字符数
*抽象基类Writer的主要方法有:
①abstract void close():关闭输出流,关闭后的写操作会产生IOException异常
②void write(int ch):向输出流写入单个字符。参数是一个整型,可以不必把参数转换成字符型就可以调用
③void write (char buffer[ ]):向一个输出流写入一个完整的字符数组
④abstract void write (char buffer[ ], intoffset ,int numChars):向调用的输出流写入数组buffer 以buffer[offset]为起点的numChars个字符区域内的内容
⑤void write(String str) :向调用的输出流写str
⑥void write (String str, int offset, intnumChars):写数组str中以制定的offset为起点的长度为numChars个字符区域内的内容
⑦abstract void flush():定制输出状态以使每个缓冲器都被清除,也就是刷新缓冲
(2) 字节流:用于一般目的
面向字节的抽象基类:InputStream和OutputStream ,程序使用这两个类的子类来读写字节信息
灰色为节点流,白色为处理流
*抽象基类InputStream的主要方法有:
①abstract void close():关闭输入流,关闭后读取将会产生IOException异常
②intread():读取一个字节,转换为[0,255]的之间的一个整数,返回一个int。如果读到文件末尾,返回-1
*抽象基类OutputStream的主要方法有:
①abstract void close():关闭输出流,关闭后的写操作会产生IOException异常
②public void write(int b):写一个字节到输出流。要写入的字节是参数b的低八位,计数器增加1
(3)标准输入输出流:System类的静态成员变量,包括:
System.in:InputStream类静态变量,代表标准输入流,默认状态对应为键盘输入
System.out:PrintStream类静态变量,代表标准输出流,默认状态对应为显示器输出
System.err:PrintStream类静态变量,代表标准错误信息输出流,默认状态为显示器输出
按类型输出、输入数据
1.按类型输出数据:printf方法
System.out.printf(“%2d”,l);
2.按类型输入数据:Scanner
Scanner s=new Scanner(System.in);
int n = s.nextInt();
还有下列方法:nextByte()、nextDouble()、nextFloat()、nextInt()、nextLine()、nextLong()、nextShort()
写读文本文件:
一、写文本文件
FileWriter:节点流,创建一个可以写文件的Writer类,继承自Writer抽象类的子类OutputStreamReader
例1:
Import java.io. *
class FileWriterTester
{
public static void main (String[] args)throws IOException //main方法中声明抛出IO异常
{
String filename = “Hello.txt”;
FileWriter writer=new FileWriter(FileName);
writer.write(“Hello!\n”);
writer.close();
}
}
存在问题:1.每次运行都会删除旧文件生成新文件2.\n在不同平台下不一定都表示换行
解决问题1:使用FileWriter writer=newFileWriter(“Hello.txt”,true);如果FileWriter(" ",true);的话表示这个文件不会被重新生成而是会覆盖,而且写入的内容是从这个文件的结尾开始写入
解决问题2:使用处理流BufferedWriter类作为缓冲输出流。BufferWriter作为缓冲输出流能提高写的效率,并且BufferedWriter和FileWriter类包含的方法几乎完全一样,但它比FileWriter多了一个提供换行的方法:newLine()。但应注意,BufferWriter为处理流,应以FileWriter类(节点流)对象作为参数,去构造缓冲的输出流,如下:
例2:
Import java.io. *
class FileWriterTester
{
public static void main (String[] args)throws IOException //main方法中声明抛出IO异常
{
String filename = “newHello.txt”;
BufferedWriter out=new BufferedWriter(new FileWriter(FileName));
out.write(“Hello!”);
out.newLine();
out.close();
}
}
二、读文本文件
FileReader:节点流,创建一个可以从文本文件读取字符的Reader类,继承自Reader抽象类的子类InputStreamReader
BufferedReader:处理流,读文本文件的缓冲器类。具有readLine()方法,可以对换行符进行鉴别,一行一行地读取输入流中的内容,继承自Reader类
例1:
Import java.io. *
class BufferedReaderTester
{
public static void main (String[] args)
{
String filename = “Hello.txt”,line;
Try
{
BufferedReader in=new BufferedReader(new FileReader(filename));
line=in.readLine();
while(line!=null)
{
System.out.println(line);
line=in.readLine();
}
in.close();
}
catch(IOException iox)
{
System.out.println(“Problem reading”+filename;);
}
例2:文件复制
Import java.io.*;
class CopyMaker
{
StringsourceName,destName;
BufferedReadersource;
BufferedWriterdest;
String line;
private booleanopenFiles()
{
try
{
source=new BufferedReaderr(newFileReader(sourceName));
}
catch(IOException iox)
{
System.out.println(“Problemopening”+sourceName));
return false;
}
try
{
dest=newBufferedWriter(new FileWriter(destName));
}
catch(IOException iox)
{
System.out.println(“Problemopening”+destName);
return false;
}
return true;
}
private booleancopyFiles()
{
try
{
line=source.readLine();
while(line!=null)//按行写入
{
dest.write(line);
dest.newLine();
line=source.readLine();
}
}
catch(IOExceptioniox)
{
System.out.println(“Problemreading or writing”);
returnfalse;
}
returntrue;
}
privateboolean closeFiles()
{
boolean retVal=true;
try
{
source.close();
}
catch(IOException iox)
{
System.out.println(“Problemclosing”+sourceName);
retVal=false;
}
try
{
dest.close();
}
catch(IOException iox)
{
System.out.println(“Problem closing”+destName);
retVal=false;
}
return retVal;
}
public Booleancopy(String src,String dst)
{
sourceName=src;
destName=dst;
returnopenFiles()&©Files()&&closeFiles();
}
}
public class FileCopy
{
publicstatic void main(String[] args)
{
if(args.length==2)
new CopyMaker().copy(args[0],args[1]);
else
System.out.println(“PleaseEnter Files names”);
}
}
在命令行方式下执行如下命令:java FileCopy c:/Hello.txtc:/CopyHello.txt,则在C盘根目录下会出现CopyHello.txt文件,内容与Hello.txt完全相同
写读二进制文件:
一、写二进制文件
FileOutputStream:节点流,用于一般目的输出(非字符输出),将数据按成组的字节输出
DataOutputStream:处理流,具有写各种基本数据类型的方法。它在所有计算机平台使用同样的数据格式。其中的Size()方法可作为计数器,统计写入的字节数
BufferedOutputStream:处理流,缓冲流类。可以提高写二进制文件的效率
DataOutputStream类的方法:
public final voidwriteByte(int b):写入一个字节到输出流。要写入的字节是参数b的最低字节(低八位),计数器增加1
public final int size():返回已经写出的字节数
public final void wirteChar(int c):将16-bit字符写入流中,高位在前,计数器增加2
public void writeDouble(double v):写双精度数,计数器增加8
public void writeFloat(float f):写单精度数,计数器增加4
public void writeInt(int i):写整数,计数器增加4
public void writeLong(long l):写长整数,计数器增加8
…
例:
import java.io.*
class FileOutputstreamTester
{
publicstatic void main(String[] args)
{
Stringfilename=”data1.dat”;
intvalue0=255,value1=0,value2=-1;
try
{
DataOutputStream out=new DataOutputStream(newBufferedOutputStream(new FileOutputStream(filename)));
out.writeInt(value0);
out.writeInt(value1);
out.writeInt(value2);
out.close();
}
catch(IOExceptioniox)
{
System.out.println(“Problemwriting”+fileName);
}
}
}
运行程序后会生成数据文件data.dat,用写字板打开它没有任何显示,因为它是二进制文件,应用UltraEdit打开查看二进制信息
FileOutputStream类的构造函数负责打开文件“data1.dat”,用于写数据BufferedOutputStream用于提高写的效率
DataOutputStream使其可以写基本类型数据
二、读二进制文件
同上
FileInputStream:节点流,用于一般目的读取(非字符读取),将数据按成组的字节读取
DataInputStream:处理流,具有读各种基本数据类型的方法。它在所有计算机平台使用同样的数据格式。
BufferedInputStream:处理流,缓冲流类。可以提高读二进制文件的效率
例:读取文件整型数据并相加
怎么判断是否读取到文件末尾?可以利用文件读到末尾会抛出EOFException异常
import java.io.*;
class DataInputStreamTester
{
publicstatic void main (String args[])
{
Stringfilename=”data1.dat”;
longsum=0;
try
{
DataInputStreaminstr = new DataInputStream(new BufferedInputStream(newFileInputStream(filename)));
try //正常情况下,读到文件末尾抛出EOFException异常,以满足需求
{
while(true)
sum+=instr.readInt(); //读的过程可能产生异常
}
catch (EOFException eof)
{
System.out.println(“The sum is”+sum);
instr.close(); //关闭文件有可能产生异常
}
}
catch(IOExceptioniox) //此处用于处理上面的其它异常
{
System.out.println(“IOProblems with”+filename);
}
}
}
例2:用字节流读取文本文件并显示到显示器上
import java.io.*;
public class InputStreamTester
{
publicstatic void main(String[] args)throws IOException
{
FileInputStream s=newFileInputStream(“Hello.txt”);
int c;
while((c =s.read()!=-1)) //读取1字节,返回-1
System.out.write(c);
s.close();
}
}
DataInputStream的方法:
public final int readUnsignedByte():从输入流读取1字节存入int的最低字节(最不重要字节)
例3:文件复制(一个字节一个字节复制):
import java.io.*;
class CopyBytes
{
public static void main (String[]args)
{
DataInputStreaminstr;
DataOutputStreamoustr;
if(args.length!=2)
{
System.out.println(“Pleaseenter file names”);
return;
}
try
{
instr=new DataInputStream(newBufferedInputStream(new FileInputStream(args[0])));
outstr=new DataOutputStream(newBufferedOutputStream(new FileOutputStream(args[1])));
try
{
intdata;
while(true)
{
data=instr.readUnsignedByte();
outstr.writeByte(data);
}
catch(EOFExceptioneof) //到文件结尾抛出EOFException结束复制
{
outstr.close();
instr.close();
return;
}
}
catch(FileNotFoundExceptionnfx) //捕获要被复制的文件找不到的异常
{
System.out.println(“Problemopening files”);
}
catch(IOExceptioniox)
{
System.out.println(“IOProblems”);
}
}
File类
一、File类的作用
1.创建、删除文件
2.重命名文件
3.判断文件的读写权限及是否存在
4.设置和查询文件的最近修改时间
5.构造文件流可以使用File类的对象作为参数
二、File类的方法
1.exists():判断同名文件或路径是否存在
2.delete():删除文件
3.createNewFile():创建一个空文件
4.isFile():判断File对象代表是否是一个文件而非目录(路径),是文件返回true
5.isDirectory():判断File对象代表是否是一个目录而非文件,是目录返回true
6.mkdir():只能创建一级目录,且父目录必须存在,否则无法成功创建一个目录
7.mkdirs():可以创建多级目录,父目录不一定存在
三、实例
例1:创建Hello.txt,如果存在则删除文件,不存在则直接创造新的
import java.io.*}
public class FileTester
{
publicstatic void main(String [] args)
{
Filef=new File(“Hello.txt”);
if(f.exist())
f.delete();
else
try
{
f.createNewFile();
}
catch(Exceptione)
{
System.out,println(e.getMessage());
}
}
}
例2:改进文件复制程序(复制之前先判断一下相关文件名是否已经对应着有文件存在了)import java.io.*;
class NewCopyBytes
{
public static void main (String[]args)
{
DataInputStreaminstr;
DataOutputStreamoustr;
if(args.length!=2)
{
System.out.println(“Pleaseenter file names”);
return;
}
File inFile=newFile(args[0]);
File outFile=newFile(args[1]);
if(outFile.exists()) //判断要赋值的文件名是否有同名文件存在
{
System.out.println(args[1]+”alreadyexists”);
return ;
}
if(!inFile.exists()) //判断要被复制的文件是否存在
{
System.out.println(args[0]+”doesnot exists”);
return;
}
try
{
instr=new DataInputStream(newBufferedInputStream(new FileInputStream(args[0])));
outstr=new DataOutputStream(newBufferedOutputStream(new FileOutputStream(args[1])));
try
{
intdata;
while(true)
{
data=instr.readUnsignedByte();
outstr.writeByte(data);
}
catch(EOFException eof)
{
outstr.close();
instr.close();
return;
}
}
catch(FileNotFoundExceptionnfx)
{
System.out.println(“Problemopening files”);
}
catch(IOExceptioniox)
{
System.out.println(“IOProblems”);
}
}
处理压缩文件:
一、压缩流类
1.GZIPOutputStream和ZipOutputStream:可分别把数据压缩成GZIP格式和Zip格式
2.GZIPInputStream和ZipInputStream:可分别把压缩成GZIP格式或Zip的数据解压缩恢复原状
3.Zip可以压缩多个文件,GZIP仅能对一个文件进行压缩
二、举例
例1:将文本文件“Hello.txt”压缩为GZIP文件”test.gz”,再解压该文件,显示其中内容,并另存为“newHello.txt”
import java.io.*;
import java.util.zip.*;
public class GZIPTester
{
publicstatic void main(String[] args)throws IOException
{
FileInputStream in=newFileInputStream(“Hello.txt”);
GZIPOutputStreamout=new GZIPOutputStream(new FileOutputStream(“test.gz”));
System.out.println(“Writing compressingfile from Hello.txt to test.gz”);
int c;
while((c=in.read())!=-1)
out.write(c);
in.close();
out.close();
System.out.println(“Reading file formtest.gz to monitor”);
BufferedReader in2=new BufferedReader(newInputStreamReader(new GZIPInputStream(new FileInputStream(test.gz)))); //GZIP文件解压缩成二进制文件,再转换为文本文件
String s;
while((s=in2.readLine())!=null) //BufferedReader具有的方法,按行读
System.out.println(s);
in2.close();
System.out.println(“Writing decompressionto newHello.txt”);
GZIPInputStream in3=new GZIPInputStream(newFileInputStream(“test.gz”);
FileOutputStream out2=newFileOutputStream(“newHello.txt”);
while((c=in3.read())!=-1) //用字节流读取文本文件并写入newHello.txt
out2.write(c);
in3.close();
out2.close();
}
}
InputStreamReader:字符流Reader的子类,是字节流与字符流之间的桥梁,能将字节流输出为字符流
例2:从命令行输入若干个文件名,将所有文件压缩为Zip文件“test.zip”,再从此压缩文件中解压并显示,不另存
import java.io.*;
import java.util.*;
import java.util.zip.*;
public class ZipOutputStreamTester
{
publicstatic void main(String[] args) throws IOException
{
ZipOutputStream out=new ZipOutputStream(newBufferedOutputStream(new FileOutputStream(“test.zip”)));
}
for(inti=0;i
{
System.out.println(“Writing file”+args[i]);
BufferedInputStream in=new BufferedInputStream(newFileInputStream(args[i]));
out.putNextEntry(new ZipEntry(args[i])); //表示创建压缩的子目录,ZipEntry表示ZIP文件条目
intc;
while((c=in.read())!=-1)
out.write(c); //压缩
in.close();
}
out.close();
System.out.println(“Readingfile”);
ZipInputStream in2=new ZipInputStream(new BufferedInputStream(newFileInputStream(“test.zip”));
ZipEntryze;
while((ze=in2.getNextEntry())!=null) //getNextEntry()读取下一个Zip文件条目
{
System.out.println(“Readingfile”+ze.getName()); //获得当前文件条目名
intx;
while((x=in2.read())!=-1) //在屏幕显示
System.out.write(x);
System.out.println(); //换行
}
in2.close();
}
例3:解压缩Zip文件,并恢复原来路径
import java.util.*;
import java.util.zip.*;
import java.lang.*;
import java.io.*;
class Unzip
{
bytedoc[]=null; //存储解压缩数据的缓冲字节数组
StringFilename=null; //压缩文件名
StringUnZipPath=null; //解压缩路径
publicUnzip(String filename,String unZipPath)
{
this.Filename=filename;
this.UnZipPath=unZipPath;
this.setUnZipPath(this.UnZipPath);
}
publicUnzip(String filename)
{
this.Filename=new String(filename);
this.UnZipPath=null;
this.setUnZipPath(this.UnZipPath);
}
privatevoid setUnZipPath(String unZipPath)
{
if(unZipPath.endsWith(“\\”)); //String类的endsWith(String x)表示该字符串是否与指定的后缀x为结尾
this.UnZipPath=newString(unZipPath);
else //结尾统一加\
this.UnZipPath=newString(unZipPath+”\\”);
}
publicvoid doUnZip()
{
try
{
ZipInputStream zipis=new ZipInputStream(newFileInputStream(Filename));
ZipEntry fEntry=null;
while((fEntry=zipis.getNextEntry()!=null)
{
if(fEntry.isDirectory()) //判断是否是目录(路径)
checkFilePath(UnZipPath+fEntry.getName());
else
{
Stringfname=new String(UnZipPath+fEntry.getName());
try
{
FileOutputStream out=new FileOutputStream(fname);
doc=newbyte[512];
intn;
while((n=zipis.read(doc,0,512))!=-1) //512个字节一起读
out.write(doc,0,n);
out.close();
out=null;
doc=null;
}
catch(Exceptionex)
{}
}
}
zipis.close();
}
catch(IOExceptionioe)
{
System.out.println(ioe);
}
}
privatevoid checkFilePath(String dirName) throws IOException
{
Filedir=new File(dirName);
if(!dir.exists()) //判断同名文件或目录是否存在
dir.mkdirs(); //创建目录(路径)
}
}
public class UnZipTester
{
publicstatic void main(String[] args)
{
String zipFile=args[0]; //第一个参数为zip文件名
String unZipPath=args[1]+”\\”; //第二个参数为指定解压缩路径
UnzipmyZip=new Unzip(zipFile,unZipPath);
myZip.doUnZip();
}
}
对象序列化
一、实现对象的读写
1.ObjectOutputStream:把对象写入磁盘文件
2.ObjectInputStream:把对象读入文件
3.不保存对象的transient和static类型变量
4.对象要想实现序列化,其所属的类必须实现Seralizable接口
二、ObjectOutputStream:处理流,写入
例:
FileOutputStream out=newFileOutputStream(“theTime”);
ObjectOutputStream s=newObjectOutputStream(out);
s.writeObject(“Today”); //把String对象“Today”存入文件
s.writeObject(newData()); //构造一个日期对象Data,存入文件
s.flush(); //清空缓冲区
writeObject():将对象存入文件
二、ObjectInputStream:处理流,读入
例:
FileInputStream in=newFileInputStream(“theTime”);
ObjectInputStream s=newObjectInputStream(in);
String today=(String)s.readObject();
Data date=(Data)s.readObject();
(Type)object.readObject():将Type类型对象读取出来
三、Serializable接口
1.Serializable接口其实是一个空接口,只是一个标记,但若想对象序列化则必须声明
package java.io;
public interface Serializable
{
//there’snothing there!
}
2.Serializable接口的声明语句:
public class 类名 implements Serializable
{
…
}
3.使用关键字transient可以组织对象的某些成员(变量)被自动写入文件
4.例:创建一个书籍对象,输出到一个文件book.dat,再把对象读出来,在屏幕显示
class Book implementsSerializable
{
intid;
Stringname;
Stringauthor;
floatprice;
publicBook(int id,String name,String author,float price)
{
this.id=id;
this.name=name;
this.author=author;
this.price=price;
}
}
import java.io.*;
public class SerializableTester
{
publicstatic void main(String args[]) throws IOException,ClassNotFoundException
{
Book book=new Book(100032,”JavaProgramming Skills”,”Wang Sir”,30);
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(“book.dat”));
oos.writeObject(book);
oos.close();
book=null;
ObjectInputStreamois=new ObjectInputStream(new FileInputStream(“book.dat“));
book=(Book)ois.readObject();
ois.close();
System.out.println(“IDis”+book.id);
System.out.println(“nameis”+book.name);
System.out.println(“authoris”+book.author);
System.out.println(“priceis”+book.price);
}
}
四、Externalizable接口(自定义对象序列化)
1.Externalizable接口继承自Serializable接口
2.必须实现两个方法writeExternal()和readExternal(),如果写和读对象,自己定制
3.将对象写入文件和从文件读取对象,使用的还是writeObject()和readObject(),它们再负责调用writeExternal()和readExternal()
随机文件读写
一、RandomAccessFile类
1.可跳转文件的任意位置读/写数据
2.可在随机文件中插入数据而不破坏文件的其他数据
3.实现DataInput和DataOutput接口,可使用普通的读写方法
4.有一个位置指示器,指向当前读写处的位置。刚打开文件时,文件指示器指向文件开头处,对文件指示器的操作方法有:
(1)publicint skipBytes(int n):把文件指针向前移动指定的n个字节
(2)publicvoid seek(long):移动文件指针到指定的位置
(3)publiclong getFilePointer():得到当前的文件指针
5.在等长记录的格式文件的随机读取时有很大优势
二、RandomAccessFile的构造方法
1.构造方法:
public RandomAccessFile(Filefile,String mode) throws FileNotFoundException
publicRandomAccessFile(String name,String mode) throws FileNotFoundException
2.构造RandomAccessFile对象,要指出操作:仅读or读写
仅读:RandomAccessFiler=new RandomAccessFile(“farrago.txt”,”r”);
读写:RandomAccessFiler=new RandomAccessFile(“farrago.txt”,”rw”);
三、RandomAccessFile类的方法
四、例:创建一个雇员类,包括姓名、年龄。姓名不超过8个字符,年龄是int类型。每条记录固定为20个字节(8*2+4)。使用RandomAccessFile向文件添加、修改、读取雇员信息
importjava.io.*;
classEmployee
{
char name[]={‘\u0000’,’\u0000’, ’\u0000’,’\u0000’, ’\u0000’, ’\u0000’, ’\u0000’, ’\u0000’};
//‘\u0000‘表示null,‘\uXXXX‘是unicode编码,XXXX为四位十六进制数
int age;
public Employee(String name,int age)throws Exception
{
if(name.toCharArray().length>8)
System.arraycopy(name.toCharArray(),0,this.name,0,8);
else
{
System.arraycopy(name.toCharArray(),0,this.name,0,name.toCharArray().length);
this.age=age; //toCharArray():将String转化成char[ ]
}
}
}
publicclass RandomAccessFileTester
{
String Filename;
public RandomAccessFileTester(StringFilename)
{
this.Filename=Filename;
}
public void writeEmployee(Employee e,intn) throws Exception
{
RandomAccessFile ra=newRandomAccessFile(Filename,”rw”);
ra.seek(n*20); //移动位置指示器到指定位置
for(int i=0;i<8;i++)
ra.writeChar(e.name[i]);
ra.writeInt(e.age);
ra.close();
}
public void readEmployee(int n) throwsException
{
char buf[]=new char[8];
RandomAccessFile ra=newRandomAccessFile(Filename,”r”);
ra.seek(n*20);
for(int i=0;i<8;i++)
buf[i]=ra.readChar();
System.out.print(“name:”); //print不带换行,println带换行
System.out.println(buf);
System.out.println(“age:”+ra.readInt());
ra.close();
}
public static void main(String[] args)
{
RandomAccessFileTestert=new RandomAccessFileTester(“Temp/1.txt”);
Employee e1=newEmployee(“ZhangSantt”,23);
Employee e2=new Employee(“李晓珊”,33);
Employee e3=newEmployee(“王华”,19);
t.writeEmployee(e1,0);
t.writeEmployee(e3,2);
System.out.println(“第一个雇员信息:”);
t.readEmployee(0);
System.out.println(“第三个雇员信息:”);
t.readEmployee(2);
t.writeEmployee(e2,1);
System.out.println(“第二个雇员信息:”);
t.readEmployee(1);
}