java输入与输出流

java-io 专栏收录该内容
1 篇文章 0 订阅

概述

从14年10月份开始工作,到今天做Android已经两年半了。可是到现在也没搞清楚Java的I/O机制,痛定思痛,觉得好好整理一下。古人云“格物致知”,今天就好好格一格I/O机制吧!

常见问题

什么是流

“流”是一连串流动的字符,同时也说明了数据传输的一种状态:“均匀与连续”。java使用“流”进行数据传输。而传输的双方一般是“你的程序”和“设备(手机)”。

输入和输出流

根据的方向,可以分为输入流输出流流的输入(Input)和输出(Output)是以应用程序为参考中心的。输入流就是从设备流入到应用程序,也即常说的读(Read);输出流就是从应用程序流到设备,也即我们常说的写(Write)。

原理图如下:
这里写图片描述

注:输入流命名规则是包含Input或Reader,如InputStream、BufferedReader;输出流命名规则是包含Output或Writer,如OutputStream、BufferedWriter。

字节流和字符流

数据传输的基本单位是字节(bytes),但1个字节是8位,表示范围是0-255。面对诸多汉字,1个字节很明显是不足的。所以生成了一种新的单位:字符,而字符和字节之间的映射关系就是Unicode。在java中1个字符等于2个字节。根据流的数据类型,可分为字节流和和字符流。

字节流和字符流的区别

1. 读写单位:字节流处理的基本单元是字节;字符流处理的基本单元是Unicode码,2个字节
2. 处理对象:字节流能处理所有类型的数据(图片,视频,音频等),字符流只能处理字符型数据(字符串,纯文本文档)
3. 是否缓存:字符流传输之前要先经过Unicode转换成字节流,批量转换后的字节流存储到缓存当中(提示效率),然后再进行读写。字节流则不用缓存(字节流本身是不使用字节流的,但是如果想提升效率,可以自定义缓存区)。

注:字节流一般命名规则是以Stream结尾,如InputStream或OutputStream;字符流一般命名规则是以Reader或Writer结尾。如BufferedReader、BufferedWriter。

节点和处理流

根据流是否直接与数据源相连,可以划分为节点流和处理流。节点流是可以直接从/向数据源(设备,硬盘,内存等)读/写数据;处理流是对一个已存在的流的连接、封装和处理。

注:处理流命名规则是包含buffered,如BufferedInputStream、BufferedReader。

介绍

I/O家族谱系

这里写图片描述
根据操作的数据类型,分为字节流和字符流;根据数据的流向,又分为输入流和输出流;根据功能,分为节点流和处理流。

InputStream和OutputStream

字节流处理的抽象基类是InputStream和OutputStream。InputStream是字节输入流,OutputStream是字节输出流。

Reader和Writer

字符流处理的抽象基类是Reader和Writer。Reader是字符输入流,Writer是字符输出流。

实战演示

介绍的差不多了,接下来就是实战演示了。
1.从本地读取图片
1. 读取说明数据流是从设备到应用,因此使用输入流,那就是InputStream或Reader
2. 操作的数据对象是图片,使用字节流的话效率较高(不用经由Unicode转换)
3. 所以排除Reader,选择InputStream

 public void readImg(ImageView iv) {
        File file = new File("/sdcard/temp.jpg");
        if (file.exists()) {
            FileInputStream fileInputStream = null;
            try {
                fileInputStream = new FileInputStream(file);
                byte[] img = new byte[(int) file.length()];// 根据文件长度创建字节数组
                fileInputStream.read(img);  // 将图片字节信息写入到字节数组
                Bitmap bitmap = BitmapFactory.decodeByteArray(img,0,img.length);
                iv.setImageBitmap(bitmap);  // 显示图片
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

2.保存图片到本地
1. 保存到本地说明数据流是从应用到设备,因此使用输出流,所以选择OutputStream或Writer
2. 由于操作的数据对象是图片,使用字节流的话效率较高(不用经由Unicode转换)
3. 所以排除Writer,选择OutputStream

 public void saveImg() {
        InputStream inputStream = null;
        FileOutputStream fileOutputStream = null;
        try {
            URL url = new URL("https://ss0.baidu.com/94o3dSag_xI4khGko9WTAnF6hhy/image/h%3D360/sign=e572f27e9058d109dbe3afb4e158ccd0/b7fd5266d0160924933e331bd60735fae6cd3492.jpg");
            URLConnection urlConnect = url.openConnection();
            urlConnect.setConnectTimeout(5000);
            inputStream = urlConnect.getInputStream();

            File tempFile = new File("/sdcard/temp.jpg");// 保存到临时文件中
            if(tempFile.isDirectory()){
                tempFile.delete();
            }
            if (!tempFile.exists()) {
                tempFile.createNewFile();
            }
            fileOutputStream = new FileOutputStream(tempFile);// 创建输出流,参数tempFile为写入的目标
            byte[] buffer = new byte[1024];
            int length = -1;
            while ((length = inputStream.read(buffer)) != -1) {  // 读取字节,先存储到缓存区
                fileOutputStream.write(buffer, 0, length);        // 从缓存区提取数据,可以提升效率
            }
            inputStream.close();
            fileOutputStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

3.从本地读取纯文档
1. 由于是读取,说明数据流是从设备流到应用,因此使用输入流,所以选择InputStream或Reader
2. 操作的数据对象是纯文档,需要使用字符流(纯文档需要经由Unicode转码)
3. 所以排除InputStream,选择Reader

  public String readWold() {
        try {
            FileReader fileReader = new FileReader("/sdcard/test.txt");
            BufferedReader bufferedReader = new BufferedReader(fileReader);
            String line = null;
            StringBuilder builder = new StringBuilder();
            while ((line = bufferedReader.readLine()) != null) {
                builder.append(line + "\n");
            }
            bufferedReader.close();
            return builder.toString();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

4.写入到本地纯文档
1.写入说明数据流是从应用到设备,因此使用输出流,所以选择OutputStream或Writer
2. 操作的数据对象是纯文档,需要使用字符流(纯文档或字符串需要经由Unicode转码)
3. 所以排除OutputStream,选择Writer

public void saveWord() {
        try {
            File file = new File("/sdcard/test.txt");
            if (file.isDirectory()){
                file.delete();
            }
            if (!file.exists()){
                file.createNewFile();
            }
            FileWriter fileWriter = new FileWriter(file);
            BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
            bufferedWriter.write("Hi,I am Chaos!");
            bufferedWriter.newLine();
            bufferedWriter.write("I am come from China!");
            bufferedWriter.newLine();
            bufferedWriter.flush();
            bufferedWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

参考资料

字节流和字符流 http://www.jianshu.com/p/4edb6b99204e
Java中的字节流、缓冲流 http://blog.csdn.net/sinat_34669892/article/details/52738643
java 下载网络上的图片并保存到本地目录 http://takeme.iteye.com/blog/1683380
IO结构图源于百度图片

  • 3
    点赞
  • 1
    评论
  • 1
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

评论 1 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

Chaoswx

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值