【Java】缓冲流练习

练习:四种拷贝方式效率对比

PS:每次运行程序的用时可能是不一样的,因为在电脑中不仅仅有Java在运行,还有其他的软件。

还有电脑性能不一样,用时也有可能是不一样的。

public static void main(String[] args) throws IOException {
    long start = System.currentTimeMillis();
    //method1();
    //method2();          //16.253秒
    //method3();          //95.466秒,虽然也有缓冲区,但是它需要在两个缓冲区之间进行倒手,一个字节一个字节倒。又因为这个倒手是发生在字节中的,但文件太大了,因此也要浪费一点时间的。这就导致了第三种方式的性能反而降低了,低就低在倒手的时间上。
    //method4();            //17.686秒
    long end = System.currentTimeMillis();
    // 注意在除的时候需要加上.0,否则结果只能是整数
    System.out.println((end - start) / 1000.0 + "秒");
}


//字节流的基本流:一次读写一个字节4,588,568,576 字节
public static void method1() throws IOException {
    FileInputStream fis = new FileInputStream("E:\\aaa\\CentOS-7-x86_64-DVD-1810.iso");
    FileOutputStream fos = new FileOutputStream("myio\\copy.iso");
    int b;
    while ((b = fis.read()) != -1) {
        fos.write(b);
    }
    fos.close();
    fis.close();
}

//字节流的基本流:一次读写一个字节数组
public static void method2() throws IOException {
    FileInputStream fis = new FileInputStream("E:\\aaa\\CentOS-7-x86_64-DVD-1810.iso");
    FileOutputStream fos = new FileOutputStream("myio\\copy.iso");
    byte[] bytes = new byte[8192];
    int len;
    while ((len = fis.read(bytes)) != -1) {
        fos.write(bytes, 0, len);
    }
    fos.close();
    fis.close();
}

//字节流的基本流:一次读写一个字节数组
public static void method3() throws IOException {
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\aaa\\CentOS-7-x86_64-DVD-1810.iso"));
    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("myio\\copy.iso"));
    int b;
    while ((b = bis.read()) != -1) {
        bos.write(b);
    }
    bos.close();
    bis.close();
}

//字节流的基本流:一次读写一个字节数组
public static void method4() throws IOException {
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\aaa\\CentOS-7-x86_64-DVD-1810.iso"));
    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("myio\\copy.iso"));
    byte[] bytes = new byte[8192];
    int len;
    while ((len = bis.read(bytes)) != -1) {
        bos.write(bytes, 0, len);
    }
    bos.close();
    bis.close();
}

练习:把《出师表》的文章顺序进行恢复到一个新文件中

需求:把《出师表》的文章顺序进行恢复到一个新文件中。

3.侍中、侍郎郭攸之、费祎、董允等,此皆良实,志虑忠纯,是以先帝简拔以遗陛下。愚以为宫中之事,事无大小,悉以咨之,然后施行,必得裨补阙漏,有所广益。
8.愿陛下托臣以讨贼兴复之效,不效,则治臣之罪,以告先帝之灵。若无兴德之言,则责攸之、祎、允等之慢,以彰其咎;陛下亦宜自谋,以咨诹善道,察纳雅言,深追先帝遗诏,臣不胜受恩感激。
4.将军向宠,性行淑均,晓畅军事,试用之于昔日,先帝称之曰能,是以众议举宠为督。愚以为营中之事,悉以咨之,必能使行阵和睦,优劣得所。
2.宫中府中,俱为一体,陟罚臧否,不宜异同。若有作奸犯科及为忠善者,宜付有司论其刑赏,以昭陛下平明之理,不宜偏私,使内外异法也。
1.先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。然侍卫之臣不懈于内,忠志之士忘身于外者,盖追先帝之殊遇,欲报之于陛下也。诚宜开张圣听,以光先帝遗德,恢弘志士之气,不宜妄自菲薄,引喻失义,以塞忠谏之路也。
9.今当远离,临表涕零,不知所言。
6.臣本布衣,躬耕于南阳,苟全性命于乱世,不求闻达于诸侯。先帝不以臣卑鄙,猥自枉屈,三顾臣于草庐之中,咨臣以当世之事,由是感激,遂许先帝以驱驰。后值倾覆,受任于败军之际,奉命于危难之间,尔来二十有一年矣。
7.先帝知臣谨慎,故临崩寄臣以大事也。受命以来,夙夜忧叹,恐付托不效,以伤先帝之明,故五月渡泸,深入不毛。今南方已定,兵甲已足,当奖率三军,北定中原,庶竭驽钝,攘除奸凶,兴复汉室,还于旧都。此臣所以报先帝而忠陛下之职分也。至于斟酌损益,进尽忠言,则攸之、祎、允之任也。
5.亲贤臣,远小人,此先汉所以兴隆也;亲小人,远贤臣,此后汉所以倾颓也。先帝在时,每与臣论此事,未尝不叹息痛恨于桓、灵也。侍中、尚书、长史、参军,此悉贞良死节之臣,愿陛下亲之信之,则汉室之隆,可计日而待也。

