11.I/O输入输出流

 

11、IO输入输出流

11.1、File类

File类是IO包中唯一代表磁盘文件本身的对象,File类定义了一些与平台无关的方法来操纵文件,通过调用File类提供的各种方法,我们能够创建、删除文件,重命名文件,判断文件的读写权限及是否存在,设置和查询文件的最近修改时间。

 

import java.io.*;
	public class FileTest{
		public static void main(String[] args){
			File f=new File("c:\\1.txt");
			if(f.exists()){
				f.delete();
			}else{
				try{
					f.createNewFile();
				}catch(Exception e){
					System.out.println(e.getMessage());
				}
			}
			System.out.println("File name:"+f.getName());
			System.out.println("File path:"+f.getPath());
			System.out.println("Abs path:"+f.getAbsolutePath());
			System.out.println("Parent:"+f.getParent());
			System.out.println(f.exists()?"exists":"does not exist");
			System.out.println(f.canWrite()?"is writeable":" is not writeable");
			System.out.println(f.canRead()?"is readable":"is not readable");
			System.out.println(f.isDirectory()?"is ":"is not"+" a directory");
			System.out.println(f.isFile()?"is normal file":" might be a named pipe");
			System.out.println(f.isAbsolute()?"is absolute":" is not absolute");
			System.out.println("File last modified:"+f.lastModified());
			System.out.println("File size:"+f.length()+" Bytes");
		}
	}

 

11.2、RandomAccessFile类

 

RandomAccessFile类可以说是Java语言中功能最为丰富的文件访问类,它提供了众多的文件访问方法。RandomAccessFile类支持“随机访问”方式,我们可以跳转到文件的任意位置处读写数据。在你访问一个文件的时候,不想把文件从头读到尾,并希望像访问一个数据库一样的访问一个文本文件,使用RandomAccessFile类就是你的最佳选择。

创建RandomAccessFile类对象的构造方式:

new RandomAccessFile(f,"rw"); //读写方式

new RandomAccessFile(f,"r");  //只读方式

注:当我们的程序需要以读写的方式打开一个文件时,如果这个文件不存在,程序会为你创建它。

11.3、InputStream与OutputStream

程序可以从中连续读取字节的对象叫输入流,用InputStream类完成,程序能向其中连续写入字节的对象叫输出流,用OutputStream类完成。

InputStream定义了Java的输入流模型。该类中的所有方法在遇到错误的时候都会引发IOException异常,下面是InputStream类中方法的一个简要说明:

 

int read()返回下一个输入字节的整型表示,,如果返回-1表示遇到流的末尾,结束。

int read(byte[] b)读入b.length个字节放到b中并返回实际读入的字节数。

int read(byte[] b,int off,int len) 这个方法表示把流中的数据读到,数组b中,第off个开始的len个数组元素中.

long skip(long n) 跳过输入流上的n个字节并返回实际跳过的字节数。

int availabale() 返回当前输入流中可读的字节数。

void mark(int readlimit)在输入流的当前位置处放上一个标志,允许最多再读入readlimit个字节。

void reset() 把输入指针返回到以前所做的标志处。

boolean markSupported() 如果当前流支持mark/reset操作就返回true。

void close()  在操作完一个流后要使用此方法将其关闭, 系统就会释放与这个流相关的资源。

InputStream是一个抽象类,程序中实际使用的是它的各种子类对象。不是所有的子类都会支持InputStream中定义的某些方法的,如skip,mark,reset等,这些方法只对某些子类有用。

 

OutputStream是一个定义了输出流的抽象类,这个类中的所有方法均返回void,并在遇到错误时引发IOException异常。下面是OutputStream的方法:

void write(int b) 将一个字节写到输出流。注意,这里的参数是int型,它允许write使用表达式而不用强制转换成byte型。

void write(byte[] b) 将整个字节数组写到输出流中。

