天天看点

java的I/O系统——输入/输出

Java中,流就是从源到目的地的字节的有序序列。,流式I/O是一种顺序存取方式。

输入流:java从某个数据源(文件,内存等)到程序本身的一个流,从这个流中读取数据,就是输入流。包括字节流InputStream和字符流Reader

输出流:类似地,从java程序本身到外界某个目的地的流,把数据存储在流中,以把程序的数据保存到外界,这就是输出流。包括字节流OutputStream和字符流Writer

(我自己刚开始看的时候总是把Reader和Writer混淆,因为他不像字节流一样,可以直接从单词看出是输入流还是是输出流,希望在这里提醒大家可以引起大家的注意)

文件流

顾名思义,就是对文件系统中的文件进行读写。包括FileInputStream/FileOutputStream和FileReader和FileWriter.下面通过例子来理解一些文件流和一些方法。

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;


public class CopyBytes {

	public static void main(String[] args) throws IOException {
	FileInputStream in=new FileInputStream("F:/words.txt");
	FileOutputStream out = new FileOutputStream("F:/words1.txt");
	int c;
	while((c=in.read())!=-1)
		out.write(c);
	in.close();
	out.close();
	}

}

           

这个代码简单,就是实现文件的读和写。首先通过输入流,将words文件输入到程序本身,再通过输出流将在程序中读到的内容写到文件words1中。其中,read()方法是输入流的一个方法,也很好理解,就是读取内容,返回一个整数型,当返回-1时,表示读取数据完成(读取到了末尾)。运行结果就是实现文件的复制

java的I/O系统——输入/输出
java的I/O系统——输入/输出

字符流的应用也是完全类似。只要把FileInputStream换成FileReader,把方法FileOutputStream换成FileWriter就可以了,读取数据仍然可以用read方法。

缓存流

还存留同样包括字节流和字符流,有BufferedInputStream/BufferedOutputStream类和BufferedReader/BufferedWriter类。这种流就是把数据从原十六成块读入或者把数据积累成一个大的数据块后再成块写出。由于缓存流式过滤流,所以它必须有一个InputStream/OutputStream类型的流在前端。

管道流

管道流可以实现线程之间的直接传输。线程A可以通过它的输出管道发送数据,线程B通过它的输入管道连接线程A的输出管道即可以进行线程间的交流。PipedReader/PipedInputStream实现管道的输入,而PipedWriter/PipedOutputStream是管道的输出流。管道之间需要进行连接才可以通信。连接管道有两种方法。

方法1:

PipedInputStream pin = new PipedInputStream();
PipedOutputStream pout = new PipedOutputStream(pin);
           

方法2:

PipedInputStream pin = new PipedInputStream();
PipedOutputStream pout = new PipedOutputStream();
pin.correct(pout);
           

通过例子来理解

RhymingWords.java

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.PipedReader;
import java.io.PipedWriter;
import java.io.PrintWriter;
import java.io.Reader;
public class RhymingWords {
	public static void main(String[] args) throws IOException {
	FileReader words=new FileReader("F:/words.txt");
	Reader rhymedWords=(reverse(sort(reverse(words))));//进行单词的逆序,排序,再逆序
	//显示处理后的结果
	BufferedReader in=new BufferedReader(rhymedWords);
	String input;
	while((input=in.readLine())!=null)
		System.out.println(input);
		in.close();
	}
public static Reader reverse (Reader source)throws IOException{
	BufferedReader in=new BufferedReader(source);
	PipedWriter pipeOut =new PipedWriter();//建立管道输出流
	PipedReader pipeIn =new PipedReader(pipeOut);//建立管道输入流,将结果传到其他线程
	PrintWriter out =new PrintWriter(pipeOut);//
	new ReverseThread(out,in).start();
	return pipeIn;
}
public static Reader sort(Reader source) throws IOException{
	BufferedReader in=new BufferedReader(source);
	PipedWriter pipeOut =new PipedWriter();
	PipedReader pipeIn =new PipedReader(pipeOut);
	PrintWriter out =new PrintWriter(pipeOut);
	new SortThread(out,in).start();
	return pipeIn;
}
	}


           

