java输入与输出流

来源:互联网 发布:手机蓝牙打印机软件 编辑:程序博客网 时间:2024/05/02 02:13

概述

从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 0
原创粉丝点击