void write(byte [] b,int off,int len) 将字节数组b中的从off开始的len个字节写到输出流。

void flush彻底完成输出并清空缓冲区。

void close关闭输出流。

 

11.4、FileInputStream与FileOutputStream

这两个流节点用来操作磁盘文件,在创建一个FileInputStream对象时通过构造函数指定文件的路径和名字,当然这个文件应当是存在的和可读的。

有两种创建方式:

FileInputStream inOne=new FileInputStream("hello.test");
		File f = new File("hello.test"); 
		FileInputStream inTwo = new FileInputStream(f);

 例如:

import java.io.*;
	public class FileStream{
		public static void main(String[] args){
			File f = new File("hello.txt"); 
			try{
				FileOutputStream out = new FileOutputStream(f);
				byte buf[]="www.it315.org".getBytes();
				out.write(buf);
				out.close();
			}catch(Exception e){
				System.out.println(e.getMessage());
			}
		
			try{
				FileInputStream in = new FileInputStream(f);
				byte [] buf = new byte[1024];
				int len = in.read(buf);
				System.out.println(new String(buf,0,len));
			}catch(Exception e){
				System.out.println(e.getMessage());
			}
		}
	}

 

11.5、Reader与Writer

Java中的字符是unicode编码,是双字节的,而InputStream与OutputStream是用来处理字节的,在处理字符文本时不太方便,需要编写额外的程序代码。Java为字符文本的输入输出专门提供了一套单独的类,Reader、Writer两个抽象类与InputStream、OutputStream两个类相对应,同样,Reader、Writer下面也有许多子类,对具体IO设备进行字符输入输出,如FileReader就是用来读取文件流中的字符。

import java.io.*;
	public class FileStream{
		public static void main(String[] args){
			File f = new File("hello.txt"); 
			try{
				FileWriter out = new FileWriter(f);
				out.write("www.it315.org");
				out.close();
			}catch(Exception e){
				System.out.println(e.getMessage());
			}
		
			try{
				FileReader in = new FileReader(f);
				char [] buf = new char[1024];
				int len = in.read(buf);
				System.out.println(new String(buf,0,len));
			}catch(Exception e){
				System.out.println(e.getMessage());
			}
		}
	}
 

11.6、PipedInputStream与PipedOutputStream

一个PipedInputStream对象必须和一个PipedOutputStream对象进行连接而产生一个通信管道,PipedOutStream可以向管道中写入数据,PipedInputStream可以从管道中读取PipedOutputStream写入的数据。这两个类主要用来完成线程之间的通信,一个线程的PipedInputStream 对象能够从另外一个线程的PipedOutputStream对象中读取数据。

import java.io.*;
	public class PipeStreamTest{
		public static void main(String args[]){
			try{
				Thread t1=new Sender();
				Thread t2=new Receiver();
				PipedOutputStream out = t1.getOutputStream();
				PipedInputStream in = t2.getInputStream();
				out.connect(in);
				t1.start();
				t2.start();
			}catch(IOException e){
				System.out.println(e.getMessage());
			}
		}
	}
	
	class Sender extends Thread{
		private PipedOutputStream out=new PipedOutputStream();
		public PipedOutputStream getOutputStream(){
			return out;
		}
		public void run(){
			String s=new String("hello,receiver ,how are you");
			try{
				out.write(s.getBytes());
				out.close();
			}catch(IOException e){
				System.out.println(e.getMessage());
			}
		}
	}
	
	class Receiver extends Thread{
		private PipedInputStream in=new PipedInputStream();
		public PipedInputStream getInputStream(){
			return in;
		}
		public void run(){
			String s=null;
			byte [] buf = new byte[1024];
			try{
				int len =in.read(buf);
				s = new String(buf,0,len);
				System.out.println("the following message comes from sender:\n"+s);
				in.close();
			}catch(IOException e){
				System.out.println(e.getMessage());
			}
		}
	}

 

11.7、ByteArrayInputStream与ByteArrayOutputStream

