一、概念:数据流是一组有顺序的、有起点和终点的字节集合,输入输出过程中传递的数组
组成数据流。从数据流中读取数据时,必须有一个数据源和该数据流相连
IO流的分类:
1)根据数据类型不同分为:字符流和字节流
字符流:
字节流:
2)根据数据流的方向分为:输入流和输出流
Java的输入流主要有InputStream和Reader作为基类,而输出流主要由OutputStream作为基类。
二、常用的基本类
字符流,用于操作字符,针对纯文本文件
1.两个抽象基类:Writer 和 Reader,
2.FileWriter 和 FileReader 其中提高了一些读写方法,可以单个字符读取写入也,也可以以数组的形式读取写入,
由于流的操作涉及到系统资源,所以要处理异常,及关闭资源
例如://数组读写
public static void copy_1()
{ //穿件两个流对象变量
FileWriter fw = null;
FileReader fr = null;
try
{ //关联需要读写的文件
fw = new FileWriter("SystemDemo_copy.txt");
fr = new FileReader("SystemDemo.java");
//定义数组,接收读到数据
char[] buf = new char[1024];
int len = 0;
while((len=fr.read(buf))!=-1)
{ //将数组中的数据写入流
fw.write(buf,0,len);
}
}
catch (IOException e)
{
throw new RuntimeException("读写失败");
}
finally
{
if(fr!=null)
try
{ //关闭读取流
fr.close();
}
catch (IOException e)
{
}
if(fw!=null)
try
{ //关闭写入流
fw.close();
}
catch (IOException e)
{
}
}
}
//字符读写
public static void copy_1()throws IOException//异常抛出
{
//创建目的地。
FileWriter fw = new FileWriter("RuntimeDemo_copy.txt");
//与已有文件关联。
FileReader fr = new FileReader("RuntimeDemo.java");
//定义变量接收所读字符
int ch = 0;
while((ch=fr.read())!=-1)
{
fw.write(ch);
}
fw.close();
fr.close();
}
三、Java流分类:
字符流:Reader 和 Writer
字符流:
操作文件:FileReader、FilterWriter
操作数组:CharArrayReader、CharArrayWriter
操作管道:PipeReader、PipedWriter
缓 冲 流:BufferedReader、 BufferedWriter
字符串流:StringReader、StringWriter
转 换流:InputStreamReader(字节到字符的桥梁)、OutputStreamWriter(字符到字节的桥梁)
打 印 流:PrintWriter
字节流:InputStream 和 OutputStream
字节流:
操作文件:FileInputStream、FileOutputStream
操作数组:ByteArrayInputStream、ByteArrayOutputStream
操作管道:PipedInputStream、PipedOutputStream
缓 冲 流:BufferedInputStream、BufferedOutputStream
对 象 流:ObjectInputStream、ObjectOutputStream
数 据 流:DataInputStream、DataOutputStream
推 回 流:PushbackInputStream
打 印 流:PrintStream
注意:
1、使用Java的IO流执行输出时,不要忘记了关闭输出流,关闭输出流除了可以保证
流的物理资源被回收之外,可能还可以将输出缓冲流中的数据flush到物理节点理。
流的用法。
2、当我们使用处理流来包装底层节点流之后,关闭输入/输出流资源时,只要关闭最上层的
处理流即可,关闭最上层的处理流时,系统会自动关闭被该处理包装的节点流。
1)文件流
FileWriter:
1、flush和close()的区别:
flush:是将缓冲区里面的数据强制输出到文件中去,也就是清空缓冲区,但是
文件流还没有关闭,可以继续使用。
close:是将流资源关闭,关闭之后,流将再也不能使用,也不能flush了。但是
在关闭之前它会将数据flush到文件中去。
2、window系统中的回车换行符时"\r\n",但是在Linux系统中的回车换行符却是'\n'。
3、当我们往一个文件写数据的时候,要将缓冲区flush一下,这样数据才能写入到文件中。
FileReader:
1、创建一个文件读取流对象时,要保证该文件存入,如果不存在将会抛出FileNotFoundException。
2、调用读取方法时,当返回的值为-1的时候,表示已经读到文件的结尾了,所以我们就可以将这个-1来作为文件结束的标志。
FileInputStream:
FileInputStream的三种读取方式:
1、利用循环一个一个字节的读取while((int ch = read())!=-1)
2、在文件比较小的时候(小于64M,也就是虚拟机默认的内存空间),利用开辟一个字节数组,长度为available。
3、利用循环将数据读到一个字节数组中,byte buf = new byte[n] while((int ien=read(buf))!=-1)
三种读取方式的优缺点:
第一种方式:不能读取文件中的中文,因为中文是由两个字节组成的。而且读取效率又是非常的低。
第二种方式:在文件不大的情况下,我们是用buf[available],可以将文件中的数据刚刚好的放在
一个字节数组中,不用去循环了,这样既节省了大量的空间,而且还可以提高读取的效率,
但是遇到大文件是行不通的。非常方便用于读取文本文件之类的。
第三种方式:这种方式是最好的,即使遇到了大文件也没有关系。但是数组的空间长度要划分的合
理,这样的话可以节省空间。
注意:当我们在使用FileInputStream时,如果没有对应的文件的话,那么将会抛出异常,所以在调用此流时要保证有文件存在。
FileOutputStream:
1、用法:用于写入诸如图像数据之类的原始字节的流
2、主要的方法:
1)void write(byte b):将 b.length 个字节从指定 byte 数组写入此文件输出流中。
2)void write(byte[] b,int off,int len): 将指定 byte 数组中从偏移量 off 开始的
len 个字节写入此文件输出流。
3)void write(int b):将指定字节写入此文件输出流。
FileOutputStream和FileInputStream代码演示:
public class CopyMediaFile{
private FileInputStream fis;
private FileOutputStream fos;
public static void main(String[] args)throws IOException{
CopyMediaFile cmd = new CopyMediaFile();
cmd.CopyPic();
cmd.CopyMusic();
cmd.CopyFile();
}
//将D盘下的Test.jpg拷贝到当前目录下。
public void CopyPic()throws IOException
{
fos = new FileOutputStream("copy_test.jpg");
fis = new FileInputStream("D:\\Test.jpg");
byte buf[] = new byte[1024];
int len = 0;
while((len = fis.read(buf))!=-1){
fos.write(buf,0,len);
}
fis.close();
fos.close();
}
//将D盘下的Test.wma拷贝到当前目录下。
public void CopyMusic()throws IOException{
fos = new FileOutputStream("copy_test.wma");
fis = new FileInputStream("D:\\Test.wma");
int len = fis.available();
byte buf[] = new byte[len];
fos.write(buf,0,len);
fis.close();
fos.close();
}
//将D盘下的Test.txt拷贝到当前目录下。
public void CopyFile()throws IOException{
fos = new FileOutputStream("copy_test.txt");
fis = new FileInputStream("D:\\Test.txt");
byte buf[] = new byte[1024];
int len = 0;