一、字符流

当使用字节流读取文本文件时,可能会有一个小问题。就是遇到中文字符时,可能不会显示完整的字符,那是因为一个中文字符可能占用多个字节存储。所以Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文件。

1.1 字符输入流【Reader】

java.io.Reader抽象类是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中。它定义了字符输入流的基本共性功能方法。字符输入流,是字符输入流的最顶层的父类,定义了一些共性的成员方法,是一个抽象类

  • 共性的成员方法:
    ①、int read(): 读取单个字符并返回。
    ②、int read(char[] cbuf):一次读取多个字符,将字符读入数组。
    ③、void close():关闭该流并释放与之关联的所有资源。

1.2 FileReader类

java.io.FileReader类是读取字符文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。

  • java.io.FileReader extends InputStreamReader extends Reader
    FileReader:文件字符输入流
    作用:把硬盘文件中的数据以字符的方式读取到内存中

小贴士:

  1. 字符编码:字节与字符的对应规则。Windows系统的中文编码默认是GBK编码表。

    idea中UTF-8

  2. 字节缓冲区:一个字节数组,用来临时存储字节数据。

构造方法

  • FileReader(File file): 创建一个新的 FileReader ,一个文件。
  • FileReader(String fileName): 创建一个新的 FileReader ,文件的路径。

当你创建一个流对象时,必须传入一个文件路径。类似于FileInputStream 。

  • FileReader构造方法的作用:①.创建一个FileReader对象②.会把FileReader对象指向要读取的文件

  • 构造举例,代码如下:

public class FileReaderConstructor throws IOException{public static void main(String[] args) {// 使用File对象创建流对象File file = new File("a.txt");FileReader fr = new FileReader(file);// 使用文件名称创建流对象FileReader fr = new FileReader("b.txt");}
}

读取字符数据

  • 字符输入流的使用步骤:
    ①、创建FileReader对象,构造方法中绑定要读取的数据源、
    ②、使用FileReader对象中的方法read读取文件
    ③、释放资源
  1. 读取字符read方法,每次可以读取一个字符的数据,提升为int类型,读取到文件末尾,返回-1,循环读取,代码使用演示:
public class DemoReader{public static void main(String[] args) throws Exception {//1.创建FileReader对象,构造方法中绑定要读取的数据源FileReader fr = new FileReader("D:\\test\\a.txt");//2.使用FileReader对象中的方法read读取文件//int read() 读取单个字符并返回int len = 0;while ((len=fr.read())!=-1){System.out.print((char)len);}//3.释放资源fr.close();}
}输出结果:
你好abc123###

小贴士:虽然读取了一个字符,但是会自动提升为int类型。

  1. 使用字符数组读取read(char[] cbuf),每次读取b的长度个字符到数组中,返回读取到的有效字符个数,读取到末尾时,返回-1 ,代码使用演示:
public class DemoReader{public static void main(String[] args) throws Exception {//1.创建FileReader对象,构造方法中绑定要读取的数据源FileReader fr = new FileReader("D:\\test\\a.txt");//2.使用FileReader对象中的方法read读取文件//int read(char[] arr)一次读取多个字符,将字符读入数组。char[] cs = new char[1024];//存储读取到的多少个字符int len = 0;//读取的是每次读取的有效字符的个数while ((len=fr.read(cs))!=-1){/*String类的构造方法String(char[] value):把字符数组转换为字符串String(char[] value,int offset,int count):把字符数组的一部分转换为字符串 offset数组的开始索引 count转换的个数*/System.out.println(new String(cs,0,len));}//3.释放资源fr.close();}
}
输出结果:
你好abc123###

1.3 字符输出流【Writer】

java.io.Writer抽象类是表示用于写出字符流的所有类的超类,将指定的字符信息写出到目的地。它定义了字节输出流的基本共性功能方法。

  • void write(int c) 写入单个字符。
  • void write(char[] cbuf)写入字符数组。
  • abstract void write(char[] cbuf, int off, int len)写入字符数组的某一部分,off数组的开始索引,len写的字符个数。
  • void write(String str)写入字符串。
  • void write(String str, int off, int len) 写入字符串的某一部分,off字符串的开始索引,len写的字符个数。
  • void flush()刷新该流的缓冲。
  • void close() 关闭此流,但要先刷新它。

1.4 FileWriter类

java.io.FileWriter类是写出字符到文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。

构造方法

  • FileWriter(File file): 根据给定的File对象构造一个FileWriter对象。 String fileName:文件的路径
  • FileWriter(String fileName): 根据给定的文件名构造一个FileWriter对象。 File file:是一个文件

当你创建一个流对象时,必须传入一个文件路径,类似于FileOutputStream。