ByteArrayInputStream是输入流的一种实现,它有两个构造函数,每个构造函数都需要一个字节数组来作为数据源:

ByteArrayInputStream(byte[] buf) 

ByteArrayInputStream(byte[] buf, int offset, int length)

第二个构造函数指定仅使用数组buf中的从offset开始的length个元素作为数据源。

ByteArrayOutputStream是输出流的一种实现,它也有两个构造函数。

ByteArrayOutputStream()

ByteArrayOutputStream(int)

第一种形式的构造函数创建一个32字节的缓冲区,第二种形式则是根据参数指定的大小创建缓冲区,缓冲区的大小在数据过多时能够自动增长。

11.8、BufferedInputStream与 BufferedOuputStream

对I/O进行缓冲是一种常见的性能优化。缓冲流为I/O流增加了内存缓冲区。增加缓冲区有两个基本目的:

允许Java的I/O一次不只操作一个字节,这样提高了整个系统的性能。

由于有缓冲区,使得在流上执行skip、mark和reset方法都成为可能。

BufferedInputStream

Java的BufferedInputStream类可以对任何的InputStream进行带缓冲区的封装以达到性能的改善。BufferedInputStream有两个构造函数:

BufferedInputStream(InputStream in)

BufferedInputStream(InputStream in,int size)

第一种形式的构造函数创建了一个带有32字节缓冲区的缓冲流,第二种形式的构造函数按指定的大小来创建缓冲区。

BufferedOutputStream

往BufferedOutputStream输出和往OutputStream输出完全一样,只不过BufferedOutputStream有一个flush方法用来将缓冲区的数据强制输出完。与缓冲区输入流不同,缓冲区输出流没有增加额外的功能。在Java中使用输出缓冲也是为了提高性能。它也有两个构造函数:

BufferedOutputStream(OutputStream out)

BufferedOutputStream(OutputStream out,int size)

第一种形式创建一个32字节的缓冲区,第二种形式以指定的大小来创建缓冲区。

11.9、DataInputStream与 DataOutputStream

DataOutputStream类提供了三种写入字符串的方法,分别是

public final void writeBytes(String?s) throws IOException

public final void writeChars(String?s) throws IOException

public final void writeUTF(String?str) throws IOException

11.10、字节流与字符流的转换

InputStreamReader 和 OutputStreamWriter 

这两个类是字节流和字符流之间转换的类,InputStreamReader可以将一个字节流中的字节解码成字符,OuputStreamWriter将写入的字符编码成字节后写入一个字节流。其中InputStreamReader有两个主要的构造函数:

InputStreamReader(InputStream?in) //用默认字符集创建一个InputStreamReader对象

InputStreamReader(InputStream in,String CharsetName) //接受以指定字符集名的字符串,并用//该字符集创建对象

OutputStreamWriter也有对应的两个主要的构造函数:

OutputStreamWriter(OutputStream?in) //用默认字符集创建一个OutputStreamWriter对象

OutputStreamWriter(OutputStream?in,String CharsetName) //接受以指定字符集名的字符串,并用该字符集创建OutputStreamWriter对象

为了达到最好的效率,避免频繁的字符与字节间的相互转换,我们最好不要直接使用这两个类来进行读写,应尽量使用BufferedWriter类包装OutputStreamWriter类,用BufferedReader类包装InputStreamReader。例如:

BufferedWriter out=new BufferedWriter(newOutputStreamWriter(System.out));

BufferedReader in=new BufferedReader(new InputStreamReader(System.in));

读取到键盘上输入的一整行字符,只要用下面的两行程序代码就可以解决这个问题:

BufferedReader in=new BufferedReader(new InputStreamReader(System.in));

String strLine = in.readLine();

11.11、IO包中的类层次关系图

1. 字节输入流类:



 

2. 字节输出流类:


3. 字符输入流类:


4. 字符输出流类:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值