第5章 输入输出

异常处理

一、异常处理的概念

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包中的所有字符流的抽象超类,它们的子类又可分为节点流和处理流两大类

第5章 输入输出_第1张图片

灰色为节点流,白色为处理流

*抽象基类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 ,程序使用这两个类的子类来读写字节信息

第5章 输入输出_第2张图片

灰色为节点流,白色为处理流

*抽象基类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);

}

}
第5章 输入输出_第3张图片

 

JAVA I/O流结构图
第5章 输入输出_第4张图片

你可能感兴趣的:(Java)