欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java IO流简介

程序员文章站 2024-03-12 12:34:08
...

I/O流概述

输入/输出处理是程序设计中非常重要的一部分,比如从键盘读取数据,从文件中读取数据或者向文件中写入数据等等.
Java把这些不同类型的输入,输出源抽象为流(stream),用统一的接口来表示,从而使程序简单明了.
JDK提供了包java.io,其中包括一些列的类来实现输入/输出处理.下面是对java.io包的概要介绍:

I/O流的层次

字节流:

从InputStream和OutputStream派生出来的一系列类。这类流以字节(byte)为基本处理单位。
  ◇ InputStream、OutputStream
  ◇ FileInputStream、FileOutputStream
  ◇ PipedInputStream、PipedOutputStream
  ◇ ByteArrayInputStream、ByteArrayOutputStream
  ◇ FilterInputStream、FilterOutputStream
  ◇ DataInputStream、DataOutputStream
  ◇ BufferedInputStream、BufferedOutputStream

字符流:

从Reader和Writer派生出的一系列类,这类流以16位的Unicode码表示的字符为基本处理单位。
  ◇ Reader、Writer
  ◇ InputStreamReader、OutputStreamWriter
  ◇ FileReader、FileWriter
  ◇ CharArrayReader、CharArrayWriter
  ◇ PipedReader、PipedWriter
  ◇ FilterReader、FilterWriter
  ◇ BufferedReader、BufferedWriter
  ◇ StringReader、StringWriter

对象流

◇ ObjectInputStream、ObjectOutputStream

其它

◇ 文件处理:
  File、RandomAccessFile;
  ◇ 接口
  DataInput、DataOutput、ObjectInput、ObjectOutput;

为什么要有字符流

为了防止乱码 
java IO流简介

字节流和字符流的区别

字节流可以处理任意类型的数据,比如文本,图片,视频等类型的数据
字符流只能处理纯文本数据。
总结:如果你要处理的数据是纯文本优先考虑使用字符流,其他情况统一使用字节流

File文件处理

我们使用IO流来操作数据,数据最常见的体现方式就是文件,通过Java面向对象的思想来分析,文件都有自己的一些特性,比如文件可以创建,删除,修改,查看,文件有名字,路径,类型等行为和属性。于是将文件也封装成了对象,该类就是File。

下面是类File中提供的各种方法。

文件或目录的生成