  • 构造方法的使用:
    ①、会创建一个FileWriter对象
    ②、会出根据构造方法中传递的文件/文件的路径,创建文件
    ③、会把FileWriter对象指向创建好的文件

  • 构造举例,代码如下:

public class FileWriterConstructor {public static void main(String[] args) throws IOException {// 使用File对象创建流对象File file = new File("a.txt");FileWriter fw = new FileWriter(file);// 使用文件名称创建流对象FileWriter fw = new FileWriter("b.txt");}
}

基本写出数据

  • java.io.FileWriter extends OutputStreamWriter extends Writer
    FileWriter:文件字符输出流,作用:把内存中的字符数据写入到文件中

  • 字符输出流的使用步骤(重点):
    ①、创建FileWriter对象,构造方法中绑定要写入数据的目的地
    ②、使用FileWriter中的方法writer,把数据写入到内存缓冲区中(字符转换为字节的过程)
    ③、使用FileWriter中的方法flush,把内存缓冲区中的数据,刷新到文件中
    ④、释放资源(会先把内存缓冲区中的数据刷新到文件中)

写出字符write(int b) 方法,每次可以写出一个字符数据,代码使用演示:

public class DemoWriter{public static void main(String[] args) throws Exception {//1.创建FileWriter对象,构造方法中绑定要写入数据的目的地FileWriter fw = new FileWriter("D:\\test\\a.txt");//2.使用FileWriter中的方法writer,把数据写入到内存缓冲区中(字符转换为字节的过程)//void write(int c)写入单个字符fw.write(97);//3.使用FileWriter中的方法flush,把内存缓冲区中的数据,刷新到文件中fw.flush();//4.释放资源(会先把内存缓冲区中的数据刷新到文件中)fw.close();}
}
输出结果:
a

小贴士:

  1. 虽然参数为int类型四个字节,但是只会保留一个字符的信息写出。
  2. 未调用close方法,数据只是保存到了缓冲区,并未写出到文件中。

关闭和刷新

因为内置缓冲区的原因,如果不关闭输出流,无法写出字符到文件中。但是关闭的流对象,是无法继续写出数据的。如果我们既想写出数据,又想继续使用流,就需要flush 方法了。

  • flush :刷新缓冲区,流对象可以继续使用。
  • close:先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了。

代码使用演示:

public class DemoWriter{public static void main(String[] args) throws Exception {//1.创建FileWriter对象,构造方法中绑定要写入数据的目的地FileWriter fw = new FileWriter("D:\\test\\a.txt");//2.使用FileWriter中的方法writer,把数据写入到内存缓冲区中(字符转换为字节的过程)//void write(int c)写入单个字符fw.write(97);//3.使用FileWriter中的方法flush,把内存缓冲区中的数据,刷新到文件中fw.flush();//刷新之后流可以继续使用fw.write(98);//4.释放资源(会先把内存缓冲区中的数据刷新到文件中)fw.close();//close方法之后流已经关闭了,已经从内存中消失了,流就不能再使用了//fw.write(99);//IOException: Stream closed}
}
运行结果:ab

小贴士:即便是flush方法写出了数据,操作的最后还是要调用close方法,释放系统资源。

写出其他数据

  1. 写出字符数组write(char[] cbuf)write(char[] cbuf, int off, int len) ,每次可以写出字符数组中的数据,用法类似FileOutputStream,代码使用演示:
public class DemoWriter{public static void main(String[] args) throws Exception {FileWriter fw = new FileWriter("D:\\test\\a.txt");char[] cs = {'a','b','c','d','e'};//void write(char[] cbuf)写入字符数组。fw.write(cs);//abcde//abstract void write(char[] cbuf, int off, int len)写入字符数组的某一部分,off数组的开始索引,len写的字符个数。fw.write(cs,1,3);//bcdfw.close();}
}
  1. 写出字符串write(String str)write(String str, int off, int len) ,每次可以写出字符串中的数据,更为方便,代码使用演示:
public class DemoWriter{public static void main(String[] args) throws Exception {FileWriter fw = new FileWriter("D:\\test\\a.txt");//void write(String str)写入字符串。fw.write("怪盗基德");//怪盗基德//void write(String str, int off, int len) 写入字符串的某一部分,off字符串的开始索引,len写的字符个数。fw.write("路飞海贼王",2,3);//海贼王fw.close();}
}
  1. 续写和换行:操作类似于FileOutputStream。
  • 续写和换行

