黑马程序员-IO流

------- android培训java培训、期待与您交流! ----------

IO流

自己对IO的理解:为什么称为流呢?想象一下溪流是啥样的,就是一滴一滴的水组成,并且有指定的流向,可以传输到各种地方。

那么电脑中的数据又何尝不是呢?一个个的字节就是一滴一滴的水,文件都是由一个个的字节组成的,那么传输一个文件不就相当于传输水到某处么?

所以:在水中 流就是水滴的流动

那么在数据中,也就是数据的流动了

万物皆对象:java将这些流都用对象的形式来体现,存在IO包中


流也有分类,按照不同的标准分成不同的类

按传输方式: 字节流和字符流

按传入的目的:输入流和输出流


字节流:处理字节数据的流对象,设备中的数据无论是图片或者DVD,文字,都以二进制存储的

二进制的最终都是以一个8位为数据单元进行体现,所以计算机中的最小数据单元就是字节。意味着,字节流可以处理设备上的所有数据

所以字节流一样可以处理字符数据


那么为什么要有字符流呢?

因为字符每个国家不一样,所以会涉及到字符编码,那么GBK编码的中文用unicode编码就有问题了

所以将字节流和编码表封装成对象,就是字符流。只要操作字符数据,优先考虑使用字符流体系


那么来介绍流的体系,首先不断抽取形成的四个基类,都是抽象类

字节流  InputStream  OutputStream

字符流  Reader   Writer

在这四个系统中,它们的子类,都有一个共性特点:子类名后缀都是父类名,前缀名都是这个子类的功能名称。

并且每一个都会有IO异常  所以要抛或者处理IOException


介绍几种简单的形式:

1.创建一个字符输出流对象,操作文件

2.对象产生后,会在堆内存中有一个实体,同时也调用了系统底层资源,在指定的位置创建了一个存储数据的文件

3.如果指定位置,出现了同名文件,文件会被覆盖


FileWriter fw = new FileWriter("demo.txt"); //FileNotFoundException如果字符串不是一个文件名报出此异常

记住:Writer的write方法是需要刷新缓冲区的。

fw.flush();

用完要关闭流

fw.close();



io异常处理方式: io一定要写finally

FileWriter写入数据的细节

1.window中的换行符: \r\n 

2.续写数据:只要在构造函数中传入新的参数True

3.目录分割符:window \\ 


FileReader:使用Reader 读取一个文本文件中的数据

返回-1 标志读到结尾

FileReader fr = new FileReader("demo.txt");

int ch = 0;

while((ch=fr.read())!=-1) //条件是没有读到结尾 , 返回字符的整数形式

{

System.out.println((char)ch);

}

fr.close();


第二种方式:自定义缓冲区,高效

FileReader fr = new FileReader("demo.txt");

char[] buf = new char[1024]; //自定义一个字符数组做缓冲

int len = 0;

while((len=fr.read(buf))!=-1)//返回的长度为元素的角标

{

sop(new String(buf,0,len));

}

fr.close();


IO使用到了一个设计模式:装饰设计模式

对一组类进行功能的增强

包装:写一个类对被包装对象进行包装

1.包装类和被包装对象要实现同样接口

2.包装类要持有一个呗包装的对象

3.包装类在实现接口时,大部分方法是靠调用被包装对象来实现,对于需要修改的方法我们自己实现


字符流

Reader

|--BufferedReader 从字符输入流中读取文本,缓冲字符,实现字符数组和行的高效读取

可以指定缓冲区大小,可使用默认大小

    |--LineNumberReader 跟踪行号的缓冲字符输入流。此类定义了setLineNumber(int) 和getLineNumber() 来设置和获取行号

|--InputStreamReader 是字节流通向字符流的桥梁

   |--FileReader 用来读取字符文件的便捷类

|--CharArrayReader

|--StringReader



Writer 

|---BufferedWriter 将文本写入字符输出流,缓冲各个字符,从而提供单个字符,数组,字符串的高效写入

|--OutputStreamWriter 字符流通向字节流的桥梁

|--FileWriter 用来写入字符文件的便捷类

|--PrintWriter 

|--CharArrayWriter

|--StringWriter


字节流

InputStream

|--FileInputStream  从文件系统中的某个文件中获得输入字节,哪些文件可用取决于主机环境

用于读取图像数据之类的原始字节流

|--FilterInputStream 包含其他一些输入流,将这些流用作基本数据源,它可以直接传输数据或提供一些额外功能

|--BufferedInputStream 该类实现缓冲的输入流

|--Stream

|--ObjectInputStream

|--PipedInputStream


OutputStream 抽象类是表示输出字节流的所有类的超类

