浅谈JAVA中输入输出流实例详解
java语言的输入输出功能是十分强大而灵活的,美中不足的是看上去输入输出的代码并不是很简洁,因为你往往需要包装许多不同的对象。在Java类库中,IO部分的内容是很庞大的,因为它涉及的领域很广泛:标准输入输出,文件的操作,网络上的数据流,字符串流,对象流,zip文件流....本文的目的是为大家介绍JAVA中输入输出流实例详解。
流的层次结构
定义:
java将读取数据对象成为输入流,能向其写入的对象叫输出流。结构图如下:
1、输入输出:
输入/输出(Input/Output)是指对某个设备或环境进行数据的输入或输出.任何语言都有输入输出的功能,在Java程序中,是通过流来完成输入和输出的,它通过Java输入输出系统连接到物理设备,虽然输入输出流所连接的实际物理设备并不一样,但却可以以同一种方式工作.例如对硬盘的输入输出,对网络主机进行输入输出,因此设备或者环境的不同会有各式各样的输入输出的问题与解决方案.
2、流:
流是指在计算机的输入与输出之间运动的数据序列.流序列中的数据既可以是未经加工的原始的二进制数据,也可以是经一定编码处理后符合某种格式规定的特定数据.习惯上称代码相关的部分为内部,称与代码无关的部分为外部.
从数据的传输方式划分,流可分为输入流和输出流;从流的内容上划分,流可分为字节流和字符流.
(1) 输入输出流
输入流的作用是从程序内部向外部读取数据.
输出流的作用是从程序外部向内部写入数据.
(2) 字节流和字符流
字流(byte stream)对数据以字节为单位进行读写,既可以一个字节接一个字节的读写数据,也可以一次读写任意长度的字节块(即字节数组).
字符流(character stream)在读写流内数据时是以字符为单位,一次一个字符,或者一次一个字符块.
为了方便流的处理,Java语言的流都封装在java.io包中,所以要使用流,必须导入java.io包.
Java的I/O流是建立在四个抽象类的基础上,分别是InputStream, OutputStream, Reader和Writer.InputStream类及其子类可用于实现字节流数据的输入处理;OutputStream类及其子类可用于实现字节流数据的输出处理;Reader类及其子类可用于实现字符流数据的输入处理;Writer类及其子类可用于实现字符流数据的输出处理.
一、File类
Java中对文件的读写操作可以通过输入输出流来实现,但对于文件目录、属性以及管理等信息Java提供了一个专门的File类来实现.
(1) File类的构造方法
创建一个File类对象的构造方法有:
File (String pathname); //根据路径名创建.
File (File parent, String child); //在给定File对象下创建.
File (String parent, String child); //根据指定路径下创建.
File (URL url); //根据一个URL链接创建.
(2) File类的常用方法
boolean canRead():判断File对象对应的路径是否可读.
boolean canWrite():判断File对象对应的路径是否可写.
boolean exists():判断File对象对应的路径是否存在.
String getAbsolutePath():获取File对象对应路径的绝对路径.
String getParent():获取File对象对应路径的目录.
String getPath():获取File对象对应的路径.
boolean isAbsolute():判断File对象对应的路径是否为绝对路径.
String getName():获取File对象对应路径的文件名.
boolean isDirectory():判断File对象对应的路径是否为目录.
boolean isFile():判断File对象对应的路径是否为文件.
boolean isHidden():判断File对象对应的文件是否为隐藏属性.
long length():获得File对象对应文件的长度.
long lastModified():获得File对象对应文件的最近修改时间.
boolean renameTo(File dest):更改File对象对应文件的文件名.
boolean setReadOnly():设置File对象对应文件为只读.
(3) 创建文件
通过创建一个文件输出流来创建一个新文件.这种方式不能创建目录,并且如果要创建的文件已存在,会新建一个文件覆盖原文件.
FileOutrputStream file = new FileOutputStream(“filename”);
(4) 获得文件列表
通过File类的list()或listFiles()方法获得某个文件夹的文件列表.有以下几种形式:
String[] list();
File[] listFiles();
File[] listFiles(FilenameFilter filter);
File[] listFiles(FileFilter filter);
其中,FileFilter和FilenameFilter都是接口,filter为相应的过滤器.声明某个类,实现过滤器接口,便可以通过过滤条件来列出所有符合的文件.
二、InputStream类和OutputStream类
字节流类是从抽象类InputStream和OutputStream派生出来的一系列类.这类流以字节为基本处理单位.InputStream 和 OutputStream类除了可以用来处理二进制文件的数据之外,也可以用来处理文本文件.
1、InputStream类的常用方法
InputStream类是所有输入流的父类,该类的所有方法在错误发生时都会抛出IOException,主要的方法有:
(1) public abstract int read() thows IOException
方法返回一个0至255之间的整数或-1, -1代表遇到了流的结束,其它对应读入的字节.
(2) public int read(byte[]b) thows IOException
方法将字节读入参数给定的字节数组,返回值是实际读入的字节数或-1(遇到了流结束).
(3) public int read(byte[]b, int i, int b) thows IOException
方法的后两个参数分别给出读入的起始位置和读入的最大字节数.
(4) public int available()
返回当前流对象中还没有被读取的字节数量.也就是获得流中数据的长度.
(5) public long skip(long n)
跳过当前流对象中的n个字节,而实际跳过的字节数量则以返回值的方式返回.
(6) public boolean markSupported()
判断流是否支持标记(mark),标记可以方便的回到原来读过的位置.
(7) public void close()
关闭当前流对象,并释放该流对象占用的资源.
(8) public void mark(int i)
为流中当前的位置设置标志,使得以后可以从该位置继续读取.
(9) public void reset()
使流读取的位置回到设定标记的位置.
2、OutputStream类的常用方法
OutputStream类是所有输出流的父类,该类所有方法都返回void,并且在错误情况下抛出IOException,主要的方法有:
(1) public void write(int b) throws IOException
向流的末尾写入一个字节的数据.
(2) public void write(byte[] b) throws IOException
将数组b中的数据依次写入当前的流对象中.
(3) public void wirte(byte[]b, int i, int n)
将数组中从开始下标(包含),后续长度的数据依次写入到流对象中.
(4) public void close()
关闭当前流对象,并释放该流对象占用的资源.
(5) public void flush()
将当前流对象中的缓冲数据强制输出出去.使用该方法可以实现立即输出.
上面两个类的大多数方法由InputStream和OutputStream的子类覆盖,mark()和reset()方法除外.
3、FileInputStream类
FileInputStream类是InputStream的子类,可以用来处理以文件作为数据输入源的数据流,实现文件的读取操作.
它的构造方法有:
(1) FileInputStream(File f)
以指定名字的文件对象f为数据源建立文件输入流.
如果f存在的话但是它应是一个文件路径,如果是目录则会抛出IOException,但是如果是这个目录不存在的时候则会抛出:FileNotFoundException.
(2) FileInputStream(String name)
以名为name的文件为数据源建立文件输入流.
(3) FileInputStream(FileDescriptor f)
根据文件描述符对象f为输入端建立一个文件输入流.
它的主要方法是覆盖了父类(InputStream类)的方法:read()、read(byte[]b)、read(byte[]b , int i, int length)、skip(long n)、available()、close().
4、FileOutputStream类
FileOutputStream类是OutputStream的子类,用来处理以文件作为数据输出的数据流,实现对文件的写入操作.它的构造方法有:
FileOutputStream(File f);
FileOutputStream(File f, boolean b);
FileOutputStream(String f);
它的主要的方法有覆盖父类的方法:write(int b)、write(byte[]b)、write(byte[]b,int off,int len)、close()、flush().
5、DataInputStream和DataOutputStream类
DateInputStream和DataOutputStream类创建的对象分别被称为数据输入流和数据输出流.它们分别实现了DataInput接口和DataOutput接口.DateInputStream类和DataOutputStream对象允许读取Java各种类型的数据.
这两个流属于过滤流,常以其它流如InputStream或OutputStream作为它们的输入或输出.例如:
FileInputStream fis = new FileInputStream("d:\\a.txt");
DataInputStream dis = new DataInputStream(fis);
FileOutputStream fos = new FileOutputStream("d:\\a.txt");
DataOutputStream dos = new DataOutputStream(fos);
DateInputStream和DataOutputStream的输入和输出几乎是对应的,每种基本数据类型的读写方法可以从其后缀名字识别.例如:
readInt(),writeInt() // 读写一个int值
readBoolean(),writeBoolean() // 读写一个布尔值
readChar(),writeChar() // 读写一个字符
readDouble(),writeDouble() // 读写一个双精度浮点值
readFloat(),writeFloat() // 读写一个单精度浮点值
WriteChars() // 写一个字符串,但没有直接读字符串的方法
三、Reader类和Writer类
Java中的字符使用的是Unicode编码,每个字符占有两个字节,即16bit.字符流是以16位的Unicode码表示的字符为基本处理单位,进行文本数据的读写,可以实现Java程序中的内部格式和文本文件、显示输出、键盘输入等外部格式之间的转换.这种方法尤其适合汉字的操作.如果汉字以字节形式操作,有可能输出乱码.
Reader和Writer是java.io包中所有字符流的抽象父类,定义了实现其他流类的关键方法.其中两个最重要的是read()和write(),它们分别进行字符数据的读和写.Reader及Writer类和它们子类的方法,与InputStream类和OutputStream类及它们子类的使用方法非常类似.只不过其中的参数换成字符或字符数组.
1、Reader类和Writer类的常用方法
Reader类是个抽象类,该类的所有方法在错误条件下都会抛出IOException异常.常用方法如下:
(1) abstract void close():关闭输入源.
(2) void mark(int numChars):放置一个标记到输入源的当前点.
(3) boolean markSupported():如果这个流支持mark/reset方法,将返回true.
(4) int read():读取单个字符.
(5) int read(char[] buf):读字符读入到字符数组.
(6) abstract int read(char[] buf, int offset, int numChars): 将字符读入数组的某一部分.
(7) boolean ready():如果下一个输入请求不必等待,返回true,否则返回false.
(8) void reset():重置输入指针到前面设置的标记.
(9) long skip(long numChars):跳过n个字符输入,返回实际跳过的字符数.
Writer类也是个抽象类,常用方法如下:
(1) abstract void close():关闭输出流.
(2) abstract void flush():确定输出状态以便清空任何缓存.
(3) void write(int ch):写入单个字符.
(4) void write(char[] buf):写入字符数组.
(5) abstract void write(char[] buf, int offset, int numChars):写入字符数组的一部分.
(6) void write(String str):写入字符串.
(7) void write(String str, int offset, int numChars):写入字符串的一部分.
2、FileReader类
FileReader类是继承自InputStreamReader类,而InputStreamReader类又继承自Reader类,因此Reader类与InputStreamReader类所提供的方法均可供FileReader类所创建对象使用.FileReader的构造方法有:
FileReader(File file);
FileReader(FileDescriptor e );
FileReader(String filename);
3、FileWriter类
FileWriter类继承自OutputStreamWriter类,而OutputStreamWriter类又继承自Writer类,因此Writer类与OutputStreamWriter类所提供的方法均可供FileWriter类所创建对象使用.FileWriter的构造方法有:
FileWrite(File filePath);
FileWrite(File f, boolean append);
FileWrite(FileDescriptor e);
FileWrite(String filename);
FileWrite(String filename,boolean append);
4、BufferedReader类
BufferedReader类继承自Reader类,BufferedReader类是用来读取缓冲区里的数据.BufferedReader类属于过滤流,常以其它流如FileReader作为它们的输入或输出.它的构造方法有:
BufferedReader(Reader in);
BufferedReader(Reader in, int bufSize);
例如:
FileReader fr=new FileReader("d:\1.txt");
BufferedReader buf = new BufferedReader(fr);
BufferedReader提供了readerLine()方法用来读取文本每一行.
5、BufferedWriter类
BufferedWriter类继承自Writer类,BufferedWriter类是用来将数据写入到缓冲区里.使用BufferedWriter类与使用BufferedReader类过程相似.不同的是,缓冲区内的数据最后必须要用flush()方法将缓冲区清空,也就是将缓冲区中的数据全部写到文件内.它的构造方法有:
BufferedWriter(Writer out);
BufferedWriter(Writer out, int bufSize);
四、RandomAccessFile类
Java中的随机文件访问需要用到RandomAccessFile类(该类允许从任意位置访问,不仅能读取,而且能写入),它直接从Object类继承,并实现接口DataInput和DataOutput.
由于RandomAccessFile类实现了DataInput和DataOutput接口中所定义的所有方法,能够从文件中读取基本类型的数据,也能向文件写入基本类型的数据.除了DataInput和DataOutput接口中定义的方法以外,RandomAccessFile类还定义了其他的一些方法来支持随机访问.
RandomAccessFile类创建的流与前面的输入、输出流不同,RandomAccessFile类既不是输入流类InputStream类的子类,也不是输出流类OutputStram类的子类流.但是RandomAccessFile类创建的流的指向既可以作为源也可以作为目的地,换句话说,当对一个文件进行读写操作时,可以创建一个指向该文件的RandomAccessFile流即可,这样既可以从这个流中读取这个文件的数据,也通过这个流写入数据给这个文件.
RandomAccessFile类的两个构造方法:
(1) RandomAccessFile(String name, String mode)
参数name 用来确定一个文件名,给出创建的流的源(也是流目的地),参数mode取r(只读)或rw(可读写),决定创建的流对文件的访问权利.
(2) RandomAccessFile(File file, String mode)
参数file 是一个File对象,给出创建的流的源(也是流目的地),参数mode取r(只读)或rw(可读写),决定创建的流对文件的访问权利.创建对象时应捕获FileNotFoundException异常;当流进行读写操作时,应捕获IOException异常.
对象RandomAccessFile读写信息的方法同数据输入输出对象的方法相同,它可以访问类DataInputStream和DataOutputStream中的所有read()、write()方法.
移动文件读写指针的方法:
(1) long getFilePointer():返回文件指针的当前位置.
(2) void seek(long pos):将文件指针置于指定的绝对位置.位置值以从文件开始处的字节偏移量pos来计算,pos为0代表文件的开始.
(3) long length():返回文件的长度.位置值为length(),代表文件的结尾.