流就是对输入数据源和输出目的地的抽象表示。
IO流用来处理设备之间的数据传输,Java对数据的操作是通过流的方式。
流按操作数据分为两种:字节流与字符流
流按流向分为:输入流,输出流)。
字节流的抽象基类:
InputStream ,OutputStream。
字符流的抽象基类:
Reader ,Writer。
为了提高输入输出流的效率引入了缓冲流
BufferedWirter,BufferedReader,BufferedInputStream,BufferedOutputStream
import java.io.*;
class BufferedReaderDemo
{
public static void main(String[] args) throws IOException
{
//创建一个读取流对象和文件相关联
FileReader fr = new FileReader("MapDemo.java");
//为了提高效率,将字符读取流对象作为参数传递给缓冲区对象的构造函数
BufferedReader bufr = new BufferedReader(fr);
String line = null;
while((line = bufr.readLine()) != null)
{
System.out.println(line);
}
bufr.close();
}
}
这是字节流复制文本文件的示例:
import java.io.*;
class CopyText
{
public static void main(String[] args)
{
String fromFile = null,toFile = null;
if(args.length != 2)
{
System.out.println("please input like this:java CopyText fromFile toFile");
System.exit(1);
}
copy(args[0], args[1]);
}
public static void copy(String fromFile, String toFile)
{
BufferedWriter bufw = null;
BufferedReader bufr = null;
try
{
bufw = new BufferedWriter(new FileWriter(toFile));
bufr = new BufferedReader(new FileReader(fromFile));
String line = null;
while((line = bufr.readLine()) != null)
{
bufw.write(line);
bufw.newLine();
bufw.flush();
}
}
catch (IOException e)
{
throw new RuntimeException("读写失败");
}
finally
{
if(bufw != null)
try
{
bufw.close();
}
catch (IOException e)
{
throw new RuntimeException("写入关闭失败");
}
if(bufr != null)
try
{
bufr.close();
}
catch (IOException e)
{
throw new RuntimeException("读取关闭失败");
}
}
/*
//没有调用缓冲区对象
FileWriter fw = null;
FileReader fr = null;
try
{
fw = new FileWriter(toFile);
fr = new FileReader(fromFile);
char[] buf = new char[1024];
int len=0;
while((len = fr.read(buf)) != -1)
{
fw.write(buf, 0, len);
}
}
catch (Exception e)
{
throw new RuntimeException("操作失败");
}
finally
{
if(fw != null)
try
{
fw.close();
}
catch (Exception e)
{
}
if(fr != null)
try
{
fr.close();
}
catch (Exception e)
{
}
}
*/
}
}
在一个程序中到底使用哪种流都需要进行一下判断,具体思路如下:
(1)是否为字节流,是字符流就使用InputStream与OutputStream,是字节流就使用Reader与Wirter。
(2)是否需要提高效率,需要的话就加上相应流的缓冲区
(3)是否需要字节流与字符流之间的转化,如果需要就要加上他们之间的桥梁转换流
转化流有两种形式
InputStreamReader :是字节流通向字符流的桥梁
InputStreamWirter :是字符流通向字节流的桥梁
就拿一个复制Mp3的例子来作为分析:
(1)因为图片是二进制文件,所以要使用字节流InputStream与OutputStream
(2)因为MP3文件大于1M,需要提高效率,使用缓冲区BufferedInputStream与BufferedOutputStream
(3)不需要字节流与字符流之间的转化,不需要转换流
import java.io.*;
class CopyMp3
{
public static void main(String[] args) throws IOException
{
if(args.length != 2)
{
System.out.println("please input like:java CopyMp3 formMp3 toMp3");
System.exit(1);
}
long start = System.currentTimeMillis();
copy_2(args[0],args[1]);
long end = System.currentTimeMillis();
System.out.println((end-start)+"毫秒");
}
//通过字节流的缓冲区实现复制
public static void copy_2(String fromMp3, String toMp3) throws IOException
{
BufferedInputStream bufis = new BufferedInputStream(new FileInputStream(fromMp3));
BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream(toMp3));
int by = 0;
while((by = bufis.myread()) != -1)
{
bufos.write(by);
}
bufos.close();
bufis.close();
}
/*
byte:-1 ------> int:-1
11111111 11111111 11111111 11111111
00000000 00000000 00000000 11111111 255
11111111 ---》提升为int时也为-1,&255变为
00000000 00000000 00000000 11111111
这样前面补零,保留原数据不变,又避免-1的出现
*/
//通过字节流的缓冲区实现复制
public static void copy_1(String fromMp3, String toMp3)
{
BufferedInputStream bufis = null;
BufferedOutputStream bufos = null;
try
{
bufis = new BufferedInputStream(new FileInputStream(fromMp3));
bufos = new BufferedOutputStream(new FileOutputStream(toMp3));
byte[] buf = new byte[1024];
int len = 0;
while((len = bufis.read(buf)) != -1)
{
bufos.write(buf, 0 ,len);
}
}
catch (IOException e)
{
throw new RuntimeException("字节流读取失败");
}
finally
{
if(bufis != null)
try
{
bufis.close();
}
catch (IOException e)
{
throw new RuntimeException("输入字节流关闭失败");
}
if(bufos != null)
try
{
bufos.close();
}
catch (IOException e)
{
throw new RuntimeException("输出字节流关闭失败");
}
}
}
}