------- android培训、java培训、期待与您交流! ----------
IO流
a)IO流的作用:
1.IO流用来处理设备之间的数据传输。
2.Java对数据的操作是通过流的方式。
3.Java用于操作流的对象都在IO包中。
4.流按操作数据分为两种:字节流和字符流。
5.流按流向分为:输入流和输出流。
b)IO流常用基类
1.字节流的抽象基类:InputStrem OutputStream。
2.字符流的抽象基类:Reader Writer。
注:由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。
Eg:InputStream的子类 FileInputStream
Reader的子类FileReader
字符流
FileWriter 文件写入流
import java.io.*;
class FileWriterDemo
{
public static void main(String[] args) throws IOException//读写都会发生异常
{
//创建一个FileWriter对象。该对象一被初始化就必须要明确被操作的文件。
//而且该文件会被创建到指定目录下。如果该目录下已有同名文件,将被覆盖。
//其实该步就是在明确数据要存放的目的地。
FileWriter fw = new FileWriter("demo.txt");
//调用write方法,将字符串写入到流中。
fw.write("abcde");
//刷新流对象中的缓冲中的数据,将数据刷到目的地中。
fw.flush();
//关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据。
//将数据刷到目的地中。
fw.close();
}
}
Close和flush区别:flush刷新后,流可以继续使用;
close刷新后,会将流关闭,该方法主要用于结束调用的底层资源,这个动作一定要做。
对文件写入流的异常处理
import java.io.*;
class FileWriterDemo2
{
public static void main(String[] args)
{
FileWriter fw = null;//在外边建立引用,在try内进行初始化
try
{
fw = new FileWriter("demo.txt");
fw.write("abcdefg");
}
catch (IOException e)
{
System.out.println("catch:"+e.toString());
}
finally
{
try
{
if(fw!=null)
fw.close();
}
catch (IOException e)
{
System.out.println(e.toString());
}
}
}
}
补充一点:如果想不覆盖已有的文件并在文件的末尾处进行数据的续写,那么只需要传递一个true参数
FileWriter fw = newFileWriter("demo.txt",true);
FileReader 文件读取流
方式一:FileReader使用Reader体系,读取一个文本文件中的数据,返回-1,标志读到文件末尾
import java.io.*;
class FileReaderDemo
{
public static void main(String[] args) throws IOException
{
//创建一个文件读取流对象,和指定名称的文件相关联。
//要保证该文件是已经存在的,如果不存在,会发生异常 FileNotFoundException
FileReader fr = new FileReader("demo.txt");
int ch = 0;
//调用Reader的read方法,read():一次读一个字符。而且会自动往下读。
while((ch=fr.read())!=-1)
{
System.out.println((char)ch);
}
fr.close();
}
}
方式二:通过字符数组进行读取。
import java.io.*;
class FileReaderDemo2
{
public static void main(String[] args) throws IOException
{
//创建读取流和指定的文件相关联
FileReader fr = new FileReader("demo.txt");
//定义一个字符数组。用于存储读到字符。
//该read(char[])返回的是读到字符个数。
char[] buf = new char[1024];
int num = 0;
while((num=fr.read(buf))!=-1)
{
System.out.println(new String(buf,0,num));
}
fr.close();
}
}
练习:
复制一个文件 从某地到某地
复制的原理:其实就是将源文件的数据存储到新文件中
步骤:
1 创建一个文件 用于存储源文件数据
2 定义一个读取流和原文件关联
3 通过不断的读写完成数据存储
4 关闭资源
代码如下:
import java.io.*;
public class FlieReaderTest
{
public static void main(String[] args) throws IOException
{
FileReader fr = new FileReader("text.txt");
FileWriter fw = newFileWriter("textNew.txt");
char[] buf = new char[1024];
int num = 0;
while((num = fr.read(buf)) != -1)
{
fw.write(buf,0,num);
fw.flush();
}
fr.close();
fw.close();
}
}
字符流的缓冲区
对应类: BufferedWriter BufferedReader
缓冲区的出现是为了提高流的操作效率而出现的。所以在创建缓冲区之前必须要现有流对象 。
BufferedWriter是给字符输出流提高效率应用的。
import java.io.*;
class BufferedWriterDemo
{
public static void main(String[] args) throws IOException
{
//创建一个字符写入流对象。
FileWriter fw = new FileWriter("buf.txt");
//为了提高字符写入流效率。加入了缓冲技术。
//只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即 可。
BufferedWriter bufw = new BufferedWriter(fw);
for(int x=1; x<5; x++)
{
bufw.write("abcd"+x);
bufw.newLine();//跨平台的换行符
bufw.flush();
}
//只要用到缓冲区,就要刷新。
bufw.flush();
//其实关闭缓冲区,就是在关闭缓冲区中的流对象。
bufw.close();
}
}
BufferedReader是给字符读取流提高效率应用的
import java.io.*;
class BufferedReaderDemo
{
public static void main(String[] args) throws IOException
{
//创建一个读取流对象和文件相关联。
FileReader fr = new FileReader("buf.txt");
//为了提高效率。加入缓冲技术。将字符读取流对象作为参数传递给缓 冲对象的构造函数。
BufferedReader bufr = new BufferedReader(fr);
String line = null;
//一次读一行的方法 readLine,方便于对文本数据的获取,当返回null 时,表示读到文件末尾。
while((line=bufr.readLine())!=null)//readLine方法返回的时候只返回回车符之前的数据内容。并不返回回车符。
{
System.out.print(line);
}
bufr.close();
}
}
练习:
通过缓冲区复制一个文件。
import java.io.*;
class CopyTextByBuf
{
public static void main(String[] args)
{
BufferedReader bufr = null;
BufferedWriter bufw = null;
try
{
bufr = new BufferedReader(newFileReader("text.txt"));
bufw = new BufferedWriter(newFileWriter("newText.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("写入关闭失败");
}
}
}
}
例:自定义BufferedReader类中的readLine方法 模拟BufferedReader
import java.io.*;
class MyBufferedReader extendsReader
{
private Reader r;
MyBufferedReader(Reader r)
{
this.r = r;
}
//可以一次读一行数据的方法。
public String myReadLine()throws IOException
{
//定义一个临时容器。原BufferReader封装的是字符数组。
//为了演示方便。定义一个StringBuilder容器。因为最终还是要将数据变成字符串。
StringBuilder sb = new StringBuilder();
int ch = 0;
while((ch=r.read())!=-1)
{
if(ch=='\r')
continue;
if(ch=='\n')
return sb.toString();
else
sb.append((char)ch);
}
if(sb.length()!=0)
return sb.toString();
return null;
}
/*
覆盖Reader类中的抽象方法。
*/
public int read(char[] cbuf, int off, int len) throwsIOException
{
return r.read(cbuf,off,len) ;
}
public void close()throws IOException
{
r.close();
}
public void myClose()throws IOException
{
r.close();
}
}
class MyBufferedReaderDemo
{
public static void main(String[] args) throws IOException
{
FileReader fr = new FileReader("buf.txt");
MyBufferedReader myBuf = new MyBufferedReader(fr);
String line = null;
while((line=myBuf.myReadLine())!=null)
{
System.out.println(line);
}
myBuf.myClose();
}
}
装饰设计模式:
1.当想要对已有的对象进行功能增强时,
可以定义类,将已有对象传入,基于已有的功能,并提供加强功能。
那么自定义的该类称为装饰类。
装饰类通常会通过构造方法接收被装饰的对象。
并基于被装饰的对象的功能,提供更强的功能。
2.装饰和继承的区别:
装饰模式比继承要灵活。避免了继承体系臃肿。
而且降低了类于类之间的关系。
3.装饰类的特点:
装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能。所以装饰类和被装饰类通常是都属于一个体系中的。
自定义装饰类:
import java.io.*;
class MyLineNumberReaderextends MyBufferedReader
{
private int lineNumber;
MyLineNumberReader(Reader r)
{
super(r);
}
public String myReadLine()throws IOException
{
lineNumber++;
return super.myReadLine();
}
public void setLineNumber(int lineNumber)
{
this.lineNumber = lineNumber;
}
public int getLineNumber()
{
return lineNumber;
}
}
class MyLineNumberReader
{
private Reader r;
private int lineNumber;
MyLineNumberReader(Reader r)
{
this.r = r;
}
public String myReadLine()throws IOException
{
lineNumber++;
StringBuilder sb = new StringBuilder();
int ch = 0;
while((ch=r.read())!=-1)
{
if(ch=='\r')
continue;
if(ch=='\n')
return sb.toString();
else
sb.append((char)ch);
}
if(sb.length()!=0)
return sb.toString();
return null;
}
public void setLineNumber(int lineNumber)
{
this.lineNumber = lineNumber;
}
public int getLineNumber()
{
return lineNumber;
}
public void myClose()throws IOException
{
r.close();
}
}
class MyLineNumberReaderDemo
{
public static void main(String[] args) throws IOException
{
FileReader fr = newFileReader("copyTextByBuf.java");
MyLineNumberReader mylnr = new MyLineNumberReader(fr);
String line = null;
mylnr.setLineNumber(100);
while((line=mylnr.myReadLine())!=null)
{
System.out.println(mylnr.getLineNumber()+"::"+line);
}
mylnr.myClose();
}
}
字节流
FileInputStreamFileOutputStream
BufferedInputStreamBufferedOutputStream
a)基本操作与字符流相同,但是它不仅仅可以操作字符,还可以操作其他的媒体文件。
b)字节流的缓冲区同样是提高了字节流的读取效率。
复制一个图片
思路:
1,用字节读取流对象和图片关联。
2,用字节写入流对象创建一个图片文件。用于存储获取到的图片数据。
3,通过循环读写,完成数据的存储。
4,关闭资源。
import java.io.*;
class CopyPic
{
public static void main(String[] args)
{
FileOutputStream fos = null;
FileInputStream fis = null;
try
{
fos = newFileOutputStream("c:\\2.bmp");
fis = newFileInputStream("c:\\1.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("写入关闭失败");
}
}
}
}
练习模拟BufferedInputStream
import java.io.*;
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)
{
count = in.read(buf);
if(count<0)
return -1;
pos = 0;
byte b = buf[pos];
count--;
pos++;
return b&255;
}
else if(count>0)
{
byte b = buf[pos];
count--;
pos++;
return b&0xff;
}
return -1;
}
public void myClose()throws IOException
{
in.close();
}
}
读取转换流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);
//键盘的最常见写法。上面三句话的综合写法
BufferedReader bufr =
new BufferedReader(newInputStreamReader(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();
}
bufr.close();
}
}
写入转换流OutputStreamWriter
BufferedWriter bufw =new BufferedWriter (new OutputStreamWriter(System.out));
键盘录入和读取
BufferedReader bufr = newBufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw = newBufferedWriter(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、是否需要提高效率
是就用缓冲类
------- android培训、java培训、期待与您交流! ----------