----------------------android培训、java培训、期待与您交流! ----------------------
几乎所有程序都离不开信息的输入和输出,比如从键盘读取数据 ,从文件中获取或者向文件存入数据、在显示器上显示数据,以及在网络连接上进行信息交互时,都会涉及有关输入/输出的处理。在JAVA中,把这些不同类型的输入、输出源抽象为流(Stream),而其中输入或输出的数据则称为数据流(data Stream).用统一的接口来表示。
数据流:是指一组有顺序的,有起点和终点的字节集合
数据流最粗略的分法:输入数据流(Input Stream)输出数据流(Output Stream)
一、IO(Input Output)流
- IO流用来处理设备之间的数据传输
- JAVA对数据的操作是通过流的方式
- JAVA用于操作流的对象都在IO包中
- 流按操作数据分为两种:字节流与字符流
- 流按流向分为:输入流,输出流
- IO流常用基类:字节流的抽象基类(InputStream,OutputStream),字符流的抽象基类(Reader,Writer)
注:由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀
如:InputStream的子类FileInputStream
Reader的子类FileReader
1.字符流
从JDK1.1开始,java.io包中加入了专门用于字符流处理的类,它们是以Reader和Writer为基础派生的一系列类。
既然IO流是用于操作数据的,那么数据的最常见体形式是文件。
演示:写
(1)需求:在硬盘上,创建一个文件并写入一些文字数据
import java.io.*;
class FileWriterDemo
{
public static void main(String[] args) throws IOException
{
//创建一个FileWriter对象,该对象一被初始化就必须要明确被操作的文件而且该文件
//会被创建到指定目录下.
//如果该目录下已有同名文件,将被覆盖,其实该步就是在明确数据要存放的目的地.
FileWriter fw=new FileWriter("demo.txt");
fw.write("dkfjdjfidfifiefe");//调用write方法,将字符串写入到流中
fw.flush();//刷新流对象中的缓冲区中的数据将数据刷新到目的地
fw.close();//关闭流资源,但是关闭之前会刷新一次部缓冲区中的数据
}
}
注:flush():刷新流对象中的缓冲区中的数据,将数据刷新到目的地
close():关闭流资源,但是关闭之前会刷新一次内部的缓冲区数据,将数据刷新到目的地,
区别:flush()刷新后,流可以继续使用,close()刷新后,会将流关闭
(2) IO异常处理方式
import java.io.*;
class FileWriteDemo2
{
public static void main(String[] args)
{
FileWrite fw=null;
try
{
fw=new FileWrite("Demo.txt");
fw.write("fdjfijfiejfiegdfd");
}
catch(IOException e)
{
System.out.println(e.toString());
}
finally
{
try
{
if(fw!=null)
fw.close();
}
catch(IOException e)
{
System.out.println(e.toString());
}
}
}
}
(3)对已有文件的数据续写
import java.io.*;
class FileWriterDemo3
{
public static void main(String[] args) throws IOException
{
//传递一个true参数,代表不覆盖已有的文件,并在已有文件的末尾处
//进行数据续写.
FileWriter fw=new FileWriter("demo.txt",true);
fw.write("haha");
fw.write("nihao\r\nxiexie");//在windows下换行是用\r\n来识别的
fw.close(); //关闭流资源
}
}
演示:读
(1)文本文件读取方式一
import java.io.*;
class FileReaderDemo
{
public static void main(String[] args) throws IOException
{
//创建一个文件读取流对象和指定名称的文件相关联.
//要保证该文件是已经存在的,如果不存在,
//会发生异常FileNotFoundException
FileReader fr=new FileReader("demo.txt");
//调用读取流对象的read()方法,一次读一个字符而且会往下读,返回一个Int数
int ch=0;
while((ch=fr.read())!=-1)
{
System.out.println((char)ch);
}
}
}
(2) 文本文件读取方式二:通过字符数组进行读取
import java.io.*;
class FileReaderDemo2
{
public static void main(String[] args) throws IOException
{
FileReader fr=new FileReader("demo.txt");
char[] buf=new char[1024];//定义一个字符数组,用于存储读到的字符
int num=0;
while((num=fr.read(buf))!=-1)//该read(char[])返回的是读到的字符个数
{
System.out.println(new String(buf,0,num));
}
fr.close();
}
}
演示:读写
(1) 将C盘上的一个文本文件复制到D盘上
复制原理:其实就是将C盘下的文件数据存储到D盘上的一个文件中
步骤:
- 在D盘上创建一个文件,用于存储C盘文件中的数据
- 定义读取流和C盘文件关联
- 通过不断的读写完成数据存储
- 关闭资源
import java.io.*;
class CopyTest
{
public static void main(String[] args)
{
copy();
}
public static void copy()
{
FileReader fr=null;
FileWriter fw=null;
try
{
fr=new FileReader("SystemDemo.java");
fw=new FileWriter("SystemDemo_copy.txt");
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
{
try
{
if(fr!=null)
fr.close();
}
catch(IOException e)
{
throw new RuntimeException("读取流关闭失败");
}
try
{
if(fw!=null)
fw.close();
}
catch(IOException e)
{
throw new RuntimeException("写入流关闭失败");
}
}
}
}
2.字符流的缓冲区
- 缓冲区的出现提高了对数据的读写效率
- 对应类:BufferedWriter 将文本写入字符输出流,缓冲各个字符,从而提供单个字符,数组和字符串的高效写入
BufferedReader从字符输入流中读取文本,缓冲各个字符,从而实现字符,数组和行的高效读取
- 缓冲区要结合流才可以使用
- 在流的基础上对流的功能进行了增强
- 缓冲区的出现是为了提高流的操作效率而出现的所以在创建缓冲区之前,必须要先有流对象
- 该缓冲区中提供了一个跨平台的换行符:newLine();
- 字符读取流缓冲区提供了一个一次读一行的方法readLine(),方便于对文本数据的获取,当返回null时,表示读到文件末尾
演示:BufferedWriter缓冲区的应用
import java.io.*;
class BufferedWriterDemo
{
public static void main(String[] args)
{
//创建一个字符写入流对象
FileWriter fw=new FileWriter("buf.txt");
//为了提高字符写入流效率,才加入了缓冲技术,
//只要将需要被提高效率的流对象作为参数传递给
//缓冲区的构造函数即可.
BufferedWriter bufw=new BufferedWriter(fw);
bufw.write("fdfeggrrwaf");
bufw.flush();//只要用到缓冲区,就要记得刷新
bufw.close();//关闭缓冲区,其实就是在关闭缓冲区中的流对象
}
}
演示:BufferedReader字符读取流缓冲区的应用
import java.io.*;
class BufferedReaderDemo
{
public static void main(String[] args)
{
//创建一个读取流对象和文件相关联
FileReader fr=new FileReader("buf.txt");
//为了提高读取效率,加入了缓冲区技术,
//将字符读取流对象作为参数传递给缓冲区对象的构造函数
BufferedReader bufr=new BufferedReader(fr);
String line=null;
while((line=bufr.readLine())!=null)
{
System.out.println(line);
}
bufr.close();
}
}
演示:BufferedReader与BufferedWriter
(1) 通过缓冲区复制一个.java文件
提示:readline()方法返回的时候只返回回车符之前的数据内容,并不返回回车符
所以用一个newLine()方法来换行
import java.io.*;
class CopyTextByBuf
{
public static void main(String[] agrs)
{
BufferedReader bufr=null;
BufferedWriter bufw=null;
try
{
bufr=new BufferedReader(new FileReader("BufferedWriterDemo.java"));
bufw=new BufferedWriter(new FileWriter("bufWriter_copy.txt"));
String line=null;
while((line=bufr.readLine())!=null)
{
bufw.write(line);
bufw.newLine();
bufw.flush();
}
}
catch(IOException e)
{
throw new RuntimeException("读写失败");
}
finally
{
try
{
if(bufr!=null)
bufr.close();
}
catch(IOException e)
{
throw new RuntimeException("读取关闭失败");
}
try
{
if(bufw!=null)
bufw.close();
}
catch(IOException e)
{
throw new RuntimeException("写入关闭失败");
}
}
}
}
3.字节流
常用的字节流有FileInputStream和FileOutputStream,这两个类用来进行文件的I/O处理,其数据源或数据终点
都应该是文件。
演示:FileInputStream和FileOutputStream的应用
(1) 复制一张图片文件
思路:
- 用字节读取流对象和图片关联
- 用字节写入流对象创建一个图片文件,用于存储获取到的图片数据
- 通过循环读写,完成数据的存储
- 关闭资源
import java.io.*;
class CopyPic
{
pubic static void main(String[] args)
{
FileInputStream fis=null;
FileOutputStream fos=null;
try
{
fis=new FileInputStream("c:\\1.bmp");
fos=new FileOutputStream("c:\\2.bmp");
byte[] buf=new byte[1024];
int len=0;
while((len=fis.read(buf))!=-1)
{
fos.write(buf,0,len);
}
}
catch(IOException 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("写关闭失败");
}
}
}
}
(2)字节流读写原理
import java.io.*;
class FileStream
{
public static void main(String[]args)throw IOException
{
//readFile_1();
//readFile_2();
readFile_3();
writeFile();
}
public staic void readFile_3()throws IOException
{
FileInputStream fis=new FileInputStream("fos.txt");
byte[] buf=new byte[fis.available()];//定义一个刚刚好的缓冲区,不用再循环了
fis.read(buf);
System.out.println(new String(buf));
fis.close();
}
public static void readFile_2()throws IOException
{
FileInputStream fis=new FileInputStream("fos.txt");
byte[] buf=new byte[1024];
int len=0;
while((len=fis.read(buf))!=-1)
{
System.out.println(new String(buf,0,len));
}
fis.close();//关流是必须的,不论是字符流还是字节流,
}
public static void readFile_1()throw IOException
{
FileInputStream fis=new FileInputStream("fos.txt");
int ch=0;
while((ch=fis.read())!=-1)
{
System.out.println((char)ch);
}
}
public static void writeFile()
{
FileOutputStream fos=new FileOutputStream("fox.txt");
fos.write("kdfiejfie".getBytes());
fos.close();
}
}
(3)演示mp3的复制。通过缓冲区。
//BufferedOutputStream
//BufferedInputStream
import java.io.*;
class
{
public static void main(String[] args)
{
long start=System.currentTimeMillis();
copy_1();
long end=System.currentTimeMillis();
System.out.println((end-start)+"毫秒");
}
//通过字节流的缓冲区完成复制
public static void copy_1() throw IOException
{
BufferedInputStream bufis=new BufferedInputStream(new FileInputStream("c:\\0.mp3"));
BufferedOutputStream bufos=new BufferedOutputStream(new FileOutputStream("c:\\1.mp3"));
int by=0;
while((by=bufis.read())!=-1)
{
bufos.write(by);
}
}
}
注:read方法在提升,将byte提升为int;write方法在降,将int转成byte,这样就可以保证数据最终的一致性。
(4)读取键盘录入:
需求:
通过键盘录入数据
当录入一行数据后就将该行数据进行打印
如果录入的数据是over,那么停止录入
import java.io.*;
class ReadIn
{
public static void main(String[] args)
{
InputStream in=System.in;
StringBuilder sb=new StringBuilder();
while(true)
{
int ch=in.read();
if(ch=='\r')
continue;
if(ch=='\n')
{
String s =sb.toString();
if("over".equals(s))
break;
System.out.println(s.toUpperCase());
sb.delete(0,sb.length());
}
else
sb.append((char)ch)
}
}
}
上例总结:
通过刚才的键盘录入珩数据并打印其大写,发现其实就是读一行数据的原理也就是readLine方法
能不能直接使用readLine方法来完成键盘录入的一行数据的读取呢?readLine方法是字符流BufferReader类
中的方法,而键盘录入的read方法是字节流InputStream的方法,那么能不能将字节流转成字符流再使用
字符流缓冲区的readLine方法呢?
InputStreamReader是字节流通向字符流的桥梁。它使用指定的charset读取字节并将其解码为字符。
每次调用InputStreamReader中的一个read()方法都会导致从底层输入流读取一个或多个字节,要启用
从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节
为了达到最高效率,可要考虑在BufferedReader内包装InputStreamReader(转换流)
演示:
import java.io.*;
class TransStreamDemo
{
public static void main(String[] args)throws IOException
{
//获取键盘录入对象
InputStream in=System.in;
//将字节流对象转成字符流对象,使用转换流 InputStreamReader
InputStreamReader isr=new InputStreamReader(in);
//为了提高效率,将字符串进行缓冲区技术高效操作,使用BufferedReader
BufferedReader bufr=new BufferedReader(isr);
OutputStream out=System.out;
OutputStreamWriter osw=new OutputStreamWriter(out);
BufferedWriter bufw=new BufferedWriter(osw);
String line=null;
while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
bufw.write(line.toUpperCase());
bufw.newLine();
bufw.flush();
System.out.println(line.toUpperCase());
}
bufr.close();
}
}
技巧:
键盘的最常见写法:
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
输出到控制台的最常见写法:
BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(System.out));
流操作的基本规律:
通过三个明确来完成
1.)明确源和目的
源: 输入流 InputStream Reader
目的:输出流OutputStream Writer
2.)操作的数据是否是纯文本
是: 字符流
不是:字节流
3.)当体系明确后,再明确要使用哪个具体的流对象
通过设备来进行区分:
源设备:内存,硬盘,键盘
目的设备:内存,硬盘,控制台
4、缓冲区:
字符流的缓冲区
1.缓冲区的出现提高了对数据的读写效率。
2.对应类:
BufferedWriter:将文本写入字符输出流,缓冲各个字符,从而提供单个字符,数组和字符串的高效写入。
BufferedReader:从字符输入流中读取文本,缓冲各个字符,从而实现字符,数组和行的高效读取。
3.缓冲区要结合流才可以使用。
4.在流的基础上对流的功能进行了增强。
演示:
(1)
import java.io.*;
class BufferedWriterDemo
{
public static void main(String[] args)
{
//创建一个字符写入流对象
FileWriter fw=new FileWriter("buf.txt");
//为了提高字符写入流效率,才加入了缓冲技术
//只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可
BufferedWriter bufw=new BufferedWriter(fw);
bufw.write("agdigjidjfda");
//记住,只要用到缓冲区,就要记得刷新
bufw.fulsh();
//其实关闭缓冲区,就是在关闭缓冲区中的流对象
bufw.close();
}
}
(2)
import java.io.*;
class BufferedReaderDemo
{
public static void main(String[] args)throws IOException
{
//创建一个读取流对象和文件相关联
FileReader fr=new FileReader("buf.txt");
//为了提高效率,加入缓冲区技术 ,将字符读取流对象作为参数传递给缓冲对象的构造函数
BufferedReader bufr=new BufferaedReader(fr);
string line=null;
while(line=bufr.readLine()!=null)
{
System.out.println(line);
}
bufr.close();
}
}
(3)通过缓冲区复制一个.java文件
import java.io.*;
class CopyTextByBuf
{
public static void main(String[] args)
{
BufferedReader bufr=null;
BufferedWriter bufw=null;
try
{
bufr=new BufferedReader(new FileReader("BufferedWriterDemo.java"));
bufw=new BufferedWriter(new FileWriter("bufWriter_Copy.txt"));
String line=null;
while((line=bufr.readLine())!=null)
{
bufw.write(line);
bufw.newLine();
bufw.flush();
}
}
catch(IOException e)
{
throw new RuntimeException("读写失败");
}
finally
{
try
{
if(bufr!=null)
bufr.close();
}
catch(IOException e)
{
throw new RuntimeException("读取关闭失败");
}
try
{
if(bufw!=null)
bufw.close();
}
catch(IOException e)
{
throw new RuntimeException("写入关闭失败");
}
}
}
}
5、装饰设计模式:
当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能,并提供加强功能,那么自定义的该类称为装饰类。装饰类通常会通过构造方法接收被装饰的对象,并基于被装饰的对象的功能,提供更强的功能。
演示:
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();
SuperPerson sp=new SuperPerson(p);
sp.superChifan();
}
=======================
装饰和继承的区别:装饰模式比继承要灵活,避免了继承体系臃肿而且降低了类与类之间的关系
装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强的功能所以装饰类
和被装饰类通常都是属于一个体系中的.
----------------------android培训、java培训、期待与您交流! ----------------------