public File(String path);/*如果path是实际存在的路径,则该File对象
     *表示的是目录;如果path是文件名,则该File
     对象表示的是文件。/
  public File(String path,String name);//path是路径名,name是文件名
  public File(File dir,String name);//dir是路径名,name是文件名

文件名的处理

String getName( ); //得到一个文件的名称(不包括路径)
  String getPath( ); //得到一个文件的路径名
  String getAbsolutePath( );//得到一个文件的绝对路径名
  String getParent( ); //得到一个文件的上一级目录名
  String renameTo(File newName); //将当前文件名更名为给定文件的
                   完整路径

文件属性测试

boolean exists( ); //测试当前File对象所指示的文件是否存在
  boolean canWrite( );//测试当前文件是否可写
  boolean canRead( );//测试当前文件是否可读
  boolean isFile( ); //测试当前文件是否是文件(不是目录)
  boolean isDirectory( ); //测试当前文件是否是目录

普通文件信息和工具

long lastModified( );//得到文件最近一次修改的时间
  long length( ); //得到文件的长度,以字节为单位
  boolean delete( ); //删除当前文件

目录操作

boolean mkdir( ); //根据当前对象生成一个由该对象指定的路径
  String list( ); //列出当前目录下的文件

I/O流的使用

InputStream 和OutputStream

InputStream

◇ 从流中读取数据:
  int read( ); //读取一个字节,返回值为所读的字节
  int read( byte b[ ] ); //读取多个字节,放置到字节数组b中,通常
              //读取的字节数量为b的长度,返回值为实际
              //读取的字节的数量
  int read( byte b[ ], int off, int len ); //读取len个字节,放置
                       //到以下标off开始字节
                       //数组b中,返回值为实
                       //际读取的字节的数量
  int available( );   //返回值为流中尚未读取的字节的数量
  long skip( long n ); //读指针跳过n个字节不读,返回值为实际
             //跳过的字节数量

◇ 关闭流:
  close( ); //流操作完毕后必须关闭
  
  ◇ 使用输入流中的标记:
  void mark( int readlimit ); //记录当前读指针所在位置,readlimit
                 //表示读指针读出readlimit个字节后
                //所标记的指针位置才失效
  void reset( );     //把读指针重新指向用mark方法所记录的位置
  boolean markSupported( ); //当前的流是否支持读指针的记录功能

有关每个方法的使用,详见java API。

OutputStream

◇ 输出数据:
  void write( int b );   //往流中写一个字节b
  void write( byte b[ ] ); //往流中写一个字节数组b
  void write( byte b[ ], int off, int len ); //把字节数组b中从
              //下标off开始,长度为len的字节写入流中

◇ flush( )       //刷空输出流,并输出所有被缓存的字节
  由于某些流支持缓存功能,该方法将把缓存中所有内容强制输出到流中。

◇ 关闭流:
   close( );       //流操作完毕后必须关闭
注意:
1)中文乱码:这里需要设置编码表
原因:将文字转换成字节,需要根据码表转换,这个过程是编码,使用的时候需要将字节转换成文字,这个叫解码,如果两个过程使用的码表不一样就会乱码。
String str = new String(b,“GBK”);
2)用输出流写入数据时,关于最后一个字节数组没有全部占满,其余部分用0填充的问题:我们可以在写的时候规定读多少字节写入多少字节即可,如下图:
java IO流简介

缓冲流

为了提高对数据的读写效率我们可以使用缓冲技术,Java给我们提供了两个类BufferedInputStreamBufferedOutputStream,这两个类是基于装饰模式实现,我们在使用的时候传入普通的字节流即可。
如图:
java IO流简介

字符流的处理

java中提供了处理以16位的Unicode码表示的字符流的类,即以Reader和Writer 为基类派生出的一系列类。

Reader和Writer

这两个类是抽象类,只是提供了一系列用于字符流处理的接口,不能生成这两个类的实例,只能通过使用由它们派生出来的子类对象来处理字符流。

#####Reader类是处理所有字符流输入类的父类。

◇ 读取字符
  public int read() throws IOException; //读取一个字符,返回值为读取的字符
  public int read(char cbuf[]) throws IOException; /读取一系列字符到数组cbuf[]中,返回值为实际读取的字符的数量/
  public abstract int read(char cbuf[],int off,int len) throws IOException;
  /读取len个字符,从数组cbuf[]的下标off处开始存放,返回值为实际读取的字符数量,该方法必须由子类实现/

◇ 标记流
  public boolean markSupported(); //判断当前流是否支持做标记
  public void mark(int readAheadLimit) throws IOException;
   //给当前流作标记,最多支持readAheadLimit个字符的回溯。
  public void reset() throws IOException; //将当前流重置到做标记处

◇ 关闭流
  public abstract void close() throws IOException;

##### Writer类是处理所有字符流输出类的父类。

◇ 向输出流写入字符
  public void write(int c) throws IOException;
  //将整型值c的低16位写入输出流
  public void write(char cbuf[]) throws IOException;
  //将字符数组cbuf[]写入输出流
  public abstract void write(char cbuf[],int off,int len) throws IOException;
  //将字符数组cbuf[]中的从索引为off的位置处开始的len个字符写入输出流
  public void write(String str) throws IOException;
  //将字符串str中的字符写入输出流
  public void write(String str,int off,int len) throws IOException;
  //将字符串str 中从索引off开始处的len个字符写入输出流

◇ flush( )
  刷空输出流,并输出所有被缓存的字节。

◇ 关闭流

public abstract void close() throws IOException;

InputStreamReader和OutputStreamWriter

java.io包中用于处理字符流的最基本的类,用来在字节流和字符流之间作为中介。

◇ 生成流对象
  public InputStreamReader(InputStream in);
  /in是字节流,而InputStreamReader是字符流,但是其来源是字节流in,
  因此InputStreamReader就可以把字节流in转换成字符流处理。/

public InputStreamReader(InputStream in,String enc) throws UnsupportedEncodingException;
  /enc是编码方式,就是从字节流到字符流进行转换时所采用的编码方式,
   例如 ISO8859-1,UTF-8,UTF-16等等
/

public OutputStreamWriter(OutputStream out);
  /*out是字节流,而OutputStreamReader是字符流 */

public OutputStreamWriter(OutputStream out,String enc) throws UnsupportedEncodingException; //enc是编码方式

InputStreamReader和OutputStreamWriter的方法:

◇ 读入和写出字符
  基本同Reader和Writer。

◇ 获取当前编码方式
  public String getEncoding();

◇ 关闭流
  public void close() throws IOException;

####BufferedReader和BufferedWriter

◇ 生成流对象

public BufferedReader(Reader in); //使用缺省的缓冲区大小
  public BufferedReader(Reader in, int sz); //sz为缓冲区的大小
  public BufferedWriter(Writer out);
  public BufferedWriter(Writer out, int sz);

◇ 读入/写出字符

除了Reader和Writer中提供的基本的读写方法外,增加对整行字符的处理。
  public String readLine() throws IOException; //读一行字符
  public void newLine() throws IOException; //写一行字符

例:		
 import java.io.*;
 public class NumberInput{
 		public static void main(String args[]){
 			try{
 				InputStreamReader ir;
 				BufferedReader in;
 				ir=new InputStreamReader(System.in); 
  				//从键盘接收了一个字符串的输入,并创建了一个字符输入流的对象
  				in=new BufferedReader(ir);
    		String s=in.readLine();
     	//从输入流in中读入一行,并将读取的值赋值给字符串变量s
     System.out.println("Input value is: "+s);
      int i = Integer.parseInt(s);//转换成int型
      i*=2;
      System.out.println("Input value changed after doubled: "+i);
      }catch(IOException e){
      		System.out.println(e);
      	}
     }
   }

运行结果:

D:>java NumberInput
123
Input value is 123
Input value changed after doubled: 246

注意:在读取字符流时,如果不是来自于本地的,比如说来自于网络上某处的与本地编码方式不同的机器,那么我们在构造输入流时就不能简单地使用本地缺省的编码方式,否则读出的字符就不正确;为了正确地读出异种机上的字符,我们应该使用下述方式构造输入流对象:
  
     ir = new InputStreamReader(is, “8859_1”);

采用ISO 8859_1编码方式,这是一种映射到ASCII码的编码方式,可以在不同平台之间正确转换字符