菜鸟学习笔记:Java IO流1——IO流的概念、字节流、字符流、缓冲流、转换流

  • IO流的原理及概念
  • 节点流
    • 字节流
      • 文件读取
      • 文件写出
      • 文件拷贝
      • 文件夹拷贝
    • 字符流
      • 文件读取
      • 文件写出
  • 处理流
    • 缓冲流
    • 转换流
      • 编码和解码
      • 转换流实现

IO流的原理及概念

在基础篇的讲解中大家已经了解了File对象以及它的一些方法(复习链接)。但是File的主要作用仅仅是建立文件和程序的联系,File对象的方法只能用于文件和目录的创建、文件的查找和文件的删除等功能,但无法对文件的内容做具体的操作。所以引入了现在所要讲的IO流知识点。
在Java程序中,对数据的输入输出操作以“流”的方式进行:

如果大家觉得不好理解可以这样想,我们要读取的文件好比一个装满水的桶,文件内容就是里面的水,我们的流相当于一根管道,一端接文件,一端接程序,读取文件就相当于把水抽过来,,放到程序里。不过不一样的一点是读取文件后原文件内容不变,也就是抽水过程不影响文件桶里的水,抽的水凭空产生。
对于IO流按不同的角度可以分成不同的类:

  • 如果以数据流向可以分为输入流(程序从文件抽水)和输出流(文件从程序抽水)。
  • 如果以读取数据的基本单元来划分可以分为字节流(读取基本单位是字节)和字符流(读取基本单位是字符)。这里稍微讲解一下字节和字符,字节是计算机存储的一个基本单位,它由8个2进制位组成。而一个字符表示一个文字所占的大小,为2个字节。一般情况下字节流可以用来读取一切文件,而字符流只能读取文本文件。
  • 如果按照功能来划分又可以把IO流划分为节点流(基本读取用)和处理流(包裹节点流,提高性能)。

节点流

字节流

由于读取的基本单位是字节,字节是文件的基本构成单位,所以字节流可以处理一切图片、视频音频、文本文件。InputStream和OutputStream类是Java中字节流的实现,通过这两个类所提供的方法,可以实现用字节流文件读写。

文件读取

对于流的操作我们都用代码来呈现,为方便读取代码,首先讲解几个点:

  • FileInputStream是InputStream的子类,可以用来建立文件与程序间的流
  • FileInputStream类的read(byte[] b)方法用来读取文件,b表示一个读取用的容器,每次读取的内容会存放到b中,该方法会返回每次读取文件的长度,如果读取内容为空会返回-1,也就是读取完成。
  • jdk1.7之前读取完成需要手动调用close()方法关闭流。