|--FileOutputStream 文件输出流是用于将数据写入File或FileDescriptor输出流

|--FilterOutputStream 此类是过滤输出流的所有类的超类

|--BufferedOutputStream 该类实现缓冲的输出流

|--PrintStream

|--DataOutputStream

|--ObjectOutputStream

|--PipedOutputStream


缓冲区是提高效率用的,给谁提高呢

BufferedWriter:是给字符输出流提高效率用的,那就意味着,缓冲区对象建立时,必须要先有流对象,明确要提高具体的流对象的效率

FileWriter fw = new FileWriter("bufdemo.txt")

BufferedWriter bufw = new BufferedWriter(fw); //让缓冲区和指定流相关联

for(int x = 0 ; x < 4 ; x ++)

{

bufw.write(x+"abc")';

bufw.newLine(); //写入一个换行符

bufw.flush();

}

bufw.close(); 关闭缓冲区,其实就是关闭具体的流


BufferedReader 

FileReader fr = new FileReader("bufdemo.txt");

BufferedReader bufr = new BufferedReader(fr);

String line = null;

while((line=bufr.readLine())!=null)

{

System.out.println(line) ;

}

bufr.close();


记住,只要一读取键盘录入就用

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

输出控制台

BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));

String line = null;

while((line=bufr.readLine())!= null)

{

if("over".equals(line))

{

break;

}

bufw.write(line.toUpperCase());

bufw.newLine();

bufw.flush();

}

bufw.close();

bufr.close();


流的操作规律

1.明确源和目的

数据源:需要读取,InputStream Reader

数据汇:需要写入,OutputStream Writer

2.操作的数据是否为纯文本

如果是,数据源 Reader

数据汇:Writer

如果不是 数据源:InputStream

数据汇: OutputStream

3.虽然确定了一个体系,但是该体系中有太多的对象,到底用哪个

明确操作的数据设备

数据源对应的设备:硬盘(File) 内存(数组) 键盘(System.in)

数据汇对应的设备:硬盘(File),内存(数组),控制台(System.out)

4.需要在基本操作上附加其他功能吗?

比如缓冲

如果需要就进行装饰


转换流特有功能:将字节转成字符

File的读取有局限,因为只能使用默认编码

FileReader fr = new FileReader("a.txt");

所以

InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"),"gbk");

所以,需要自定义编码表,使用转换流

不需要,则使用转换流的子类File


凡是操作设备上的文本数据,涉及编码转换,必须使用转换流


File类:万物皆对象,将文件系统中的文件和文件夹封装成对象,提供了更多的属性和行为可以对这些文件和文件夹进行操作

这些是流对象办不到的,因为流只操作数据


File常见方法

1.创建

boolean createNewFile() 在指定目录创建,如果已存在,则不创建。

boolean mkdir(); 创建此抽象路径名指定的目录

boolean mkdirs() 创建多级目录

2.删除

boolean delete() 删除此抽象路径名表示的文件或目录

void deleteOnExit() 在虚拟机退出时删除

注意:在删除文件夹时,必须保证这个文件夹中没有任何内容,才可以将该文件夹用delete删除

3.获取

long length() 获取文件大小

String getName() 返回由此抽象路径名表示的文件或目录的名称

String getPath() 将此抽象路径名转换成一个路径字符串

String getAbsolutePath() 返回此抽象路径名的绝对路径名字符串

String getParent() 返回此抽象路径名父目录的抽象路径名,如果此路径名没有指定父目录,则返回null

long lastModified() 返回此抽象路径名表示的文件最后一次被修改的时间

File.pathSeparator  返回当前系统默认路径分隔符

File.Separator 返回当前默认目录分割符

4.判断

boolean exists() 判断文件或者文件夹是否存在

boolean isDirectory() 测试此抽象路径名表示的文件是否是一个目录

boolean isFile() 测试此抽象路径名表示的文件是否是一个标准文件

boolean isHidden() 是否是一个隐藏文件

boolean isAbsolute() 是否为绝对路径名


5.重命名

boolean renameTo(File dest) 是否修改成功


String[] list() 列出指定目录下的当前的文件和文件夹的名称,包含隐藏文件

如果调用list方法的file对象中的封装的是一个文件,那么list方法返回数组为null。

如果封装的对象不存在也会返回null。所以只有封装的对象存在并且是文件夹时才有效


Properties 一个可以将键值进行持久化存储的对象

用于属性配置文件。

1.持久化存储数据 2.键值都是字符串 3.用于配置文件


|--load() 将流中的数据加载进集合

原理:其实就是将读取流和指定文件相关联,并读取一行数据,因为数据是规则的key=value,所以获取一行后,通过=对该行数据进行切割