    • 续写:追加写:使用两个参数的构造方法
      FileWriter(String fileName,boolean append)
      FileWriter(File file,boolean append)
      参数:
      String fileName:写入数据的目的地
      File file:续写开关
      ①、true:不会创建新的文件覆盖源文件,可以续写
      ②、false:创建新的文件覆盖源文件
    • 换行:换行符号
      Windows:\r\n
      Linux:/n
      mac:/r
public class DemoWriter{public static void main(String[] args) throws IOException {FileWriter fw = new FileWriter("D:\\test\\a.txt");for (int i = 0; i < 3; i++) {fw.write("HelloWorld"+i+"\r\n");}fw.close();}
}
输出结果:
HelloWorld0
HelloWorld1
HelloWorld2

小贴士:字符流,只能操作文本文件,不能操作图片,视频等非文本文件。

当我们单纯读或者写文本文件时 使用字符流 其他情况使用字节流

二、IO异常的处理

JDK7前处理

之前的入门练习,我们一直把异常抛出,而实际开发中并不能这样处理,建议使用try...catch...finally 代码块,处理异常部分,代码使用演示:

在jdk1.7之前使用try catch finally 处理流中的异常
格式:try{可能会产生异常的代码}catch(异常类变量 变量名){异常的处理逻辑}finally{一定会指定的代码释放资源}
public class DemoCatch{public static void main(String[] args) {//提高变量fw的作用域,让finally可以使用//变量在定义的时候,可以没有值,但是使用的时候必须有值FileWriter fw = null;try{//可能会产生异常的代码fw = new FileWriter("D:\\test\\a.txt");for (int i = 0; i < 3; i++) {fw.write("HelloWorld"+i+"\r\n");}}catch(IOException e){//异常的处理逻辑System.out.println(e);}finally{//一定会指定的代码//创建对象失败了,fw的默认值就是null,null是不能调用方法的,会抛出异常NullPointerException需要增加判断,不是null再把资源放掉if (fw!=null){try {//fw.close();方法声明抛出了IOException异常对象,所以我们就需要处理这个异常fw.close();} catch (IOException e) {e.printStackTrace();}}}}
}

JDK7的处理(扩展知识点了解内容)

还可以使用JDK7优化后的try-with-resource 语句,该语句确保了每个资源在语句结束时关闭。所谓的资源(resource)是指在程序完成后,必须关闭的对象。

  • JDK7的新特性: 在try的后边可以增加一个(),在括号中可以定义流对象;那么这个流对象的作用域在try中有效;try中的代码执行完毕,会自动把流对象释放,不用写finally

格式:

try (创建流对象语句,如果多个,使用';'隔开) {// 读写数据
} catch (IOException e) {e.printStackTrace();
}

代码使用演示:

public class HandleException2 {public static void main(String[] args) {// 创建流对象try ( FileWriter fw = new FileWriter("fw.txt"); ) {// 写出数据fw.write("黑马程序员"); //黑马程序员} catch (IOException e) {e.printStackTrace();}}
}

JDK9的改进(扩展知识点了解内容)

JDK9中try-with-resource 的改进,对于引入对象的方式,支持的更加简洁。被引入的对象,同样可以自动关闭,无需手动close,我们来了解一下格式。

  • JDK9新特性:
    ①、try的前面可以定义流对象
    ②、在try后边的()中可以直接引入流对象的名称(变量名)
    ③、在try代码执行完毕后,流对象也可以释放掉,不用谢finally
    改进前格式:
A a = new A();
B b = new B();
try(a,b){可能会产生异常的代码
}catch(异常类变量 变量名){异常的处理逻辑
}

改进后,代码使用演示:

public class TryDemo {public static void main(String[] args) throws IOException {// 创建流对象final  FileReader fr  = new FileReader("in.txt");FileWriter fw = new FileWriter("out.txt");// 引入到try中try (fr; fw) {// 定义变量int b;// 读取数据while ((b = fr.read())!=-1) {// 写出数据fw.write(b);}} catch (IOException e) {e.printStackTrace();}}
}

三、 属性集

3.1 概述

java.util.Properties 继承于Hashtable ,来表示一个持久的属性集。它使用键值结构存储数据,每个键及其对应值都是一个字符串。该类也被许多Java类使用,比如获取系统属性时,System.getProperties 方法就是返回一个Properties对象。

  • Properties集合是一个唯一和IO流相结合的集合

3.2 Properties类

构造方法

  • public Properties() :创建一个空的属性列表。

基本的存储方法

  • 属性列表中的每个键及其对应值都是一个字符串
    Properties集合是一个双列集合,key和value默认都是字符串