有了这些知识基础我们就可以看实例代码了,这段代码的功能就是从文件中读取内容并输出,首先看我们的文件:

 public static void main(String[] args) {//1、建立联系   File对象File src =new File("D:/testFile/haha.txt");//2、选择流(输入字节流)//注意流需要在读取结束后关闭,必须放在trycatch之外。jdk1.7之后可不用这样InputStream is =null; //首先IO操作会产生FileNotFoundException和IOException两个异常,需要捕获出路try {//建立程序和文件之间的流(之前例子里的水管)is =new FileInputStream(src);//3、操作 不断读取 缓冲数组byte[] car =new byte[1024];int len =0; //接收 实际读取大小//循环读取StringBuilder sb =new StringBuilder();while(-1!=(len=is.read(car))){//输出  字节数组转成字符串String info =new String(car,0,len);sb.append(info);}System.out.println(sb.toString());//打印haha} catch (FileNotFoundException e) {e.printStackTrace();System.out.println("文件不存在");} catch (IOException e) {e.printStackTrace();System.out.println("读取文件失败");}finally{try {//4、释放资源if (null != is) {is.close();}} catch (Exception e2) {System.out.println("关闭文件输入流失败");}}}

程序效果

文件写出

和读入对应

  • 写出文件所用的是FileOutputStream(dest,true),构造方法中第一个参数表示要写入的文件对象。第二个参数为true表示如果文件存在则追加内容 ,false表示覆盖文件内容。
  • 写入文件用的是write(data,start,end)方法,data必须为byte[]类型,可以指定开始和结束位置。
  • flush()方法的作用是将存放在流中的数据强行写道文件中防止写出文件不完整的情况。
    输出流的代码如下:
public static void main(String[] args) {//1、建立联系   File对象  目的地File dest =new File("D:/testFile/houhou.txt");//2、选择流   文件输出流  OutputStream FileOutputStreamOutputStream os =null;//以追加形式 写出文件 必须为true 否则为覆盖try {os =new FileOutputStream(dest,true);//3、操作String str="very good \r\n";//字符串转字节数组byte[] data =str.getBytes();os.write(data,0,data.length);os.flush(); //强制刷新出去} catch (FileNotFoundException e) {e.printStackTrace();System.out.println("文件未找到");} catch (IOException e) {e.printStackTrace();System.out.println("文件写出失败");}finally{//4、释放资源 :关闭try {if (null != os) {os.close();}} catch (Exception e2) {System.out.println("关闭输出流失败");}}}

程序结果:

文件拷贝

将以上两个流结合就可以得到文件拷贝的代码:

public class FileUtil {public static void copyFile(String srcPath,String destPath) throws FileNotFoundException,IOException {//1、建立联系 源(存在且为文件) +目的地(文件可以不存在)  File src =new File(srcPath);File dest =new File(destPath);if(! src.isFile()){ //不是文件或者为nullSystem.out.println("只能拷贝文件");throw new IOException("只能拷贝文件");}//2、选择流InputStream is =new FileInputStream(src);OutputStream os =new FileOutputStream(dest);//3、文件拷贝   循环+读取+写出byte[] flush =new byte[1024];int len =0;//读取while(-1!=(len=is.read(flush))){//写出os.write(flush, 0, len);}os.flush(); //强制刷出//关闭流os.close();is.close();}}

文件夹拷贝

依据上面文件拷贝的案例可以扩展成文件夹的拷贝:

 public static void copyDirDetail(File src,File dest) throws FileNotFoundException,IOException{if(src.isFile()){ //文件try {FileUtil.copyFile(src, dest);} catch (FileNotFoundException e) {//e.printStackTrace();throw e;} catch (IOException e) {//e.printStackTrace();throw e;}}else if(src.isDirectory()){ //文件夹//确保目标文件夹存在dest.mkdirs();//获取下一级目录|文件for(File sub:src.listFiles()){copyDirDetail(sub,new File(dest,sub.getName()));}}}

字符流

与字节流不同,由于只有文本文件的基本组成单位是字符,所以字符流只能读写文档文件。Reader和Writer是类是Java中字节流的实现。

文件读取

字符流需要注意的有几个点:

  • 字符流需要创建FileReader类。
  • 读取过程建立的不是byte[]而是char[]。

写法和思路与字节流读取基本相同,下面直接看例子。

 public static void main(String[] args) {//创建源File src =new File("E:/xp/test/a.txt");//选择流Reader reader =null;try {reader =new FileReader(src);//读取操作char[] flush =new char[1024];int len =0;while(-1!=(len=reader.read(flush))){//字符数组转成 字符串String str =new String(flush,0,len);System.out.println(str);}} catch (FileNotFoundException e) {e.printStackTrace();System.out.println("源文件不存在");} catch (IOException e) {e.printStackTrace();System.out.println("文件读取失败");}finally{try {if (null != reader) {reader.close();}} catch (Exception e2) {}}}

文件写出

 public static void main(String[] args) {//创建源File dest =new File("e:/xp/test/char.txt");//选择流Writer wr =null;try {//追加文件,而不是覆盖文件wr =new FileWriter(dest);//写出String msg ="追加.....锄禾日当午\r\n码农真辛苦\r\n一本小破书\r\n一读一上午";wr.write(msg);//文件追加内容wr.append("倒萨发了看电视剧 ");wr.flush();} catch (FileNotFoundException e) {e.printStackTrace();}catch (IOException e) {e.printStackTrace();}finally{try {if (null != wr) {wr.close();}} catch (Exception e2) {}}}

拷贝与字节流相同,这里不再举例。由于字符流不能处理非文本文件,所以不能用来拷贝文件夹。

处理流

以上所讲述的字节流和字符流都属于节点流,是文件传输的基本流。处理流和节点流不同,它不能用来直接传输数据,而是用来加强节点流的功能,进而提升传输性能。就之前抽水的例子,你可以把想象处理流为在水管上加一个电动抽水器,加快抽水速度。

缓冲流

缓冲流是最常用的处理流,Java中的缓冲流类为BufferedReader和BufferedWriter,它的使用非常简单,直接在构造函数中传入流对象就可以实现,使用方法如下:

reader =new BufferedReader(new FileReader(new File(地址)));
wr =new BufferedWriter(new FileWriter(new File(地址)));

对于缓冲流最常用的操作就是字符流中的readLine方法,它大大简化了读取文件的操作,下面就是一个缓冲流的使用案例:

public static void main(String[] args) {//创建源 仅限于 字符的纯文本File src =new File("E:/xp/test/Demo03.java");File dest =new File("e:/xp/test/char.txt");//选择流BufferedReader reader =null;     BufferedWriter wr =null;try {reader =new BufferedReader(new FileReader(src));wr =new BufferedWriter(new FileWriter(dest));//新增方法的操作String line =null;//readLine方法可以按行进行读取,不用在建立字节数组进行接收,大大简化了操作while(null!=(line=reader.readLine())){wr.write(line);//wr.append("\r\n");wr.newLine(); //换行符号}wr.flush();//强制刷出} catch (FileNotFoundException e) {e.printStackTrace();System.out.println("源文件不存在");} catch (IOException e) {e.printStackTrace();System.out.println("文件读取失败");}finally{try {if (null != wr) {wr.close();}} catch (Exception e2) {}try {if (null != reader) {reader.close();}} catch (Exception e2) {}}}

转换流

编码和解码

我们都知道计算机处理的文件称之为二进制文件,但二进制文件不能被我们直接阅读,所以需要将二进制数据翻译为文本数据,这个翻译过程就称为解码,同样我们输入电脑的文本数据也需要翻译成二进制数据读入电脑,这个翻译过程被称为编码。
字符集就是编码和解码过程中用来翻译的工具,但不同的字符集会带来乱码问题乱码问题(在基础篇第一节就有讲解,链接),在文件操作中一不注意就会产生字符集不同的情况。比如我们ecilpse中设置的字符集如下:

如果用GBK的方式打开之前的文件不会有问题(ANSI就是GBK)

我们之前写出的文件的编码设置为UTF-8,就会出现乱码的情况:


为避免这种情况我们需要手动设定编码集。
Java中可以通过String类getBytes()对数据进行编码

 public static void test1() throws UnsupportedEncodingException{//解码 byte -->charString str ="中国"; //gbk //编码 char -->bytebyte[] data =str.getBytes();//编码与解码字符集同一System.out.println(new String(data));data =str.getBytes("utf-8"); //设定编码字符集//不同一出现乱码System.out.println(new String(data));//编码byte[] data2 = "中国".getBytes("utf-8");//解码str=new String(data2,"utf-8");System.out.println(str);}

转换流就是将字节流转换为字符流的操作,它的主要作用是处理复制文件过程中的乱码问题。

转换流实现

Java中转换流对应的类为OutputStreamWriter和InputStreamReader。注意转换流只能将字节流转化为字符流,没有逆向操作。
指定编码和解码字符集:

 public static void main(String[] args) throws IOException {//指定解码字符集BufferedReader br =new BufferedReader(//缓冲流new InputStreamReader(//转换流new BufferedInputStream(//缓冲流new FileInputStream( //节点流new File("E:/xp/test/Demo03.java"))),"UTF-8")//通过转换流指定字符集);//写出文件 编码BufferedWriter bw =new BufferedWriter(//缓冲流new OutputStreamWriter(//转换流new BufferedOutputStream( //缓冲流new FileOutputStream(new //节点流File("E:/xp/test/encode.java")))));String info =null;while(null!=(info=br.readLine())){//System.out.println(info);bw.write(info);bw.newLine();}bw.flush();bw.close();br.close();}
}

上一篇:菜鸟学习笔记:Java提升篇4(容器4——Collections工具类、其他容器)

下一篇:菜鸟学习笔记:Java提升篇6(IO流2——数据类型处理流、打印流、随机流)

菜鸟学习笔记:Java提升篇5(IO流1——IO流的概念、字节流、字符流、缓冲流、转换流)相关推荐

  1. 决策树算法学习笔记(提升篇)

    声明:本文虽有部分自己理解成分,但是大部分摘自以下链接. 决策树(decision tree)(三)--连续值处理 决策树参数讲解+实例 数据挖掘十大算法 C4.5算法的改进: 用信息增益率来选择属性 ...

  2. 菜鸟学习笔记:Java提升篇6(IO流2——数据类型处理流、打印流、随机流)

    菜鸟学习笔记:Java IO流2--其他流 字节数组输入输出流 数据类型处理流 基本数据类型 引用类型 打印流 System.in.System.out.System.err 随机流RandomAcc ...

  3. 菜鸟学习笔记:Java提升篇10(网络2——UDP编程、TCPSocket通信、聊天室案例)

    菜鸟学习笔记:Java提升篇10(网络2--UDP编程.TCPSocket通信) UDP编程 TCP编程(Socket通信) 单个客户端的连接 多个客户端的连接(聊天室案例) UDP编程 在上一篇中讲 ...

  4. 菜鸟学习笔记:Java提升篇9(网络1——网络基础、Java网络编程)

    菜鸟学习笔记:Java提升篇9(网络1--网络基础.Java网络编程) 网络基础 什么是计算机网络 OS七层模型 Java网络编程 InetAddress InetSocketAddress URL类 ...

  5. 菜鸟学习笔记:Java提升篇4(容器4——Collections工具类、其他容器)

    菜鸟学习笔记:Java容器4--Collections工具类.其他容器 Collections工具类 容器其他知识点 队列Queue Enumeration接口 Hashtable Propertie ...

  6. 菜鸟学习笔记:Java提升篇12(Java动态性2——动态编译、javassist字节码操作)

    菜鸟学习笔记:Java提升篇12(Java动态性2--动态编译.javassist字节码操作) Java的动态编译 通过脚本引擎执行代码 Java字节码操作 JAVAssist的简单使用 常用API ...

  7. 菜鸟学习笔记:Java提升篇11(Java动态性1——注解与反射)

    Java提升篇11(Java其它高级特性--注解与反射) 注解(Annotation) JDK内置注解 自定义注解 元注解(meta-annotation) 反射(reflection) 动态语言 反 ...

  8. 菜鸟学习笔记:Java提升篇8(线程2——线程的基本信息、线程安全、死锁、生产者消费者模式、任务调度)

    菜鸟学习笔记:Java提升篇8(线程2--线程的基本信息.线程安全.死锁.生产者消费者模式.任务调度) 线程的基本信息 线程同步 线程安全 死锁 生产者消费者模式 任务调度(了解) 线程的基本信息 J ...

  9. 菜鸟学习笔记:Java提升篇3(容器3——泛型、排序)

    菜鸟学习笔记:Java容器3--泛型.排序 泛型 泛型类 泛型接口 泛型方法 泛型继承 通配符"?" 泛型知识点补充 容器排序 Comparable接口与compareTo方法 C ...

最新文章

  1. python实现单例_Python 实现单例模式
  2. 【Extjs】large按钮,图片全部覆盖按钮
  3. C++primer 10.2.1节练习
  4. 无锡锡东2021高考成绩查询,2021年无锡高考成绩查询网址,无锡高考成绩查询系统时间安排...
  5. python抽奖概率设计_通过python分析原神,结果出现了“这种情况”
  6. 二叉树经典题之线索二叉树(中序)
  7. Exp3 免杀原理与实践 20164314
  8. python simdjson_python+json
  9. 【linux】一次性杀死多个同名进程
  10. [C++]指针与引用(应用辨析)
  11. torch.optim.lr_scheduler:调整学习率
  12. MFC BMP设置Bitmap的分辨率DPI为600点 gdiplus 生成标签
  13. 中英文停用词(stop word)列表
  14. 纯js实现数据导出excel表格
  15. 雅思c1语言等级,雅思分数各代表什么水平
  16. postgresql客户端远程连接
  17. Windows下删除文件夹提示找不到该项目,请确认该项目的位置,然后重试。
  18. php 生成pdf 图片转pdf
  19. html左边导航栏点击下拉显示内容,html导航栏-简单运用display设置左拉和下拉导航栏...
  20. 香蕉树上第十一根芭蕉——vs一些操作设置

热门文章

  1. 排序算法(2)----插入排序
  2. 知荐 | 自动驾驶的“大脑”:决策规划篇
  3. 网页web前端学习技巧
  4. C++中宏的定义与用法(现已被内联函数所代替)
  5. EASYUI- EASYUI左移右移 GRID中值
  6. 自动变量和开辟内存的生存期和作用域探讨
  7. linux网络编程之socket:使用fork并发处理多个client的请求
  8. iphone 使用Core Graphics 剪贴图片
  9. java 蓝桥杯历届试题 分糖果(题解)
  10. Telnet三步完成连接(简短版)