如果使用字符流的基本流读也行,但是需要将所有读到的字拼在一起,太麻烦了。

因此这里使用 字符缓冲流,它里面有一个非常好用的 readLine(),一次可以读一整行数据。

排序的时候不可以使用字符串排序,因为如果写的再多一点,可能会有序号 11、12、13 等,此时就不能使用字符串排了,因此尽量要考虑代码的通用性。

写法一:

//1.读取数据
BufferedReader br = new BufferedReader(new FileReader("myio\\csb.txt"));
String line;
ArrayList<String> list = new ArrayList<>();
while((line = br.readLine()) != null){
    list.add(line);
}
br.close();

//2.排序
//排序规则:按照每一行前面的序号进行排列
Collections.sort(list, new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
        //获取o1和o2的序号
        int i1 = Integer.parseInt(o1.split("\\.")[0]);
        int i2 = Integer.parseInt(o2.split("\\.")[0]);
        return i1 - i2;
    }
});

//3.写出
BufferedWriter bw = new BufferedWriter(new FileWriter("myio\\result.txt"));
for (String str : list) {
    bw.write(str);
    bw.newLine();
}
bw.close();

写法二:

//1.读取数据
BufferedReader br = new BufferedReader(new FileReader("myio\\csb.txt"));
String line;
TreeMap<Integer,String> tm = new TreeMap<>();
while((line = br.readLine()) != null){
    String[] arr = line.split("\\.");
    //0:序号  1 :内容,注意这里添加的是完整的数据,包括序号
    tm.put(Integer.parseInt(arr[0]), line);
}
br.close();


//2.写出数据
BufferedWriter bw = new BufferedWriter(new FileWriter("myio\\result2.txt"));
Set<Map.Entry<Integer, String>> entries = tm.entrySet();
for (Map.Entry<Integer, String> entry : entries) {
    String value = entry.getValue();
    bw.write(value);
    bw.newLine();
}
bw.close();

练习:软件运行四次

实现一个验证程序运行次数的小程序,要求如下:
1.当程序运行超过3次时给出提示:本软件只能免费使用3次,欢迎您注册会员后继续使用~
2.程序运行演示如下:
    第一次运行控制台输出: 欢迎使用本软件,第1次使用免费~
    第二次运行控制台输出: 欢迎使用本软件,第2次使用免费~
    第三次运行控制台输出: 欢迎使用本软件,第3次使用免费~
    第四次及之后运行控制台输出:本软件只能免费使用3次,欢迎您注册会员后继续使用~

一、代码示例

注意这里是不能通过定义变量 int count = 0 去统计次数,因为变量是运行在内存中的,程序结束后,变量就会消失,因此不能将变量定义在内存中。

我们可以将它保存在本地文件中。

//1.把文件中的数字读取到内存中
BufferedReader br = new BufferedReader(new FileReader("myio\\count.txt"));
String line = br.readLine(); // 由于只有一行,就没必要循环去遍历了

int count = Integer.parseInt(line);
//表示当前软件又运行了一次
count++;//1
//2.判断
if(count <= 3){
    System.out.println("欢迎使用本软件,第"+count+"次使用免费~");
}else{
    System.out.println("本软件只能免费使用3次,欢迎您注册会员后继续使用~");
}
BufferedWriter bw = new BufferedWriter(new FileWriter("myio\\count.txt"));

//3.把当前自增之后的count写出到文件当中
bw.write(count + ""); //PS:注意转为字符串,否则如果写的是数字,那么真正写到文件里的是这个数字在字符集中所对应的字符
bw.close();

二、扩展

有的人之前拷贝写习惯了,喜欢将这两种流先创建出来,下面再挨个使用。

BufferedReader br = new BufferedReader(new FileReader("myio\\count.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("myio\\count.txt"));

在这里绝对不行!因为 BufferedWriter 在创建文件的时候,如果文件存在,就会清空。

一旦清空了,下面读取文件的时候就会有空指针。

因此一般在创建 IO流 对象的时候,一般会有这样的原则:IO流 不是随随便便创建的,而是什么时候用什么时候创建,什么时候不用什么时候关闭。

因此上面的代码一旦 br 读完了数据,就要将它立马关掉。

BufferedReader br = new BufferedReader(new FileReader("myio\\count.txt"));
String line = br.readLine(); // 由于只有一行,就没必要循环去遍历了
br.close();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值