  • public Object setProperty(String key, String value) : 保存一对属性。

  • public String getProperty(String key) :使用此属性列表中指定的键搜索属性值。

  • public Set<String> stringPropertyNames() :所有键的名称的集合。

public class DemoProperties{public static void main(String[] args) {show01();}/*使用Properties集合存储数据,遍历取出Properties集合中的数据Properties集合是一个双列集合,key和value都是字符串Properties集合有一些操作字符串的特有方法Object setProperty(String key,String value)调用Hashtable的方法putString getProperty(String key)通过key找到value值,此方法相当于Map集合中的get(key)方法Set<String> stringPropertyNames() 返回此属性列表中的键集,其中该键及其对应值是字符串,此方法相当于Map集合中的keySet方法*/private static void show01() {//创建Properties集合对象Properties prop = new Properties();//使用setProperty往集合中添加数据prop.setProperty("路飞","168");prop.setProperty("索隆","165");prop.setProperty("山治","160");//使用stringPropertyNames把Properties集合中的键取出,存储到一个Set集合中Set<String> set = prop.stringPropertyNames();//遍历Set集合,取出Properties集合的每一个键for (String key : set) {//使用getProperty方法通过key获取valueString value = prop.getProperty(key);System.out.println(key+"="+value);}}
}
输出结果:
索隆=165
山治=160
路飞=168

与流相关的方法

(1)Properties集合中的store方法

  • 可以使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储
    ①、void store(OutputStream out,String comments)
    ②、void store(Writer writer,String comments)

  • 参数:
    OutputStream out:字节输出流,不能写入中文
    Writer writer:字符输出流,可以写中文
    String comments:注释,用来解释说明保存的文件是做什么用的
    不能使用中文,会产生乱码,默认是Unicode编码
    一般使用" " 空字符串

  • 使用步骤:
    ①、创建Properties集合对象,添加数据
    ②、创建字节输出流/字符输出流对象,构造方法中绑定要输出的目的地
    ③、使用Properties集合中的方法store,把集合只能的临时数据,持久化写入到硬盘中存储
    ④、释放资源

public class DemoProperties{public static void main(String[] args) throws IOException {show02();}private static void show02() throws IOException {//1.创建Properties集合对象,添加数据Properties prop = new Properties();prop.setProperty("路飞","168");prop.setProperty("索隆","165");prop.setProperty("山治","160");//2.创建字节输出流/字符输出流对象,构造方法中绑定要输出的目的地FileWriter fw = new FileWriter("D:\\test\\a.txt");//3.使用Properties集合中的方法store,把集合只能的临时数据,持久化写入到硬盘中存储prop.store(fw,"save date");//4.释放资源fw.close();//也可以使用下面的方法,但是会产生乱码//prop.store(new FileOutputStream("D:\\test\\a.txt"),"");}
}

(2)Properties集合中的load方法

  • public void load(InputStream inStream): 从字节输入流中读取键值对。

  • 可以使用Properties集合中的方法load,把硬盘中保存的文件(键值对),读取到集合中使用
    ①、 void load(InputStream inStream)
    ②、void load(Reader reader)

  • 参数:
    InputStream inStream:字节输入流,不能读取含有中文的键值对
    Reader reader:字符输入流,能读取含有中文的键值对

  • 使用步骤:
    ①、创建Properties集合对象
    ②、使用Properties集合对象中的方法load读取保存键值对的文件
    ③、遍历Properties集合

  • 注意事项:
    ①、存储键值对的文件中,键与值默认的连接符号可以使用=,空格(其他符号)
    ②、存储键值对的文件中,可以使用#进行注释,被注释键值对不会再被读取
    ③、存储键值对的文件中,键与值默认都是字符串,不用再加引号

public class DemoProperties{public static void main(String[] args) throws Exception {show03();}private static void show03() throws Exception {//1.创建Properties集合对象Properties prop = new Properties();//2.使用Properties集合对象中的方法load读取保存键值对的文件prop.load(new FileReader("D:\\test\\a.txt"));//也可以采用下面的方法,但是会产生乱码//prop.load(new FileInputStream("D:\\test\\a.txt"));//3.遍历Properties集合Set<String> set = prop.stringPropertyNames();for (String key : set) {String value = prop.getProperty(key);System.out.println(key+"="+value);}}
}
输出结果:
山治=160
索隆=165
路飞=168

小贴士:文本中的数据,必须是键值对形式,可以使用空格、等号、冒号等符号分隔。

字符流的相关概念和相关方法的使用、IO异常的处理以及Properties属性集相关推荐

