使用I/O

1.Java I/O系统是基于类层次结构的;Java定义了两个完整的I/O系统:字节I/O系统和字符I/O系统;字节流为处理字节的输入输出提供了一种便利的方法,如读写二进制数据,字节流在处理文件时也特别有用;字符流是设计用于处理字符的输入输出的,使用Unicode,可以国际化,在某些情况下比字节流效率高
  a.字节流由两个类的层次结构定义,在它们顶端是两个抽象类:InputStream和OutputStream;
  b.字符流由两个类的层次结构定义,其顶端是两个抽象类:Reader和Writer;
  c.预定义流:在Java中,所有的Java程序会自动导入java.lang包,该包定义了一个名为System的类,它封装了运行时环境的几个要素,其中有三个预定义的流变量,分别为in、out和err,这些域在System中声明为public和static,故程序的任何部分都无需引用指定的System对象就可以使用它们。
2.使用字节流:其层次结构的顶端是InputStream和OutputStream类,以下是两者的方法:
 InputStream定义的方法:
  int available() 返回当前可读取的输入字节数
  void close()  关闭输入源,而且任何读取尝试将生成一个IOException
  void mark(int numBytes)  在输入流的当前点放置一个标记,在读取numBytes数量字节之前保持有效
  boolean markSupported()  如果被调用的流支持mark()/reset(),则返回true
  int read() 返回一个整数代表下一个输入的有效字节,返回-1时表示到达文件末尾
  int read(byte buffer[]) 尝试读取buffer.legth数目的字节到缓冲器,并返回实际读取成功的字节数                          。返回-1时表示到达文件末尾
  int read(byte buffer[],int offset,int nmBytes) 尝试读取numBytes数目的字节到缓冲中以buffer                    [offset]开始的位置,并返回实际成功读取的字节数。返回-1表示到达文件末尾
  void reset()  将输入指针重新改为原来设置的标记
  long skip(long numBytes) 忽略(即跳过)numBytes数目的输入字节,返回实际忽略的字节数
 OutputStream定义的方法:
  void close() 关闭输出流,而且任何写尝试将产生一个IOException
  void flush() 完成输出状态,使任何缓冲器清空,即刷新输出缓冲器
  void write(int b) 向输出流写入单个字节,注意若为int类型,它允许使用无需强制转换回byte的表                    达式调用write()
  void write(byte buffer[])  向输出流写入一个完整的字节数组
  void write(byte buffer[],int offset,int numBytes)  从数组的buffer[offset]位置开始写入                                                     numBytes个字节的子区间
总之,两者中的方法都可以根据错误抛出一个IOException,这两个抽象类定义的方法对于它们的所有子类都是有效的。
  a.读取控制台输入:现在可以使用字节流或字符流执行控制台输入;对于商业代码,首选字符流;由于System.in是InputStream的一个实例,故拥有自动调用InputStream定义的方法的权限;从System.in读取字节时,按回车键会产生一个流结束条件。
  b.写入控制台输出:使用print和println可以轻松的完成控制台的输出,这些方法由printStream定义,即使System.out是一个字节流,使用这种流用于简单控制台输出也是可取的;因为PrintStream是一个从OutputStream派生的输出流,所以还执行低级别的方法write(),其最简单形式是void write(int byteval) throws Exception;
  c.使用字节流读写文件:在Java中,所有的文件都是由字节组成的;为创建一个与文件相链接的字节流,需要使用FileInputStream和FileOutputStream;打开文件只需创建这些类的一个对象,将文件名指定为构造函数的一个参数,一旦文件被打开就可以对其进行读取或写入了。
  d.通过创建一个FileInputStream对象可以打开一个用于输入的文件,常用构造函数为FileInputStream(String FileName) throws FileNotFoundException,fileName指定了要打开的文件名称,若给文件不存在,就会抛出一个FileNotFoundException,需要使用read()方法从文件读取,当处理完文件后,应该调用close()来关闭它,其基本形式void close() throws IOException。
  e.通过创建一个FileOutputStream对象可以打开一个用于输出的文件,常用两个构造函数为FileOutputStream(String fileName) throws FileNotFoundException和FileOutputStream(String fileName,boolean append) throws FileNotFoundException,如果无法创建文件就会抛出FileNotFoundException,在第一种形式中,当一个输出文件打开后,以前任何同名的文件都会被销毁;在第二种形式中,如果append为true,那么输出会添加在文件末尾,否则文件会被重写。执行文件输出时,输出会被缓冲,直到有相当大小的数据块可以一次性写入为止,但是如果要不管缓冲区是否已满,都想让数据写入实际的物理设备,可调用flush(),形式为void flush() throws IOException,当文件处理完毕时,同样要用close()关闭它。
