您的位置:首页 > 职场人生

黑马程序员—IO输入输出流

2014-02-23 17:38 316 查看
1、IO流用来处理数据之间的传输

2、通过流的方式

3、操作流的对象存储于对象中

4、按操作的数据分为字符流和字节流,其中字节流融合了编码表

5、按流向分为输入流和输出流

IO流中的常用基类

1、字节流的抽象基类:InputStream和OutputStream

2、字符流中的抽象基类:Reader和Writer

以上四个类派生出来的子类名称都是以其父类名作为子类名的后缀。

例如InputStream的子类FileInputStream,Reader的子类FileReader。

简单的IO字符流演示:

//简单的IO字符流与字节流演示:
import java.io.*;

class demo1
{
public static void main(String[] args) throws IOException
{
FileWriter fw = new FileWriter("demo.txt");
FileReader fr = new FileReader("demo.txt");

String buf = new String("黑马程序员,从这里出发!");
fw.write(buf);
fw.flush(); //这里必须要刷新下,否则数据都进行了缓冲区,没写进文件里

int ch = 0;
//reda()方法一次读取一个字节,并且会自动往下读,将字符作为一个整数返回,
//如果读到末尾的话会返回-1
while((ch = fr.read())!=-1){
System.out.println((char)ch);
}
fw.close();//关闭流资源,关闭的时候会自动刷新一下
fr.close();
}
}

字符流与字节流的区别主要在于字节流可以处理非文本数据的传输,

比如对图片或者音频这类文件的处理时就需要用到字节流了。

/*
复制一个图片
思路:
1、用字节读取流对象和图片关联
2、用字节写入流对象创建一个图片文件,用于存储获取到的图片数据
3、通过循环读写,完成数据的存储。
4、关闭资源
*/
import java.io.*;
class CopyPic
{
public static void main(String[] args)
{
FileOutputStream fos = null;
FileInputStream fis = null;
try
{
fos = new FileOutputStream("F:\\1234.jpg");
fis = new FileInputStream("F:\\java\\day19\\123.jpg");

byte []buf = new byte[1024];
int len = 0;
while((len=fis.read(buf))!=-1)
{
fos.write(buf,0,len);
}
}
catch(IOException e)
{
System.out.println(e);
throw new RuntimeException("文件复制失败");
}
finally
{
try
{
if(fis!=null)
fis.close();
}
catch(IOException e)
{
throw new RuntimeException("读取图片关闭失败");
}
try
{
if(fos!=null)
fos.close();
}
catch(IOException e)
{
throw new RuntimeException("写入图片关闭失败");
}

}
}
}

我们发现用流对象操作文件的时候,一次只能读一个字节,效率非常的低。

这时就引入了一个新的概念:缓冲区技术。从而也派生了两个新的类BufferedReader和BufferedWriter。

缓冲区技术的出现提高了对数据的读写效率。

缓冲区中提供了一些新的方法:

readLine(),该方法会根据换行符的位置,一次读取一行的数据,读到末尾的时候会返回null。

newLine(),写入一个行分隔符。

BufferedReader bufr = new BufferedReader(new FileReader("demo.txt")); //构造方法接收的是一个流对象。

模拟BufferedReader中的readLine方法

//通过自定义一个缓冲区的增强类来提升读的速度
class MyBufferedInputStream
{
private InputStream in;
private byte[] buf = new byte[1024*4];
private int pos=0,count=0;//定义一个指针和计数器

MyBufferedInputStream(InputStream in)
{
this.in = in;
}
//一次读一个字节,从缓冲区字节数组获取
public int MyRead() throws IOException
{
//通过in对象读取硬盘上的数据并存储在buf中
if(count==0)
{
pos = 0;
count = in.read(buf);
if(count<0)
return -1;
byte b = buf[pos];
count--;
pos++;
return b&0xff;
}
else if(count>0)
{
byte b = buf[pos];
count--;
pos++;
//byte类型在转换成int类型的时候会进行高位补位,导致高位全是1,
//与上255,让其高位全是0,只保留最低8位。
return b&0xff;
}
return -1;
}

装饰设计模式:

IO流的缓冲技术就是一种装饰设计模式,当想要对已有的对象进行功能增强时,可以定义类,

将已有的对象传入,基于已有的功能,并提供加强功能,那么自定义的类就称为装饰类。

特点:装饰类通常会通过构造方法接收被装饰的对象,并基于被装饰对象的功能,提供更强的功能。

装饰与继承的区别:

装饰模式比继承要灵活,避免了继承体系的臃肿,而且降低了子类与类之间的关系。

装饰类因为增强已有对象,具有的功能和已有的功能是相同的,只不过提供了更强功能,所以装饰类和被装饰类通常都属于一个体系中的。

流对象使用的总结:

1、明确源和目的。

源:输入流。InputStream,Reader

目的:输出流。OutputStream,Writer

2、操作的是不是纯文本。

是:字符流

不是:字节流

3、当体系明确后,再明确要使用哪个具体的对象

通过设备来区分

源设备:内存,硬盘,键盘

目的设备:内存,硬盘,控制台

转换流:

InputStreamReader

OutputStreamWriter

在接收键盘录入并存储的时候,进行字节流和字符流的转换

BufferedReader bufr = new BufferedReader(new InputSreamReader(System.in));

BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("dest.txt"),"utf-8"));//转换流可以将数据以指定的编码方式进行存储

转换流中可以改变输入输出的设备,例如上面的System.in。方法如下

System.setIn(InputStream in);

System.setOut(PrintStream out);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  黑马程序员