字节流的抽象基类:
InputStream(输入) OutPutStream(输出)
字符流的抽象基类:
Reader(读) Writer(写)
这四个类派生出来的子类都是由父类的名作为子类名的后缀.
IO需要了解的问题:
1.有了垃圾回收站为什么还要调用close方法去进行关闭
解答: 虽然java已经垃圾回收了这个流,但是系统根本就不知道什么时候关闭这个流,所以我们要手动的去关闭
2.为什么IO异常一定要处理嗯?
解答:如果io异常不处理的, 当读到一个文件的时候出现错误,那么后面的也就会执行不到了.所以我们一定要异常处理/..
字符流创建一个文件
1 FileWriter fw = new FileWriter(“src/a.txt”); //建立数据存放的文件 2 3 fw.writer(“test”); //把text写入到流中
关闭流资源,并将流中的数据进行清空到文件中.
如果想要在原文件中加入新的数据呢?
FileWriter fw = new FileWriter(“src/a.txt”,true);//代表从一个文件的末尾处追加 fw.writer(“happy”);
1.jpgCopy.class(对一个图片进行拷贝)
package com.javami.kudy.Code14;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.FileOutputStream;
public class JpgCopy {
public static void main(String[]args)
{
FileInputStream fis = null;
FileOutputStream fos = null;
try
{
fis = new FileInputStream("src/a.jpg"); //输入一个图(输出(读) 输出(写))
fos = new FileOutputStream("src/b.jpg");
int len;
while((len=fis.read())!=-1)
{
fos.write(len); //输出(写入)
}
}catch(IOException e)
{
e.printStackTrace();
}
finally
{
}
}
}
CloseUtil.class(自己写的一个工具关闭流)
package com.javami.kudy.Code14;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
public class CloseUtil {
private CloseUtil(){}
public static void close(InputStream is,OutputStream os,Reader r,Writer w) throws IOException
{
try
{
is.close();
}
finally
{
os.close();
try
{
r.close();
}
finally
{
w.close();
}
}
}
}
System.currentTimeillis();//获取毫米数
自定义输入流:(读)
package com.javami.kudy.CodeBuffer;
import java.io.IOException;
import java.io.InputStream;
public class MyBufferedInputStream extends InputStream {
private InputStream is;
private byte[] buf = new byte[1024]; //假设我这边有1024个缓冲区
private int len; //默认为零
private int pos; //标记一下角标的个数
public MyBufferedInputStream(InputStream is)
{
this.is = is;
}
/*
* 1.需要考虑的问题?
* 思路:
* 加速
* FileInputStream is = new FileInputStream("src/a.jpg");
*/
@Override
public int read() throws IOException
{
if(len==0)
{
len = is.read(buf); //一次性填充缓冲区(从这个文件中截取1024个放到buf里面去,返回的是最长的个数)
//角标pos置零
pos=0;
}
if(len==-1)
return -1;
len--;
//但是返回的这个byte有可能是-1 ,如果-1程序就错了
return buf[pos++]&0xff; //0xff代表:11111111 &00000000 00000000 00000000 11111111
//返回的结果是前面+24个08个1.这样就不会被当成-1处理啦
}
public void close()throws IOException
{
//关闭底层的流
is.close();
}
}
自定义输出(写入)
package com.javami.kudy.CodeBuffer;
import java.io.IOException;
import java.io.OutputStream;
public class MyBufferedOutputStream extends OutputStream {
private OutputStream op;
private byte[] buf = new byte[1024];
int pos;
int len;
public MyBufferedOutputStream(OutputStream op)
{
this.op = op;
}
@Override
public void write(int b) throws IOException {
if(pos == 1024)
{
flush();
pos = 0;
}
/*
* 外部执行的情况:
* while 不断往里面放入字节
* 内部实现: 判断是否满了.如果满了.我这边就刷新一下.
*/
buf[pos++] = (byte)b;
}
public void flush()throws IOException
{
op.write(buf,0,pos);//写入 : 输出(到一个指定的文件里面去)
}
public void close()throws IOException
{
op.close();
}
}
测试几种用法的时间差:
package com.javami.kudy.CodeBuffer;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.BufferedInputStream;
import com.javami.kudy.Code14.CloseUtil;
public class Mp3Copy {
public static void main(String[]agrs)
{
/*
//时间差
long Timedifference =end - start;
System.out.println(Timedifference);*/
String source = "src/a.mp3"; //来源
String target = "src/d.mp3"; //目标
long start = System.currentTimeMillis();
try
{
myTest(source,target);
}
catch(IOException e)
{
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println(end-start); //获取到时间差
System.out.println("hello");
}
/*
* 单个拷贝字节: 毫秒大概是: 50000~60000之间
*/
private static void FileInputStreamTest(String source,String target)throws IOException
{
FileInputStream fls = null;
FileOutputStream fos = null;
try
{
fls = new FileInputStream(source);
fos = new FileOutputStream(target);
int ch;
while((ch=fls.read())!=-1)
{
fos.write(ch);
}
}
finally
{
CloseUtil.close(fls, fos, null, null);
}
}
/*
* 通过包装类来拷贝 缓存---> 593
*/
private static void BufferedTest(String source,String target)throws IOException
{
BufferedInputStream bis= null; //读(输入)
BufferedOutputStream bos = null; //写(输出)
try
{
bis = new BufferedInputStream(new FileInputStream(source));
bos = new BufferedOutputStream(new FileOutputStream(target));
int len;
while((len=bis.read())!=-1) //把左边的内容读到底层的一个bis[pos++]之后再从缓冲区里面返回
{
bos.write(len);
}
}
finally
{
CloseUtil.close(bis, bos, null, null);
}
}
/*
* 用户自定义的缓存数组: 94
*/
private static void copyMp3ByBuf(String source,String target)throws IOException
{
FileInputStream fis = null;
FileOutputStream fos = null;
try
{
fis = new FileInputStream(source);
fos = new FileOutputStream(target);
byte[] buf = new byte[1024];
int ch;
while((ch=fis.read(buf))!=-1)
{
fos.write(buf);
}
}
finally
{
CloseUtil.close(fis, fos, null, null);
}
}
/*
* 用自己写的包装输入输出字节流
* 203
* 通过比较得出的结论:
*
*/
private static void myTest(String source,String target )throws IOException
{
MyBufferedInputStream mis = null;
MyBufferedOutputStream mos = null;
try
{
mis = new MyBufferedInputStream(new FileInputStream(source));
mos = new MyBufferedOutputStream(new FileOutputStream(target));
int b;
while((b=mis.read())!=-1)
{
mos.write(b);
}
}
finally
{
CloseUtil.close(mis, mos, null, null);
}
}
}
关闭流的工具类:
package com.javami.kudy.Code14;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
public class CloseUtil {
private CloseUtil(){}
public static void close(InputStream is,OutputStream os,Reader r,Writer w) throws IOException
{
try
{
if(is!=null)
is.close();
}
finally
{
if(os!=null)
os.close();
try
{
if(r!=null)
r.close();
}
finally
{
if(w!=null)
w.close();
}
}
}
}
其实字符流的底层实现是需要字节流的
package com.javami.kudy.CodeBuffer;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
public class MyFileWriter extends OutputStreamWriter {
/*
* 如果你放进去一个字符流!
* 我们通过底层调用父类的字节流.帮你处理这个数据
*/
public MyFileWriter(String name)throws IOException
{
//底层实现原理: 其实调用字符流底层是字节流实现的?为何呢?
super(new FileOutputStream(name));
}
public MyFileWriter(String name,boolean is)throws IOException
{
super(new FileOutputStream(name,true));
}
}
关于字节流转字符流
package com.javami.kudy.PM;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import com.javami.kudy.Code14.CloseUtil;
public class TreasStreamTest {
/*
* 字节流转换成字符流
* 思路:
* 1.首先要获取到输入流与输出流
* 2.(字符流) == <-- InputStreamReader--> (输入流)
3.(字符流) == <--OutputStream-->(输出流)
*/
public static void main(String[]args)
{
/*//1.获取输入流
InputStream ism = System.in;
//2.获取输出流
PrintStream pts = System.out;
//3.字符流(读)-->输入流 转换
InputStreamReader isr = new InputStreamReader(ism);
//4.字符流(写)-->输出留
OutputStreamWriter osr = new OutputStreamWriter(pts);
//5.转换成父类型的引用可以指向子类型的对象(转换成字符流的读)
Reader r = isr;
//6.转换成父类型的引用可以指向子类型的对象(转换成字符流的写)
Writer w = osr;
//包装字符流
BufferedReader br = new BufferedReader(r);//包装
BufferedWriter bw = new BufferedWriter(w);
关于执行速度-->
*/
//从字节流转换成字符流的步骤
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
try
{
String line;
while(true)
{
line = br.readLine(); //读一行
bw.write(line); //写一行
bw.newLine();
bw.flush(); //刷新-->从流里面刷新一下.因为它是属于打一行打一行的概率
if("bye".equals(br))
break;
}
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
try
{
CloseUtil.close(null, null, br, bw);
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
}
流程图:
System.in(读)
System.out(写)
BufferedReader br = new BufferedReader(new InputStream(System.in)); //把输入流转换成包装的读
BufferedWriter bw = new BufferedWriter(new OutputStream(System.out)); //把输出流转换成包装的写
BuffferedReader对标准输入System.in进行包装,实现读取键盘上输入的一行
注意:
如果想要实现读一行,打一行↓
String line br.readLine(); //第一行
bw.writer(line);
bw.newLine(); //换行
bw.flush()刷新一下流
/**
* 测试题5
* 输入学生新,按break终止,每个学生有3门课的成绩,定义一种比较直观的文本文件格式,
输入学生姓名和成绩,从键盘输入以上数据(包括姓名,三门课成绩),
按总分数从高到低的顺序将学生信息存放在磁盘文件"stu.txt"中。
思路:
1.读取键盘,一行输入一个学生的信息,封装成学生对象
2.将学生对象存入一个TreeSet按总分排序
3.遍历TreeSet集合,取出所有的学生信息,输出到stu.txt中
*/
package com.javami.kudy.PM;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.TreeSet;
public class Test {
public static void main(String[]args)
{
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>(){
//比较器
@Override
public int compare(Student s1, Student s2) {
int num = s1.getSum()-s2.getSum();
if(num!=0)
return -num;
return s1.getName().compareTo(s2.getName());
}
});
try
{
saveStuInfo(ts);
listStuInfo(ts);
}
catch(IOException e)
{
e.printStackTrace();
}
}
/*
* 遍历集合里面的内容,把它写入到一个文件名里面
*/
private static void listStuInfo(TreeSet<Student> ts)throws IOException
{
BufferedWriter bw = null;
try
{
bw = new BufferedWriter(new FileWriter("src/a.txt"));
for(Student str : ts)
{
//一定要标记为toString 为啥呢? 因为它是不会自动的打印toString的
bw.write(str.toString());
bw.newLine();
}
}
finally
{
bw.close();
}
}
/*
* 读取键盘
* 获取学习的对象
* 把学习的对象存入ts里面去
*/
public static void saveStuInfo(TreeSet<Student> ts)throws IOException
{
//当你读的时候,我们要求它用逗号分隔
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));//输入-?读
try
{
String line;
while(true)
{
line = br.readLine(); //读一行
if("break".equals(line))
break;
//将line分隔成4部分
String[]bufs = line.split(",");
Student s = new Student(bufs[0],Integer.parseInt(bufs[1])
,Integer.parseInt(bufs[2])
,Integer.parseInt(bufs[3]));
ts.add(s);
}
}
finally
{
br.close();
}
}
}
class Student
{
private String name;
private int chinese; //语文成绩
private int math; //数学成绩
private int english; //英语成绩
private int sum; //总分
public Student(String name,int chinese,int math,int english)
{
this.name = name;
this.chinese = chinese;
this.math = math;
this.english = english;
this.sum = chinese+math+english;
}
public int getSum()
{
return sum;
}
public String getName()
{
return name;
}
@Override
public String toString()
{
return "姓名:"+name+"语文成绩:"+chinese+"数学成绩:"+math+"英语成绩:"+english;
}
}