ReverseThread.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;


public class ReverseThread extends Thread{
private PrintWriter out=null;
private BufferedReader in=null;
public ReverseThread(PrintWriter out,BufferedReader in){
	this.out=out;
	this.in=in;
}
public void run(){
	if(out!=null&&in!=null){
		try{
			String input;
			while((input=in.readLine())!=null){
				out.println(reverselt(input));
				out.flush();
			}
			out.close();
		}catch(IOException e){
			System.out.println("ReverseThread run:"+e);
		}
	}
}
实现单词的逆序算法
private String reverselt(String source){
	int i,len=source.length();
	StringBuffer dest=new StringBuffer(len);
	for(i=(len-1);i>=0;i--)
		dest.append(source.charAt(i));
	return dest.toString();
}
}

           

SortThread.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
public class SortThread extends Thread{
	private PrintWriter out=null;
	private BufferedReader in=null;
	public SortThread(PrintWriter out,BufferedReader in){
		this.out=out;
		this.in=in;
		
	}
	public void run(){
		int MAXWORDS=50;
		if(out!=null&&in!=null){
			try{
				String[] listOfWords=new String[MAXWORDS];
				int numwords=0;
				
					while((listOfWords[numwords] = in.readLine())!=null)
						numwords++;
				
						quicksort(listOfWords,0,numwords-1);
				for(int i=0;i<numwords;i++)
					out.println(listOfWords[i]);
				out.close();
			}catch( IOException e){
				System.out.println("SortThread run:"+e);
			}
			
		}
	}
private static void quicksort(String[] a,int lo0,int hi0){
	int lo=lo0;
	int hi=hi0;
	if(lo>=hi)return;
	String mid=a[(lo+hi)/2];
	while(lo<hi){
		while(lo<hi&&a[lo].compareTo(mid)<0)
			lo++;
			while(lo<hi&&a[hi].compareTo(mid)>0)
				hi--;
		if(lo<hi)
		{
			String T= a[lo];
			a[lo]=a[hi];
			a[hi]=T;
			lo++;
			hi--;
		}
	}
	if(hi<lo){
		int T=hi;
		hi=lo;
		lo=T;
	}
	quicksort(a,lo0,lo);
	quicksort(a,lo==lo0?lo+1:lo,hi0);
}
}

           

这三个程序是实现将文件中的单词倒置,再排序,最后再倒置,使最后得到的单词具有押韵。F:/words.txt文件为:

java的I/O系统——输入/输出

运行结果为:

java的I/O系统——输入/输出

随机存储文件的操作——RandomAccessFile

前面介绍额流都是顺序读取,而强大的RandomAccessFile则可以实现随机读写,即可以再文件的任意位置实现读写操作。

还是通过例子来理解

import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessTest {
	public static void main(String[] args) throws IOException{	
		long filePoint=0;
		String s;
		RandomAccessFile file = new RandomAccessFile("F:/words.txt","r");
		long fileLength =file.length();
		while(filePoint<fileLength){
			s=file.readLine();
			System.out.println(s);
			filePoint = file.getFilePointer();
		}
		file.close();
	}

}
           

还是那个文件,filePoint相当于是指针,使用文件的getFilePoint方法可以获取当前指针的位置,当指针的位置小于文件的长度fileLength时,就进行读操作并且将其直接输出。RandomAccessFile再使用时,经常会配合指针一起使用。

总结

流式进行数据读取的途径,可以死文件,网站等等。文件流就是从文件读取数据的流,缓存流就是将数据暂存于缓存区的流,管道流则可以进行线程之间的通信,最后锁讲的是速记读取数据的方法。