左边就是键,右边就是值,将键,值存储到Properties集合中

|--store() 写入各个项后,刷新输出流

|--list() 将集合的键值数据列出到指定目的地



扩展功能流对象:装饰设计模式

outputstream.PrintStream  打印流

1.提供更多功能,比如打印

2.有自动刷新机制

3.使用默认编码

4.不抛出IOException


构造:

PrintStream(File file)  :创建具有指定文件且不带自动行刷新的新打印流。

PrintStream(File file, String csn) :创建具有指定文件名称和字符集且不带自动行刷新的新打印流。

PrintStream(OutputStream out) :创建新的打印流。

PrintStream(OutputStream out, boolean autoFlush) :创建新的打印流。

PrintStream(OutputStream out, boolean autoFlush, Stringencoding) :创建新的打印流。

PrintStream(String fileName) :创建具有指定文件名称且不带自动行刷新的新打印流。

PrintStream(String fileName, String csn) 


PrintStream可以操作目的: 1.File对象 2.字符处路径 3.字节输出流

当目的是一个字节输出流时,使用println方法,可以再printStream对象上加入一个true参数

即可自动刷新。并且不用抛出异常


操作数据如果都是字符串,则使用PrintWriter

对象目的: 1.File对象 2.字符串路径 3.字节输出流 4.字符输出流


开发时尽量使用PrintWriter


方法中直接操作文件的第二参数是编码表

直接操作输出流的是True 即自动刷新


//读取键盘录入将数据转成大写显示在控制台.

BufferedReader bufr = new BufferedReader(newInputStreamReader(System.in));//源:键盘输入

//目的:把数据写到文件中,还想自动刷新。

PrintWriter out = new PrintWriter(new FileWriter("out.txt"),true);//设置true后自动刷新

String line = null;

while((line=bufr.readLine())!=null){

    if("over".equals(line))

        break;

    out.println(line.toUpperCase());//转大写输出

}

//注意:System.in,System.out这两个标准的输入输出流,在jvm启动时已经存在了。随时可以使用。当jvm结束了,这两个流就结束了。但是,当使用了显示的close方法关闭时,这两个流在提前结束了。

out.close();

bufr.close();


SequenceInputStream 序列流 作用 将多个读取流合并成一个读取流。实现数据合并

RandomAccessFile: 操作的必须是文件。内部封装了字节读取和字节写入

自身定义了一个byte数组,可以通过方法获取和设置指针的位置

PipedInputStream 

PipedOutputStream   管道流

DataOutputStream  DataInputStream  专门用于操作基本数据类型数据的对象


操作数组元素的流

ByteArrayInputStream  源:内存

ByteArrayOutputStream 目的:内存


例1:键盘敲入转换大写再打印

import java.io.*;


class TransStreamDemo
{
public static void main(String[] args) throws IOException  //一定要抛出异常。
{
//获取键盘录入对象
InputStream in = System.in();


//将字节流对象转成字符流对象,使用转换流。
InputStreamReader isr = new InputStreamReader(in);


//为了提高效率,将字符串进行缓冲区技术高效操作,使用BufferedReader
BufferedReader bufr = new BufferedReader(isr);

上述三句话可以归为一句

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


//按行读取
String line = null;


while ((line = bufr.readLine())!=null)
{
if ("over".equals(line))
{
break;
}
System.out.println(line.toUpperCase());
}
bufr.close();
}
}


例二 装饰类,在本类基础上扩展功能

class Person
{
public void chifan()
{
sop("吃饭");
}
}


class SuperPerson
{
private Person p ;
SuperPerson(Person p)
{
this.p = p;
}
public void superChifan()
{
sop("开胃酒");
p.chifan();
sop("甜点");
}
}


class  PersonDemo
{
public static void main(String[] args) 
{
Person p = new Person();
SuperPerson sp = new SuperPerson(p);
sp.superChifan();
}
}


例3:MP3复制

/*
MP3的复制,通过缓冲区
*/


import java.io.*;
class  CopyMp3
{
public static void main(String[] args) throws IOException 
{
long start = System.currentTimeMillis();
copy_1();
long end = System.currentTimeMillis();
System.out.println((end-start)+"毫秒");
}


//通过字节流的缓冲区完成复制
public static void copy_1()
{

//创建缓冲输入流,源:1.3gp    
BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("f:\\1.3gp"));

//创建缓冲输出流  目的: 2.3gp
BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("f:\\2.3gp"));

//因为read返回的值是当前字符的角标
int by = 0;


while ((by=bufis.read())!=-1)
{
bufos.write(by);
}


bufos.close();
bufis.close();
}




}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值