1.流的分类
1.1. 输入流和输出流
输入流:只能从中读取数据,InputStream(字节流,8位)和Reader(字符流,16位)为基类。
输出流:只能输出数据,OutputStream和Writer为基类。
输入流的使用:
import java.io.*;
class FileInputStreamTest
{
public static void main(String[] args) throws IOException
{
//定义一个指向本文件的字节输入流
FileInputStream fis=new FileInputStream("FileInputStreamTest.java");
byte[] buff=new byte[1024];
int hasRead=0;
while((hasRead=fis.read(buff))>0)
{//循环读取数据,并转为字符串进行输出
System.out.print(new String(buff,0,hasRead));
}
fis.close();//关闭文件
try(FileReader fr=new FileReader("FileInputStreamTest.java"))//该方法定义的输入流会自动关闭输入流
{
char[] cbuf=new char[32];
int frhasRead=0;
while((frhasRead=fr.read(cbuf))>0)
{//按照原格式进行输出,包括注释
System.out.print(new String(cbuf,0,frhasRead));
}
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
}
输出流的使用:
import java.io.*;
class FileOutputStreamTest
{
public static void main(String[] args)
{
try(FileInputStream fis=new FileInputStream("FileOutputStreamTest.java");
FileOutputStream fos=new FileOutputStream("output.txt"))
{
byte[] buff=new byte[32];
int hasRead=0;
while((hasRead=fis.read(buff))>0)
{
fos.write(buff,0,hasRead);
}
}
catch(IOException ex)
{
ex.printStackTrace();
}
}
}
1.2.节点流和处理流
节点流:可以从/向一个特定的IO设备中读/写数据的流。程序直接连接数据源进行数据传输。
处理流:对一个已存在的流进行连接或封装,使得程序和数据源通过中间的封装流进行数据传输,则只要使用相同的处理流,程序可以采用完全相同的方式访问不同的数据源.其模型如下:
为什是使用处理流?
当我们使用不同的输出流时,而这些输出流中使用的方法不一定相同,为了使用统一的方法进行输出,则可以在外层封装一个处理流,使得在不同输出流之间进行切换时,只需修改该处理流指向的流类型,消除不同节点流的实现差异。如下:
import java.io.*;
class PrintStreamTest
{
public static void main(String[] args) throws IOException
{
try
{
FileOutputStream fos=new FileOutputStream("test.txt");
PrintStream ps=new PrintStream(fos);
ps.println("12345");
ps.println(123456);
fos.close();
FileOutputStream fos1=new FileOutputStream("test2.txt");
ps=new PrintStream(fos1);//重新指向一个输出流
ps.println("test2");
fos1.close();
}
catch(IOException ex)
{
ex.printStackTrace();
}
}
}
1.3转换流
作用:用于实现将字节流转为字符流,其中InputStreamReader将字节输入流转为字符输入流,OutputStreamWriter是将字节输出流转为字符输出流。
没有将字符流转为字节流的转换流,尽管字节流比字符流使用广泛,但是字符流比字节流操作方便。
import java.io.*;
class TranStream
{
public static void main(String[] args)
{
try(//将键盘输入转为Reader对象
InputStreamReader reader=new InputStreamReader(System.in);
BufferedReader br=new BufferedReader(reader)//将转换流包装
)
{
String buff=null;
while((buff=br.readLine())!=null)
{//按行读取。遇到q退出
if(buff.equals("q"))
{
System.exit(1);
}
System.out.println("the input is:"+buff);
}
}
catch(IOException ex)
{
ex.printStackTrace();
}
}
}
1.4. 推回输入流
该输入流可将已经读取出的数据推回到缓冲区中,从而允许重复读取刚刚读取的内容。使用PushbachInputStream和PushbackReader中的unread()方法实现。当创建一个PushbachInputStream和PushbackReader时需要指定推回缓冲区的大小,默认为1。
import java.io.*;
public class PushbackTest
{
public static void main(String[] args)
{
PushbackReader pr = null;
try
{
//创建一个PushbackReader对象,指定推回缓冲区的长度为64
pr = new PushbackReader(new FileReader("PushbackTest.java") ,128);
char[] buf = new char[32];
//用以保存上次读取的字符串内容
String lastContent = "";
int hasRead = 0;
//循环读取文件内容
while ((hasRead = pr.read(buf)) > 0)
{
//将读取的内容转换成字符串
String content = new String(buf , 0 , hasRead);
int targetIndex = 0;
//将上次读取的字符串和本次读取的字符串拼起来,查看是否包含目标字符串"new PushbackReader"
//如果包含目标字符串
if ((targetIndex = (lastContent + content).indexOf("new PushbackReader")) > 0)
{
//将本次内容和上次内容一起推回缓冲区
pr.unread((lastContent + content).toCharArray());
//再次读取指定长度的内容(就是目标字符串之前的内容)
pr.read(buf , 0 , targetIndex);
//打印读取的内容
System.out.print(new String(buf , 0 ,targetIndex));
System.exit(0);
}
else
{
//打印上次读取的内容
System.out.print(lastContent);
//将本次内容设为上次读取的内容
lastContent = content;
}
}
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
finally
{
try
{
if (pr != null)
pr.close();
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}
}
}