3.读写二进制数据:为读写和写入Java原语类型的二进制值,需要使用DataInputStream和DataOutputStream,它们分别实现了DataInput和DataOutput接口,两个接口分别定义了所有Java原语类型读取文件和向文件写入的方法;数据的写入使用的是内部二进制格式,而不是人们可读的文本形式,以下分别为DataOutputStream和DataInputStream定义的常用方法:
 DataOutputStream方法:
   void writeBoolean(boolean var)  写入var指定的boolean类型数据
   void writeByte(int bar)  写入var指定的低阶字节
   void writeChar(int var)  写入var指定为字符的值
   void writeDouble(double var)  写入var指定的double类型数据
   void writeFloat(float var)  写入var指定的float类型数据
   void writeInt(int var)  写入var指定的int类型数据
   void writeLong(long var)  写入var指定的long类型数据
   void writeShort(int var)  写入var指定为short类型的值
 DataInputStream方法:
   void readBoolean()  读取一个boolean类型数据
   void readByte()  读取一个byte类型数据
   void readChar()  读取一个char类型数据
   void readDouble()  读取一个double类型数据
   void readFloat()  读取一个float类型数据
   void readInt()  读取一个int类型数据
   void readLong()  读取一个long类型数据
   void readShort()  读取一个short类型数据
其中OutputStream的构造函数为DataOutputStream(OutputStream outputstream),这里outputStream是写入数据的流,为向文件输出,可以使用FileOutputStream为该参数创建的对象;DataInputStream的构造函数为DataInputStream(InputStream inputStream),这里inputStream是与创建的DataInputStream的实例相连的流,为了从文件读取输入,可以使用FileInputStream为该参数创建的对象。
4.随机访问文件:Java使用封装有随机访问文件的RandomAccessFile来实现随机访问文件,它是由执行定义I/O基本方法的接口DataInput和DataOutput得来的;其构造函数为RandomAccessFile(String fileName,String access) throws FileNotFoundException,这里fileName中存储的是被传递的文件名称,access确定了允许的文件访问类型,访问类型及其含义如下:
   (1)、"r" 以只读方式打开。调用结果对象的任何 write 方法都将导致抛出 IOException。 
   (2)、"rw" 打开以便读取和写入。如果该文件尚不存在,则尝试创建该文件。 
   (3)、"rws" 打开以便读取和写入,对于 "rw",还要求对文件的内容或元数据的每个更新都同步写入到基础存储设备。 
   (4)、"rwd"打开以便读取和写入,对于 "rw"还要求对文件内容的每个更新都同步写入到基础存储设备
 "rws" 和 "rwd" 模式分别传递 true 和 false 参数,除非它们始终应用于每个 I/O 操作,并因此通常更为高效。如果该文件位于本地存储设备上,那么当返回此类的一个方法的调用时,可以保证由该调用对此文件所做的所有更改均被写入该设备。这对确保在系统崩溃时不会丢失重要信息特别有用。如果该文件不在本地设备上,则无法提供这样的保证。"rwd" 模式可用于减少执行的 I/O 操作数量。使用 "rwd" 仅要求更新要写入存储的文件的内容;使用 "rws" 要求更新要写入的文件内容及其元数据,这通常要求至少一个以上的低级别 I/O 操作。 
 另外,RandomAccessFile()还支持定位请求,即可以在文件中定位文件中的指针,这里的seek()方法用于设置文件中文件指针的位置:void seek(long newPos) throws IOExeception,其中newPos指定了以字节计数的从文件开始到文件指针的新位置,在调用seek()后,下一个读写操作将在新的文件位置发生。