  1. Java笔记整理六(File类,递归,字节流IO,字符流IO,流中的异常处理,属性集Properties,缓冲流,转换流,序列化,打印流)

    1.File类 java.io.File 类是文件和目录路径名的抽象表示,主要用于文件和目录的创建.查找和删除等操作. 文件和目录路径名的抽象表示 java把文件和文件夹封装位为一个File类,我们可 ...

  2. java 文件字节流_Java:文件字符流和字节流的输入和输出

    最近在学习Java,所以就总结一篇文件字节流和字符流的输入和输出. 总的来说,IO流分类如下: 输入输出方向:     输入流(从外设读取到内存)和输出流(从内存输出到外设) 数据的操作方式: 字节流 ...

  3. IO流、字节流和字符流

    Java 一.IO流 1.1 概念 1.2 分类 1.3 IO流的父类 二.字节流 2.1 概念 2.2 OutputStream 2.2.1 常用方法 2.2.2 FileOutputStream类 ...

  4. 【java笔记】字符流,Properties,序列化,打印流

    字符流 字符流=字节流+编码 package demo04;import java.io.FileInputStream; import java.io.FileNotFoundException; ...

  5. Java基础(十五)IO流---字符流(Reader、Writer)、字节流(InputStream、OutputStream)

    IO流(应用广泛) 1.概念与三要素 本质是一套用于数据传输的机制 分类: 根据传输的方向(参照物–内存) 输入流:往内存传输数据 输出流:从内存往外传输数据 根据数据传输方式: 字符流:底层以字符形 ...

  6. Stream流、FiLe和IO流、IO流(字节流-拷贝文件_和_字符流-读取文本中的数据写入文本文件中)9-10-11

    package com.streamdemo; import java.util.ArrayList; import java.util.List; /*** 体验Stream流** 创建一个集合,存 ...

  7. Stoker的Java学习之字节流与字符流

    Java学习之字节流与字符流 一. 字节流 字节流是在java.io包中操作文件内容的一大类,字节流将文字图片音频等文件转换成字节,进行数据传输. 在字节流中输出数据主要是使用OutputStream ...

  8. java中io流是类吗_Java中的IO流

    今天刚刚看完java的io流操作,把主要的脉络看了一遍,不能保证以后使用时都能得心应手,但是最起码用到时知道有这么一个功能可以实现,下面对学习进行一下简单的总结: IO流主要用于硬板.内存.键盘等处理 ...

  9. java(十)【属性集,缓冲流、转换流、序列化流】

    day10[缓冲流.转换流.序列化流] 今日目标 IO资源的处理. finnally释放资源 jdk 1.7开始的新技术 try-with-resources 缓冲流 提高字节流和字符流读写数据的性能 ...

最新文章

  1. c++连接oracle数据库程序,无法从c++程序连接到我的oracle数据库
  2. 基于pygame的射击小游戏制作(四)击杀外星人
  3. 789. 逃脱阻碍者
  4. vue 将行转换成对象_Vue简化版实现
  5. 单身汪的电梯之旅(洛谷P1897题题解,Java语言描述)
  6. java nslookup_nslookup使用教程
  7. c++ 遍历所有点且距离最短_图解:最短路径之迪杰斯特拉算法
  8. DRP:基本环境安装中遇到那些事儿
  9. 关于VOID *在cl与gcc的不同(无意中发现)
  10. mysql 5.6的安装
  11. Cadence OrCAD Capture 锁定工程和图纸图文视频教程
  12. java p2p实例_java文件p2p传输
  13. struts2拦截器,拦截指定方法
  14. win10 ie设置不了代理服务器
  15. 一个迷茫的应届生程序员
  16. stata基础使用教程(操作版)
  17. uboot启动流程详解
  18. BLE MESH组网(一)简介和基本概念
  19. 计算机技术在物理教学中的应用,信息技术在物理教学中的运用案例与感悟
  20. CodeGear公司正式推出delphi2007 for win32

热门文章

  1. PHP验证身份证类(包含香港身份证校验)
  2. 2021年国企、银行求职面经汇总(更新中)
  3. 如何把两张图片拼在一起?
  4. python 交叉验证后获取模型_Pysal:如何使用Pysal回归模型进行交叉验证? - python
  5. 实现不同的导航条,看直播app开发怎么做
  6. 批量将磁盘上所有文件的路径地址、文件名、扩展名和文件夹名整理到 Excel 表格中
  7. 【C/C++】基础概念
  8. 怎么把图片压缩到200K以内?如何在线压缩图片大小?
  9. 用Python写一个程序,解密游戏内抽奖的秘密
  10. 多视图多示例多标签的协同矩阵分解