java I/O流的一些常用操作

java i/o 的一些操作

文件流:FileInputStream/FileOutputStream, FileReader/FileWriter

  • 这四个类是专门操作文件流的,用法高度相似,区别在于前面两个是操作字节流,后面两个是操作字符流。它们都会直接操作文件流,直接与OS底层交互。因此他们也被称为节点流。

package com.lw.study.excelTest;

import com.lw.study.Application;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.io.*;

/**
 * @author:
 * @Date: 15:21 2019/2/28
 */
@SpringBootTest(classes = Application.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class FileTest {
//    字节流没有缓冲区,是直接输出的,而字符流是输出到缓冲区的。因此在输出时,字节流不调用colse()方法时,信息已经输出了,
// 而字符流只有在调用close()方法关闭缓冲区时,信息才输出。要想字符流在未关闭时输出信息,则需要手动调用flush()方法。

    @Test
    public void testGetFile() throws IOException {
        //字节流
        String filepath = "/tmp/dashu/test.txt";
        OutputStream outputStream = new FileOutputStream("/tmp/dashu/test3.txt");
        InputStream inputStream = new FileInputStream(filepath);
        try {
                byte[] b = new byte[inputStream.available()];
                System.out.println(inputStream.available());
                inputStream.read(b);
                System.out.println(new String(b));
                outputStream.write(b);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }finally {
            inputStream.close();
            outputStream.close();
        }
    }

    @Test
    public void testWrite() {
   //字符流
        try {
            //若文件不存在会新建一个文件,然后写入内容,文件存在覆盖源文件内容
            FileWriter fw = new FileWriter("/tmp/dashu/test4.txt");
            FileReader fd = new FileReader("/tmp/dashu/test2.txt");

            char[] read = new char[32];
            int hasRead = 0;
            while ( (hasRead =fd.read(read)) > 0) {
//                System.out.println(read);
                String readLine = new String(read, 0, hasRead);
                System.out.println(readLine);
                //一定要关闭这个溜。不然会写不进去
                //关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据。
                //将数据刷到目的地中去。
                //和flush区别:flush 刷新后,流可以继续使用,close刷新后,会将流关闭。
//                实际上,当我们写好了new FileWriter 的时候,我们进行下一步的操作,将数据写入文本,但是这时的数据并没有写入文本,而是存在了计算机中的流中。这也是JAVA能够在Windows 系统中调用文本流的作用。而如果在这里我们使用fw.flush时,是可以将存储在计算机流中的数据放入fw的,但是如果我们之后再想加入数据的时候,也就是说我们将写入的数据这句话放在fw.flush之后的话,之后输入的数据就不会放入到 test.txt中去。
//                再说一说fw.close, 我们可以去查询close的定义,很明确的写了 先刷新一次,然后关闭数据流。没错,事实上,close是包含了两步,flush 和close 这两步。所以我们注释掉了flush 因为在这里一个close语句就够用了。
//                flush 刷新后,流可以继续使用,close刷新后,会将流关闭。
//
                fw.write(readLine);
                fw.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 字符缓冲流 用来读取纯文本文件
     * @throws IOException
     */
    @Test
    public void testBufferReader() throws IOException {
        try {
            BufferedReader bufferedReader = new BufferedReader(new FileReader("/tmp/dashu/test.txt"));
            BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("/tmp/dashu/test5.txt"));
            //保存每次读取的一行的内容
            String line = "";
            while ((line = bufferedReader.readLine()) != null) {
                System.out.println(line);
                bufferedWriter.write(line);
                //换行
                bufferedWriter.newLine();
            }
            bufferedReader.close();
            bufferedWriter.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

    }

    /**
     *字节缓冲流,读取图片、视频等
     * @throws IOException
     */
    @Test
    public void testBufferInputStream() throws IOException {
        BufferedInputStream in = new BufferedInputStream(new FileInputStream("/tmp/dashu/终端背景.jpg"));
        BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("/tmp/dashu/终端背景2.jpg"));
        byte[] bRead = new byte[in.available()];
        in.read(bRead);
        out.write(bRead);

        in.close();
        out.close();
    }
}

总结几种流的应用场景:

  • FileInputStream/FileOutputStream 需要逐个字节处理原始二进制流的时候使用,效率低下
  • FileReader/FileWriter 需要组个字符处理的时候使用
  • StringReader/StringWriter 需要处理字符串的时候,可以将字符串保存为字符数组
  • PrintStream/PrintWriter 用来包装FileOutputStream 对象,方便直接将String字符串写入文件
  • Scanner 用来包装System.in流,很方便地将输入的String字符串转换成需要的数据类型
  • InputStreamReader/OutputStreamReader , 字节和字符的转换桥梁,在网络通信或者处理键盘输入的时候用
  • BufferedReader/BufferedWriter , BufferedInputStream/BufferedOutputStream , 缓冲流用来包装字节流后者字符流,提升IO性能,BufferedReader还可以方便地读取一行,简化编程。
  • StringBufferInputStream – 把一个 String 对象作为。InputStream。不建议使用,在转换字符的问题上有缺陷
注意:

available()来获取文件的总大小,这个方法在获取本地文件的时候没啥问题,但是如果是获取网络文件的大小,如果网络阻塞了,inputstream已经打开,但是数据却还没有传输过来,那么这个inputstream势必会被阻塞,从而导致inputstream.available返回0。而对inputstream.read(byte[] b)而言,如果b的长度等于0,该方法将返回0。可以考虑手工设定一个固定值;或者读取http报文头的content-length属性值,后一种方式:

URLConnection openConnection = new URL("http://www.apache.org").openConnection(); 
System.out.println(openConnection.getContentLength());

available()这个方法其实是通过文件描述符获取文件的总大小,而并不是事先将磁盘上的文件数据全部读入流中,再获取文件总大小。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值