1.概述
a)IO流用来处理设备之间的数据传输
b)JAVA对数据的操作是通过流的方式
c)JAVA用来操作流的对象都在IO包中
2.分类
a)按操作数据分:字节流和字符流(融合编码表)
b)按流向分: 输入流和输出流
c)节点流:
抽象基类:
-字节流:InputStream OutputStream
-字符流:Reader Writer
d)过滤流:除了上述4个类
3.IO异常标准处理方式
public static void main(String[] args)
{
FileWriter fw=null;
try {
fw = new FileWriter("k:/abc.txt");
fw.write("aaa");
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
try
{
if(fw!=null)
{
fw.close();
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
4.字符流入门之Writer
a) FileWriter FileWriter fw=new FileWriter(“abc.txt”);
b) 初始化时必须指定文件,NEW 时在工程目录下创建文件,如存在同名文件会覆盖
c) fw.write(“abc”); 将写入缓冲区,并不会进入文件
d) fw.flush(); 刷新缓冲数据,才会写入文件
e) Fw.write(“def”); 可以继续写入
f) Fw.close(); 关闭并刷新 不能继续写入
g) FileWriter fw=new FileWriter(“abc.txt”,true);append为T则写入末尾
h) Fw.write(“hello\r\nworld”); Win \r\n LINUX \N
5.字符流入门之Reader
a) FileReader FileReader fr=new FileReader("x:abc.txt"); 如果不存在,FileNotFoundException
b) Fr.read(); 一次读一个,并会后移
c) 循环实现一次读一个字符
int ch;
while((ch=fr.read())!=-1)
{
System.out.print((char)ch);
}
d)一次读一个字符数组
char[] buf=new char[1024]; //2KB
int len=0;
while((len=fr.read(buf))!=-1)
{
System.out.println(new String(buf,0,len));
}
6.小应用 复制文件(比较长)
package FileDemo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class CopyFileTest
{
public static void main(String[] args)
{
File f1=new File("3.txt");
File f2=new File("4.txt");
cpyFile_1(f1,f2);
}
public static void cpyFile(File src,File des)
{
FileReader fr=null;
FileWriter fw=null;
try
{
fr=new FileReader(src);
fw=new FileWriter(des);
char[] buf=new char[1024];
int len=0;
while(-1!=(len=fr.read(buf)))
{
fw.write(buf,0,len);
}
}
catch(Exception e)
{
throw new RuntimeException("读写失败");
}
finally
{
if(null!=fr)
{
try
{
fr.close();
}
catch(IOException e)
{
throw new RuntimeException("流无法关闭");
}
}
if(null!=fw)
{
try
{
fw.close();
}
catch(IOException e)
{
throw new RuntimeException("流无法关闭");
}
}
}
}
public static void cpyFile_1(File src,File des)
{
FileInputStream fis=null;
FileOutputStream fos=null;
try
{
fis=new FileInputStream(src);
fos=new FileOutputStream(des);
byte[] buf=new byte[1024];
int len=0;
while(-1!=(len=fis.read(buf)))
{
fos.write(buf,0,len);
}
}
catch(IOException e)
{
throw new RuntimeException("读写失败");
}
finally
{
if(null!=fis)
{
try
{
fis.close();
}
catch(IOException e)
{
throw new RuntimeException("流无法关闭");
}
}
if(null!=fos)
{
try
{
fos.close();
}
catch(IOException e)
{
throw new RuntimeException("流无法关闭");
}
}
}
}
}
7.字符流的缓冲区
a) 缓冲的出现提高了数据的读写效率
b) 对应类
i. BufferReader
ii. BufferWriter
c)缓冲区要结合流来使用
d)在流的基础上对流进行了增强
7.1
BufferedWriter
a) FileWriter fw=new FileWriter("x:buf.txt");
BufferedWriter bw=new BufferedWriter(fw); //传入字符流
bw.write("abcde");
bw.flush();
bw.newLine(); //跨平台的换行方法
bw.write("abcde");
bw.close();
7.2
BufferedReader
a)
FileReader fr=new FileReader("x:buf.txt");
BufferedReader br=new BufferedReader(fr);
String line=null;
while((line=br.readLine())!=null)
{
System.out.println(line);
}
7.3 缓冲区完成复制
public static void cpyFile() throws Exception
{
BufferedWriter bw;
BufferedReader br;
bw=new BufferedWriter(new FileWriter("x:bufcpy.txt"));
br=new BufferedReader(new FileReader("x:buf.txt"));
String line=null;
//READLINE()不返回行终止符
while((line=br.readLine())!=null)
{
bw.write(line);
bw.newLine();
bw.flush();
}
bw.close();
br.close();
}
7.4缓冲区模拟
public class MyBufferedReader
{
private FileReader fr;
public MyBufferedReader(FileReader fr)
{
this.fr=fr;
}
public String myReadLine() throws Exception
{
StringBuilder sb=new StringBuilder();
int ch=0;
while((ch=fr.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 myClose() throws Exception
{
fr.close();
}
public static void main(String[] args) throws Exception
{
MyBufferedReader mbr=new MyBufferedReader(new FileReader("x:buf.txt"));
String line=null;
while((line=mbr.myReadLine())!=null)
{
System.out.println(line);
}
}
}
8.装饰设计模式
a) 对已有对象进行功能增强时,可以定义一个类将已有对象传入,在其功能的基础上提供加强功能,那么被定义的类就被称为装饰类。
b) 装饰类通常会通过构造方法接收被装饰类的对象,并基于被装饰类提供更强的功能
c) 装饰和继承
d) 装饰类增强了已有对象,具备的功能是相同的,只不过提供了更强的功能,所以装饰类和被装饰类通常属于同一个体系。从继承结构变成了组合结构。
e) 修改后的MyBufferedReader(核心)
public class MyBufferedReader extends Reader
{
private Reader r;
public MyBufferedReader(Reader fr)
{
this.r=fr;
}
@Override
public int read(char[] cbuf, int off, int len) throws IOException
{
return r.read(cbuf, off, len);
}
@Override
public void close() throws IOException {
r.close();
}
public String myReadLine() throws Exception{同上}
}
f) LineNumberReader 继承自 BufferedReader,增加了行号的功能
自定义的MyLineNumberReader
public class MyLineNumberReader extends BufferedReader
{
private int lineNumber=0;
public MyLineNumberReader(Reader in) {
super(in);
// TODO Auto-generated constructor stub
}
public MyLineNumberReader(Reader in, int sz) {
super(in, sz);
// TODO Auto-generated constructor stub
}
public int getLineNumber() {
return lineNumber;
}
public void setLineNumber(int lineNumber) {
this.lineNumber = lineNumber;
}
@Override
public String readLine() throws IOException {
lineNumber++;
return super.readLine();
}
9.字节流
a)常规操作
public static void writeFile() throws Exception //无需刷新
{
FileOutputStream fos=new FileOutputStream("x:def.txt");
fos.write("abcde".getBytes());
fos.close();
}
public static void readFile() throws Exception
{
FileInputStream fis=new FileInputStream("x:def.txt");
int ch=0;
while((ch=fis.read())!=-1)
{
System.out.println((char)ch);
}
fis.close();
}
public static void readFile_2() throws Exception //推荐
{
FileInputStream fis=new FileInputStream("x:def.txt");
byte[] buf=new byte[1024];
int len=0;
while((len=fis.read(buf))!=-1)
{
System.out.println(new String(buf,0,len));
}
}
public static void readFile_3() throws Exception //慎用
{
FileInputStream fis=new FileInputStream("x:def.txt");
int num=fis.available();
byte[] buf=new byte[num];
fis.read(buf);
System.out.println(new String(buf));
fis.close();
}
b)拷贝图片 略 (用字节流,而不是字符流)
c)字节流的缓冲区 BufferedInputStream BufferedOutputStream
d)自定义字节流缓冲区
READ在提升而WRITE在强转
public class MyBufferedInputStream
{
private InputStream in;
private byte[] buf=new byte[1024];
private int pos=0; //指针
private int count=0; //计数器
public MyBufferedInputStream(InputStream in)
{
this.in=in;
}
public int myRead() throws IOException
{
if(0==count)
{
count=in.read(buf); //将数据读到BUF中作为缓冲区
if(count<0)
{
return -1;
}
pos=0;
byte b=buf[pos++];
count--;
return b&0xff; //保留低8位
}
else if(count>0)
{
byte b=buf[pos++];
count--;
return b&0xff;
}
return -1;
}
public void myClose() throws IOException
{
in.close();
}
}
10.读取键盘录入
a) 通过输入流INPUTSTREAM
public static void input_1() throws IOException
{
InputStream is=System.in;
StringBuilder sb=new StringBuilder();
int ch=0;
while((ch=is.read())!=-1)
{
if(ch=='\r')
{
continue;
}
if(ch=='\n')
{
if("over".equals(sb.toString()))
{
System.out.println("11111111");
break;
}
else
{
System.out.println(sb);
sb.delete(0, sb.length());
}
}
else
{
sb.append((char)ch);
}
}
Is.close();
}
b)通过转换流INPUTSTREAMREADER
public static void input_2() throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String line=null;
while((line=br.readLine())!=null)
{
if(line.equals("over"))
{
break;
}
System.out.println(line);
}
}
Br.close();
}
c)通过转换流输出在控制台
public static void input_3() throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
String line=null;
while((line=br.readLine())!=null)
{
if(line.equals("over"))
{
break;
}
bw.write(line);
bw.newLine();
bw.flush();
}
br.close();
bw.close();
}
11、流操作规律
a) 操作的数据是否是纯文本
i. 是:Reader Writer
ii. 否:InputStream OutputStream
b) 具体调用哪个对象
通过设备来区分:
源设备:内存,硬盘(文件),键盘。
目的设备:内存,硬盘(文件),控制台。
TIP:
涉及到键盘或控制台以及编码,就考虑转换流,转换流可以指定编码表
例:
OutputStreamWriter osw=new OutputStreamWriter(
New FileOutputStream(“a.txt”),”utf-8”);
GBK(默认) 3字节 UTF 4字节
c)效率
调用相应的Buffered流对象