IO流学习日志

流的分类:字节流、字符流

字节流两个基类:(×××InputStream   ×××OutputStream)

FileInputStream BufferedInputStream

FileOutputStream BufferedOutputStream

 

字符流两个基类:(×××Reader ×××Writer)

FileWriter BufferedWriter

FileReader BufferedReader 

(注:后缀名是父类名,前缀名是该流对象的功能。)

 

复制文件的原理和代码

原理:

首先用一个读取流对象和一个文件进行关联,然后用一个写入流对象作为目地的,

为了把读取流中的文件传输到目的地流对象中,我们就提供了一个字符数组,

为了关联这个数组,所以读取流对象有一个read()方法与这个字符数组进行关联,

同理,写入流对象也有一个write()方法与这个字符数组进行关联,

这样两个流对象就相连接了,而这个字符数组就相当于一个中转站。

 

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

/*

 对文本文件进行复制。将c盘的文件复制到d盘中。

 原理:其实就是一个最简单的读写过程。

 从c盘源,读取数据,并将读到的数据,写入到目的d盘中。

 */

public class CopyTextFileTest {

public static void main(String[] args) {

FileReader fr = null;

FileWriter fw = null;

try {

//1,创建一个字符读取流读取与源数据相关联。

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

//2,创建一个存储数据的目的地。

fw = new FileWriter("copyDemo.txt");

//3,创建一个字符数组将读取流对象和写入流对象相连接。

char[] buf = new char[1024];

//4,每次读取的长度不一样,所以定义一个变量.

int len = 0;

//5,用循环读取文件中的数据

while((len= fr.read(buf)) != -1) //判断是否读取完没

fw.write(buf,0,len); //为了只读取有效的数据

} catch (Exception e) {

}finally{

try {

fr.close();

} catch (IOException e) {

e.printStackTrace();

}

try {

fw.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

 

 

读取字符流对象的两种方式

第一种读取方式  一次读一个字符

  //1,创建一个文件读取流对象,和指定名称的文件相关联

        //2,要保证该文件时已经存在的。如果不存在,会发生异常。FileNotFoundException

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

        //3,调用读取流的方法,read方法一次读一个字符,而且会自动往下读。

        int line=0;      //read返回时int型的数,即返回的是字符的ascII表对应的数字

        while ((line=fr.read())!=-1)

        {

             sop((char)ch);

        }

    第二种读取方式 

        //1,创建一个文件读取流对象,和指定名称的文件相关联

        //2,要保证该文件时已经存在的。如果不存在,会发生异常。FileNotFoundException

        FileReader fr = new FileReader("Demo.txt");   //Demo.txt中的数据读到控制台

        //3,定义一个字符数组,用于存储独到的字符该read(char[]) //返回的是读到字符的个数

        char[] buf = new char[1024];

        int len=0;

        while((len=fr.read(buf))!=-1)  //把读到的字符暂时存到buf数组中

        {

           sop("num="+num+"...."+new String(buf,0,len));

        }

缓冲区

(BufferedInputStream  BufferedOutputStream  BufferedWriter  BufferedReader)

缓冲区内部将数组进行封装。变成对象后,方便于对缓冲区的操作,提高效率,并提供了对文本便捷操作的方法:readLine,newLine。

 

自定义缓冲区,MyBufferedReader

import java.io.IOException;

import java.io.Reader;

 

/*

 模拟一个缓冲区

 基于已有的缓冲区思想,我们可以从源读取用read方法。

 我们的缓冲区,应该是一个更高效的read读取方法。

 */

public class MyBufferTest extends Reader{

private Reader r;

private char[] buf = new char[1024];

private int count = 0,pos = 0;

public MyBufferTest(Reader r){

this.r = r;

}

/*

 一次从缓冲区中取一个

 */

public int myRead() throws IOException {

//1,首先判断缓冲区中是否有数据,如果没有就从源中去拿。

if(count == 0){

count = r.read(buf);

pos = 0;

}

//2,当缓冲区中没数据了且源中也没有数据时,count自减1小于0时就返回-1结束.

if(count < 0)

return -1;

//3,如果以上都不满足,那么从缓冲区中写入一个字符到新的文件中。

char ch = buf[pos];

pos++;

count--;

return ch;

}

/*

 按照文本特点,提供一个特有的操作文本的方法。

 一次读取一行文本,只要是到行结束符之前的文本即可。

 原理:

 就是从缓冲区中取出数据,并存储到一个临时容器中。

 如果取到了回车符,就将临时容器中的数据转成字符串返回。

 */

public String myReadLine() throws IOException{

//1,定义一个临时容器,进行临时存储

StringBuilder sb = new StringBuilder();

//2,定义一个变量,接收读取到的字符,也就是转成ask码表后的一个int型数字

int ch = 0;

while((ch = myRead()) != -1){

//3,当读取到\r时,直接跳出本次循环

if(ch == '\r')

continue;

//4,当读取到\n时,直接跳出当前循环

if(ch == '\n')

return sb.toString();

//5,当都没有读取到时,就将这些数据存储到临时容器中。

sb.append((char)ch);

}

//6,当临时容器中的长度不等于0时,就输出字符。

if(sb.length() != 0)

return sb.toString();

return null;

}

public void close() throws IOException {

}

public int read(char[] arg0, int arg1, int arg2) throws IOException {

return 0;

}

}

 

 

装饰设计模式

当想要对已有的对象进行功能增强时,

可以定义类,将已有对象传入,基于已有的功能,并提供加强功能。

那么自定义的该类称为装饰类。

 

装饰类通常会通过构造方法接收被装饰的对象。

并基于被装饰的对象的功能,提供更强的功能。

 

class Person

{

public void chifan()

{

System.out.println("吃饭");

}

}

 

class SuperPerson 

{

private Person p ;

SuperPerson(Person p)

{

this.p = p;

}

public void superChifan()

{

System.out.println("开胃酒");

p.chifan();

System.out.println("甜点");

System.out.println("来一根");

}

}

 

class  PersonDemo

{

public static void main(String[] args) 

{

Person p = new Person();

 

//p.chifan();

SuperPerson sp = new SuperPerson(p);

sp.superChifan();

}

}

 

File

作用:1、用来将文件或者文件夹封装成对象

             2、方便对文件与文件夹的属性信息进行操作。

      3、File对象可以作为参数传递给流的构造函数。

File对象基本使用

创建:

boolean createNewFile():创建一个新的空文件,不过该文件已存在,就不会创建

boolean mkdir():创建指定的目录

boolean mkdirs():创建指定的目录已经父目录

删除:

boolean delete():删除文件或目录

void deleteOnExit():虚拟机结束时,会自动删除指定的文件或目录

获取:

String getAbsolutePath():绝对路径

String getPath():相对路径

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

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

long length():返回此路径名表示的文件的长度

long lastModified():返回此文件最后一次被修改的时间

判断:

boolean exists():判断此路径名表示的文件或目录是否存在

boolean isFile():判断此路径名表示的文件或目录是否是一个标准的文件

boolean isDirectory():判断此路径名表示的文件或目录是否是一个目录

 

 

IO中的其他功能流对象:

打印流:

PrintStream:

特点:

1、构造函数可接收File对象,字符串路径,字节输出流。意味着打印目的可以有很多。

2、该对象具备特有的方法 打印方法print println,可以任何类型的数据。

3、特有的print方法可以保持任意类型的数据表现形式的原样性,将数据输出到目的地。

而对于OutputStream父类中的write方法,是将数据的最低字节写出去。

 

PrintWriter:

特点:

1、当操作的数据是字符时,可以选择PrintWriter,比PrintStream要方便。

2、它的构造函数可以接收File对象,字符串路径,字节输出流,字符输出流。

3、构造函数中,如果参数是输出流,那么可以通过指定另一个参数true完成自动刷新,该trueprintln方法有效。

 

序列流:

SequenceInputStream:

特点:

1,将多个字节读取流合并成一个读取流,将多个源合并成一个源,操作起来更方便

2,需要的枚举接口可以通过Collections.enumeration(collection)

 

 

IO流的操作规律总结:

1,明确体系:

数据源:InputStream Reader

数据汇:OutputStreamWriter

2,明确数据:因为数据分两种:字节,字符。

数据源:是否是纯文本数据呢?

是:Reader

否:InputStream

数据汇:

是:Writer

否:OutputStream

到这里就可以明确具体要使用哪一个体系了。

剩下的就是要明确使用这个体系中的哪个对象。

 

3,明确设备:

数据源:

键盘:System.in

硬盘:FileXXX

内存:数组。

网络:socket

数据汇:

控制台:System.out

硬盘:FileXXX

内存:数组

网络:socket

4,明确额外功能:

1,需要转换?是,使用转换流。InputStreamReader OutputStreamWriter

2,需要高效?是,使用缓冲区。Buffered

3,需要其他?

1, 复制一个文本文件。

1,明确体系:

源:InputStream Reader

目的:OutputStream Writer

2,明确数据:

源:是纯文本吗?是 Reader

目的;是纯文本吗?是 Writer

3,明确设备:

源:硬盘上的一个文件。 FileReader

目的:硬盘上的一个文件。FileWriter

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

FileWriter fw = new FileWriter("b.txt");

4,需要额外功能吗?

需要,高效,使用buffer

BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));

BufferedWriter bufw = new BufferedWriter(new FileWriter("b.txt"));

2, 读取键盘录入,将数据存储到一个文件中。

1,明确体系:

源:InputStream ,Reader

目的:OutputStream ,Writer

2,明确数据:

源:是纯文本吗?是 Reader

目的;是纯文本吗?是 Writer

3,明确设备:

源:键盘,System.in

目的:硬盘,FileWriter

InputStream in = System.in;

FileWriter fw = new FileWriter("a.txt");

4,需要额外功能吗?

需要,因为源明确的体系时Reader。可是源的设备是System.in。

所以为了方便于操作文本数据,将源转成字符流。需要转换流。InputStreamReader

InputStreamReader isr = new InputStreamReader(System.in);

FileWriter fw  = new FileWriter("a.txt");

需要高效不?需要。Buffer

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

BufferedWriter bufw = new BufferedWriter(new FileWriter("a.txt"));

3, 读取一个文本文件,将数据展现在控制台上。

1,明确体系:

源:InputStream ,Reader

目的:OutputStream ,Writer

2,明确数据:

源:是纯文本吗?是 Reader

目的;是纯文本吗?是 Writer

3,明确设备:

源:硬盘文件,FileReader。

目的:控制台:System.out。

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

OutputStream out = System.out;

4,需要额外功能?

因为源是文本数据,确定是Writer体系。所以为了方便操作字符数据,

需要使用字符流,但是目的又是一个字节输出流。

需要一个转换流,OutputStreamWriter

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

OutputStreamWriter osw = new OutputStreamWriter(System.out);

需要高效吗?需要。

BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));

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

4, 读取键盘录入,将数据展现在控制台上。

1,明确体系:

源:InputStream ,Reader

目的:OutputStream ,Writer

2,明确数据:

源:是纯文本吗?是 Reader

目的;是纯文本吗?是 Writer

3,明确设备:

源:键盘:System.in

目的:控制台:System.out

InputStream in = System.in;

OutputStream out = System.out;

4,需要额外功能吗?

因为处理的数据是文本数据,同时确定是字符流体系。

为方便操作字符数据的可以将源和目的都转成字符流。使用转换流。为了提高效率,使用Buffer

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

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

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值