5.使用字符流:在字符流层次结构的顶端是抽象类Reader和Writer,以下是两者的定义的方法集合,它们形成了一个所有字符流都应具备的最小I/O功能集合:
 Reader的方法:
   abstract void close() 关闭输入源,而且任何读操作都会产生一个IOException
   void mark(int numChars) 在输入流的当前点放置一个标记,该标记在读取numCharscharacters之前一直保持有效
   boolean markSupported() 如果该流支持mark()/reset(),就返回true
   int read() 从调用输入流返回代表下一个有效字符的整数,当到达文件末尾时返回-1
   int read(char buffer[]) 尝试读取buffer.length个字符到缓冲区,并返回成功读取的实际字符数,当到达文件末尾时,返回-1
   abstract int read(char buffer[],int offset,int numChars) 尝试读取numChars个字符到以buffer[offset]开始的缓冲区,返回成功读取的字符数
   int read(CharBuffer buffer) 尝试填写buffer指定的缓冲区,返还成功读取的字符数,当到达文件末尾时返还-1,CharBuffer是一个封装字符序列(如字符串)的类
   boolean ready() 如果下一个输入请求不等待就返还true,否则返还false
   void reset() 将输入指针重置为前面设定的标记
   long skip(long numChars) 跳过输入的numChars个字符,返回实际跳过的字符数
 Writer定义的方法:
   Writer append(char ch) throws IOException 把ch追加到调用输出流末尾,返还调用输出流的引用
   Writer append(CharSequence chars) throws IOException  把chars追加到调用输出流的末尾,返还调用输出流的引用,CharSequence是一个定义字符序列上的只读操作的接口(以上两个为J2SE 5新增功能)
   Writer append(CharSequence chars,Int begin,int end) throws IOException 把chars的从begin到end之间的字符序列追加到调用输出流的末尾,返还调用输出流的引用(J2SE 5新增功能)
   abstract void close() 关闭输出流,而且任何写操作都会产生一个IOException
   abstract void flush() 结束输出状态,以清除任何缓冲区,即用于刷新输出缓冲区
   void write(int ch) 向调用输出流写入一个字符,要写入的字符包含在给定整数值的 16 个低位中,16 高位被忽略。 注意参数为int型,它使得可以直接用表达式调用write而无需将它们强制转换成char
   void write(char buffer[]) 向调用 输出流写入一个完整的字符数组
   abstract void write(char buffer[].int offset,int numChars) 从数组缓冲区的buffer[offset]开始向输出流写入numCharscharacters的子区间
   void write(String str) 向输出流写入str
   void write(String str,int offset,int numChars) 从指定的位移开始从数组的str写入numCharscharacters的子区间。
  a.基于字符流的控制台输入:由于System.in是一个字节流,故要将System.in包含在某一类型的Reader中,读取控制台最好的类是BufferedReader,它支持缓冲输入流,但不能直接从System.in构造一个BufferedReader,而必须先将其转换为一个字符流,因此要使用InputStreamReader把字节转换为字符;为获得与System.in链接的对象InputStreamReader,使用以下构造函数InputStreamReader(InputStream inputStream),因为System.in引用一个InputStream类型的对象,所有它可以用于inputStream;然后使用下面构造函数产生一个BufferedReader:BufferedReader(Reader inputReader),inputReader是与创建的BufferedReader实例相链接的流,下面代码创建与键盘链接的BufferedReader:BufferedReader br=new BufferedReader(new InputStreamReader(System.in));此后br成为一个通过System.in与控制台链接的字符流。1.读取字符是定义了以下几个版本的read()方法:int read() throws IOException、int read(char[] data) throws IOException、int read(char[] data,int start,int max) throws IOException;当从System.in读取时,按回车键可以产生一个流结束的条件。2.读取字符串时定义了方法String readLine() throws IOException。
  b.基于字符流的控制台输出:Java向控制台写入更好的方法是使用PrintWriter流,PrintWriter是一个字符流,PrintWriter其中一个构造函数是PrintWriter(OutputStream outputStream,boolean flushOnNewline),其中outputStream是一个OutputStream类型对象,flushOnNewline控制Java是否在每次调用println()方法时刷新输出流,若值为true,则自动刷新,否则就不是自动的;另外PrinterWriter支持包括Object在内的所有类型的print()和println()方法,因此可以像System.out与它们一同使用的方法一样来使用这些方法,若一个参数不是原语类型,PrintWriter方法将调用对象的toString()方法,然后打印结果;为使用PrintWriter向控制台写入,为输出流指定System.out,在每一个println()调用之后刷新流。
  c.使用字符流的文件I/O:要执行基于字符的文件I/O,就要使用FileReader和FileWriter类;FileWriter创建一个用于写入文件的Writer,最常用的构造函数为FileWriter(String fileName) throws IOException和FileWriter(String fileName,boolean append) throws IOException,这里fileName是文件的完整路径名,若append为true,那么输出被添加到文件末尾,否则文件被重写,FileWriter是从OutputStreamWriter和Writer派生来的,故它可以使用这些类定义的方法;FileReader类创建了一个可以用于读取文件内容的Reader,最常用的构造函数为FileReader(String fileName) throws IOException,这里fileName是文件的完全路径名,若文件不存在,就会抛出一个FileNotFoundException,FileReader是由InputStreamReader和Reader派生来的,因此可以访问这些类定义的方法。
6.使用Java类型包装器转换数值字符串:在Java中,为了实现在提供读取的同时并将包含数值的字符串转换为内部二进制格式的并行输入功能,需要使用Java的类型包装器;Java的类型包装器是封装或包装了原语类型的类,因为原语类型不是对象,所以需要类型包装器;同时为了不让类型包装器在某种程度上限制原语类型的使用,Java为每个原语类型提供了相应的类,这些类为Double、Float、Long、Integer、Short、Byte、Character和Boolean,它们提供了大量的方法把原语类型整合到Java的对象层次结构中,另一方面,数字包装器还定义了可以把数字字符串转换为对应的二进制值的方法,形同如下:
static double parseDouble(String str) throws NumberFormatException。 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值