Java 字符流

1.字符流

1.1为什么会出现字符流

字符流的介绍

  由于字节流操作中文不是特别的方便,所以Java就提供字符流

  字符流 = 字节流 + 编码表

中文的字节存储方式

用字节流复制文本文件时,文本文件也会有中文,但是没有问题,原因是最终底层操作会自动进行字节拼接成中文,如何识别是中文的呢?

汉字在存储的时候,无论选择哪种编码存储,第一个字节都是负数

1.2编码表

什么是字符集

  是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等

计算机要准确的存储和识别各种字符集符号,就需要进行字符编码,一套字符集必然至少有一套字符编码。常见字符集有ASCII字符集、GBXXX字符集、Unicode字符集等

常见的字符集

ASCII字符集:

    lASCII:是基于拉丁字母的一套电脑编码系统,用于显示现代英语,主要包括控制字符(回车键、退格、换行键等)和可显示字符(英文大小写字符、阿拉伯数字和西文符号) 

    基本的ASCII字符集,使用7位表示一个字符,共128字符。ASCII的扩展字符集使用8位表示一个字符,共256字符,方便支持欧洲常用字符。是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等

GBXXX字符集:

    GBK:最常用的中文码表。是在GB2312标准基础上的扩展规范,使用了双字节编码方案,共收录了21003个汉字,完全兼容GB2312标准,同时支持繁体汉字以及日韩汉字等

Unicode字符集:

    UTF-8编码:可以用来表示Unicode标准中任意字符,它是电子邮件、网页及其他存储或传送文字的应用 中,优先采用的编码。互联网工程工作小组(IETF)要求所有互联网协议都必须支持UTF-8编码。它使用一至四个字节为每个字符编码

    编码规则: 

      128个US-ASCII字符,只需一个字节编码

      拉丁文等字符,需要二个字节编码

      大部分常用字(含中文),使用三个字节编码

      其他极少使用的Unicode辅助字符,使用四字节编码

1.3字符串中的编码解码问题

相关方法

方法名说明
byte[] getBytes()使用平台的默认字符集将该 String编码为一系列字节
byte[] getBytes(String charsetName)使用指定的字符集将该 String编码为一系列字节
String(byte[] bytes)使用平台的默认字符集解码指定的字节数组来创建字符串
String(byte[] bytes, String charsetName)通过指定的字符集解码指定的字节数组来创建字符串

代码演示

public class Test02 {public static void main(String[] args) throws IOException {OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("E:\\JavaTXT\\Task\\IO流\\myCharStream\\osw.txt"));osw.write(97);char[] ch = {97,98,99};osw.write("\r\n");osw.write(ch,0,ch.length);osw.close();}
}

1.4字符流中的编码解码问题

字符流中和编码解码问题相关的两类

● InputStreamReader:是从字节流到字符流的桥梁

    ​    它读取字节,并使用指定的编码将其解码为字符

    ​    它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集

● OutputStreamWriter:是从字符流到字节流的桥梁

    ​    是从字符流到字节流的桥梁,使用指定的编码将写入的字符编码为字节

    ​    它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集

构造方法

方法名说明
InputStreamReader(InputStream in)使用默认字符编码创建InputStreamReader对象
InputStreamReader(InputStream in,String chatset)使用指定的字符编码创建
OutputStreamWriter(OutputStream out)使用默认字符编码创建OutputStreamWriter对象
OutputStreamWriter(OutputStream out,String charset)使用指定的字符编码创建OutputStreamWriter对象

代码演示

 public class ConversionStreamDemo {public static void main(String[] args) throws IOException {//OutputStreamWriter osw = new OutputStreamWriter(new                                             FileOutputStream("myCharStream\\osw.txt"));OutputStreamWriter osw = new OutputStreamWriter(new                                              FileOutputStream("myCharStream\\osw.txt"),"GBK");osw.write("中国");osw.close();//InputStreamReader isr = new InputStreamReader(new                                              FileInputStream("myCharStream\\osw.txt"));InputStreamReader isr = new InputStreamReader(new                                                 FileInputStream("myCharStream\\osw.txt"),"GBK");//一次读取一个字符数据int ch;while ((ch=isr.read())!=-1) {System.out.print((char)ch);}isr.close();}}

1.5字符流写数据的5种方式

方法介绍

方法名说明
void   write(int c)写一个字符
void   write(char[] cbuf)写入一个字符数组
void write(char[] cbuf, int off, int len)写入字符数组的一部分
void write(String str)写一个字符串
void write(String str, int off, int len)写一个字符串的一部分

刷新和关闭的方法

方法名 

说明
flush()刷新流,之后还可以继续写数据
close()关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据

代码演示

public class OutputStreamWriterDemo {public static void main(String[] args) throws IOException {OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("myCharStream\\osw.txt"));//void write(int c):写一个字符//        osw.write(97);//        osw.write(98);//        osw.write(99);//void writ(char[] cbuf):写入一个字符数组char[] chs = {'a', 'b', 'c', 'd', 'e'};//        osw.write(chs);//void write(char[] cbuf, int off, int len):写入字符数组的一部分//        osw.write(chs, 0, chs.length);//        osw.write(chs, 1, 3);//void write(String str):写一个字符串//        osw.write("abcde");//void write(String str, int off, int len):写一个字符串的一部分//        osw.write("abcde", 0, "abcde".length());osw.write("abcde", 1, 3);//释放资源osw.close();}}

1.6字符流读数据的2种方式

方法介绍

方法名说明
int read()一次读一个字符数据
int read(char[] cbuf)一次读一个字符数组数据

- 代码演示

 public class InputStreamReaderDemo {public static void main(String[] args) throws IOException {InputStreamReader isr = new InputStreamReader(new FileInputStream("myCharStream\\ConversionStreamDemo.java"));//int read():一次读一个字符数据//        int ch;//        while ((ch=isr.read())!=-1) {//            System.out.print((char)ch);//        }//int read(char[] cbuf):一次读一个字符数组数据char[] chs = new char[1024];int len;while ((len = isr.read(chs)) != -1) {System.out.print(new String(chs, 0, len));}//释放资源isr.close();}}

案例:字符流复制Java文件

案例需求

  把模块目录下的“ConversionStreamDemo.java” 复制到模块目录下的“Copy.java”

代码实现

public class CopyJavaDemo01 {public static void main(String[] args) throws IOException {//根据数据源创建字符输入流对象InputStreamReader isr = new InputStreamReader(new FileInputStream("myCharStream\\ConversionStreamDemo.java"));//根据目的地创建字符输出流对象OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("myCharStream\\Copy.java"));//读写数据,复制文件//一次读写一个字符数据//        int ch;//        while ((ch=isr.read())!=-1) {//            osw.write(ch);//        }//一次读写一个字符数组数据char[] chs = new char[1024];int len;while ((len=isr.read(chs))!=-1) {osw.write(chs,0,len);}//释放资源osw.close();isr.close();}}

案例:字符流复制Java文件改进版

- 案例需求

  使用便捷流对象,把模块目录下的“ConversionStreamDemo.java” 复制到模块目录下的“Copy.java”

代码实现

public class CopyJavaDemo02 {public static void main(String[] args) throws IOException {//根据数据源创建字符输入流对象FileReader fr = new FileReader("myCharStream\\ConversionStreamDemo.java");//根据目的地创建字符输出流对象FileWriter fw = new FileWriter("myCharStream\\Copy.java");//读写数据,复制文件//        int ch;//        while ((ch=fr.read())!=-1) {//            fw.write(ch);//        }char[] chs = new char[1024];int len;while ((len=fr.read(chs))!=-1) {fw.write(chs,0,len);}//释放资源fw.close();fr.close();}}

1.7字符缓冲流

字符缓冲流介绍

 ● BufferedWriter:将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入,可以指定缓冲区大小,或者可以接受默认大小。默认值足够大,可用于大多数用途

 ● BufferedReader:从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取,可以指定缓冲区大小,或者可以使用默认大小。 默认值足够大,可用于大多数用途

构造方法

方法名说明
BufferedWriter(Writer out)创建字符缓冲输出流对象
BufferedReader(Reader in)创建字符缓冲输入流对象

代码演示

public class BufferedStreamDemo01 {public static void main(String[] args) throws IOException {//BufferedWriter(Writer out)BufferedWriter bw = new BufferedWriter(new FileWriter("myCharStream\\bw.txt"));bw.write("hello\r\n");bw.write("world\r\n");bw.close();//BufferedReader(Reader in)BufferedReader br = new BufferedReader(new FileReader("myCharStream\\bw.txt"));//一次读取一个字符数据//        int ch;//        while ((ch=br.read())!=-1) {//            System.out.print((char)ch);//        }//一次读取一个字符数组数据char[] chs = new char[1024];int len;while ((len=br.read(chs))!=-1) {System.out.print(new String(chs,0,len));}br.close();}}

1.8字符缓冲流复制Java文件

案例需求

  把模块目录下的ConversionStreamDemo.java 复制到模块目录下的 Copy.java

代码实现

public class CopyJavaDemo01 {public static void main(String[] args) throws IOException {//根据数据源创建字符缓冲输入流对象BufferedReader br = new BufferedReader(new FileReader("myCharStream\\ConversionStreamDemo.java"));//根据目的地创建字符缓冲输出流对象BufferedWriter bw = new BufferedWriter(new FileWriter("myCharStream\\Copy.java"));//读写数据,复制文件//一次读写一个字符数据//        int ch;//        while ((ch=br.read())!=-1) {//            bw.write(ch);//        }//一次读写一个字符数组数据char[] chs = new char[1024];int len;while ((len=br.read(chs))!=-1) {bw.write(chs,0,len);}//释放资源bw.close();br.close();}}

1.9字符缓冲流特有功能

方法介绍

BufferedWriter:

● void newLine():写一行行分隔符,行分隔符字符串由系统属性定义 

BufferedReader:
● String readLine():读一行文字。 结果包含行的内容的字符串,不包括任何行终止字符如果流的结尾已经到达,则为null 

代码演示

public class BufferedStreamDemo02 {public static void main(String[] args) throws IOException {//创建字符缓冲输出流BufferedWriter bw = new BufferedWriter(new                                                          FileWriter("myCharStream\\bw.txt"));//写数据for (int i = 0; i < 10; i++) {bw.write("hello" + i);//bw.write("\r\n");bw.newLine();bw.flush();}//释放资源bw.close();//创建字符缓冲输入流BufferedReader br = new BufferedReader(new                                                          FileReader("myCharStream\\bw.txt"));String line;while ((line=br.readLine())!=null) {System.out.println(line);}br.close();}}

案例:字符缓冲流特有功能复制Java文件

案例需求

  使用特有功能把模块目录下的ConversionStreamDemo.java 复制到模块目录下的 Copy.java

代码实现

 public class CopyJavaDemo02 {public static void main(String[] args) throws IOException {//根据数据源创建字符缓冲输入流对象BufferedReader br = new BufferedReader(new FileReader("myCharStream\\ConversionStreamDemo.java"));//根据目的地创建字符缓冲输出流对象BufferedWriter bw = new BufferedWriter(new FileWriter("myCharStream\\Copy.java"));//读写数据,复制文件//使用字符缓冲流特有功能实现String line;while ((line=br.readLine())!=null) {bw.write(line);bw.newLine();bw.flush();}//释放资源bw.close();br.close();}}

1.10IO流小结

字节流

字符流

2 练习案例

2.1集合到文件

案例需求

把ArrayList集合中的字符串数据写入到文本文件。要求:每一个字符串元素作为文件中的一行数据

代码实现

public class ArrayListToTxtDemo {public static void main(String[] args) throws IOException {//创建ArrayList集合ArrayList array = new ArrayList();//往集合中存储字符串元素array.add("hello");array.add("world");array.add("java");//创建字符缓冲输出流对象BufferedWriter bw = new BufferedWriter(new FileWriter("myCharStream\\array.txt"));//遍历集合,得到每一个字符串数据for(String s : array) {//调用字符缓冲输出流对象的方法写数据bw.write(s);bw.newLine();bw.flush();}//释放资源bw.close();}}

### 2.2文件到集合【应用】

案例需求

把文本文件中的数据读取到集合中,并遍历集合。要求:文件中每一行数据是一个集合元素

代码实现

public class TxtToArrayListDemo {public static void main(String[] args) throws IOException {//创建字符缓冲输入流对象BufferedReader br = new BufferedReader(new FileReader("myCharStream\\array.txt"));//创建ArrayList集合对象ArrayList array = new ArrayList();//调用字符缓冲输入流对象的方法读数据String line;while ((line=br.readLine())!=null) {//把读取到的字符串数据存储到集合中array.add(line);}//释放资源br.close();//遍历集合for(String s : array) {System.out.println(s);}}}

2.3点名器

案例需求

我有一个文件里面存储了班级同学的姓名,每一个姓名占一行,要求通过程序实现随点名器

代码实现

 public class CallNameDemo {public static void main(String[] args) throws IOException {//创建字符缓冲输入流对象BufferedReader br = new BufferedReader(new FileReader("myCharStream\\names.txt"));//创建ArrayList集合对象ArrayList array = new ArrayList();//调用字符缓冲输入流对象的方法读数据String line;while ((line=br.readLine())!=null) {//把读取到的字符串数据存储到集合中array.add(line);}//释放资源br.close();//使用Random产生一个随机数,随机数的范围在:[0,集合的长度)Random r = new Random();int index = r.nextInt(array.size());//把第6步产生的随机数作为索引到ArrayList集合中获取值String name = array.get(index);//把第7步得到的数据输出在控制台System.out.println("幸运者是:" + name);}}

2.4集合到文件改进版

案例需求

把ArrayList集合中的学生数据写入到文本文件。要求:每一个学生对象的数据作为文件中的一行数据
  ​        格式:学号,姓名,年龄,居住地    举例:itheima001,林青霞,30,西安

代码实现 

//学生类public class Student {private String sid;private String name;private int age;private String address;public Student() {}public Student(String sid, String name, int age, String address) {this.sid = sid;this.name = name;this.age = age;this.address = address;}public String getSid() {return sid;}public void setSid(String sid) {this.sid = sid;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}}//测试类public class ArrayListToFileDemo {public static void main(String[] args) throws IOException {//创建ArrayList集合ArrayList array = new ArrayList();//创建学生对象Student s1 = new Student("itheima001", "林青霞", 30, "西安");Student s2 = new Student("itheima002", "张曼玉", 35, "武汉");Student s3 = new Student("itheima003", "王祖贤", 33, "郑州");//把学生对象添加到集合中array.add(s1);array.add(s2);array.add(s3);//创建字符缓冲输出流对象BufferedWriter bw = new BufferedWriter(new FileWriter("myCharStream\\students.txt"));//遍历集合,得到每一个学生对象for (Student s : array) {//把学生对象的数据拼接成指定格式的字符串StringBuilder sb = new StringBuilder();sb.append(s.getSid()).append(",").append(s.getName()).append(",").append(s.getAge()).append(",").append(s.getAddress());//调用字符缓冲输出流对象的方法写数据bw.write(sb.toString());bw.newLine();bw.flush();}//释放资源bw.close();}}

2.5文件到集合改进版

案例需求

  把文本文件中的数据读取到集合中,并遍历集合。要求:文件中每一行数据是一个学生对象的成员变量值
   举例:itheima001,林青霞,30,西安

代码实现

public class FileToArrayListDemo {public static void main(String[] args) throws IOException {//创建字符缓冲输入流对象BufferedReader br = new BufferedReader(new FileReader("myCharStream\\students.txt"));//创建ArrayList集合对象ArrayList array = new ArrayList();//调用字符缓冲输入流对象的方法读数据String line;while ((line = br.readLine()) != null) {//把读取到的字符串数据用split()进行分割,得到一个字符串数组String[] strArray = line.split(",");//创建学生对象Student s = new Student();//把字符串数组中的每一个元素取出来对应的赋值给学生对象的成员变量值//itheima001,林青霞,30,西安s.setSid(strArray[0]);s.setName(strArray[1]);s.setAge(Integer.parseInt(strArray[2]));s.setAddress(strArray[3]);//把学生对象添加到集合array.add(s);}//释放资源br.close();//遍历集合for (Student s : array) {System.out.println(s.getSid() + "," + s.getName() + "," + s.getAge() + "," + s.getAddress());}}}

3 IO流案例

3.1集合到文件数据排序改进版

案例需求

键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩)。要求按照成绩总分从高到低写入文本文件
        格式:姓名,语文成绩,数学成绩,英语成绩  举例:林青霞,98,99,100

代码实现

//学生类
package com.mychar.test07;public class Student {private String name;private int chinese;private int math;private int english;public Student() {}public Student(String name, int chinese, int math, int english) {this.name = name;this.chinese = chinese;this.math = math;this.english = english;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getChinese() {return chinese;}public void setChinese(int chinese) {this.chinese = chinese;}public int getMath() {return math;}public void setMath(int math) {this.math = math;}public int getEnglish() {return english;}public void setEnglish(int english) {this.english = english;}public int sum(){int sum = getChinese() + getMath() + getEnglish();return sum;}
}
//测试类
package com.mychar.test07;import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;public class Test {public static void main(String[] args) throws IOException {TreeSet ts = new TreeSet<>(new Comparator() {@Overridepublic int compare(Student s1, Student s2) {int num = s2.sum() - s1.sum();int num2 = num == 0 ? s2.getChinese() - s1.getChinese() : num;int num3 = num2 == 0 ? s2.getMath() - s1.getMath() : num2;int num4 = num3 == 0 ? s1.getName().compareTo(s2.getName()) : num3;return num4;}});Scanner sc = new Scanner(System.in);for (int i = 0; i < 5; i++) {System.out.println("请输入学生姓名:");String name = sc.next();System.out.println("请输入该学生的语文成绩:");int chinese = sc.nextInt();System.out.println("请输入该学生的数学成绩:");int math = sc.nextInt();System.out.println("请输入该学生的英语成绩:");int english = sc.nextInt();Student s = new Student(name,chinese,math,english);ts.add(s);}/*for (Student s : ts) {System.out.println(s.getName() + "," + s.getChinese() + "," + s.getMath() + "," + s.getEnglish() + "," +s.sum());}*/BufferedWriter bw = new BufferedWriter(new FileWriter("E:\\JavaTXT\\Task\\IO流\\myCharStream\\students.txt"));for (Student s : ts){StringBuilder sb = new StringBuilder();sb.append(s.getName()).append(",").append(s.getChinese()).append(",").append(s.getMath()).append(",").append(s.getEnglish());bw.write(sb.toString());bw.newLine();bw.flush();}bw.close();}
}

3.2 复制单级文件夹

需求:把一个单级文件夹复制到模块路径下

单级文件夹:文件夹里面只有文件没有文件夹

示例代码:

public class Test {public static void main(String[] args) throws IOException{File srcFolder = new File("D:\\test");String srcFileName = srcFolder.getName();File destFolder = new File("E:\\JavaTXT\\Task\\IO流\\myCharStream",srcFileName);if (!destFolder.exists()){destFolder.mkdir();}File[] listFiles = srcFolder.listFiles();for (File srcFile : listFiles){String destName = srcFile.getName();File destFile = new File(destFolder,destName);copyFiles(srcFile,destFile);}}private static void copyFiles(File list, File destFile) throws IOException {BufferedInputStream bis = new BufferedInputStream(new FileInputStream(list));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));byte[] bys = new byte[1024];int len;while ((len = bis.read(bys)) != -1){bos.write(bys);}bis.close();bos.close();}
}

3.3 复制多级文件夹

需求:把多级文件夹复制到其他盘目录下

示例代码:

public class Test02 {public static void main(String[] args) throws IOException{File srcFolder = new File("D:\\轻音少女桌宠");File destFolder = new File("E:\\");copyFolder(srcFolder,destFolder);}private static void copyFolder(File srcFolder, File destFolder)throws IOException{if (srcFolder.isDirectory()){String srcFolderName = srcFolder.getName();File newFolder = new File(destFolder,srcFolderName);if (!newFolder.exists()){newFolder.mkdir();}File[] filesArr = srcFolder.listFiles();for (File file : filesArr){copyFolder(file,newFolder);}}else {File newFile = new File(destFolder,srcFolder.getName());copyFiles(srcFolder,newFile);}}private static void copyFiles(File srcFile, File destFile) throws IOException {BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));byte[] bys = new byte[1024];int len;while ((len = bis.read(bys)) != -1){bos.write(bys);}bis.close();bos.close();}
}

3.4 复制文件的异常处理

示例代码:

public class CopyFileDemo {public static void main(String[] args) {}//JDK9的改进方案private static void method4() throws IOException {FileReader fr = new FileReader("fr.txt");FileWriter fw = new FileWriter("fw.txt");try(fr;fw){char[] chs = new char[1024];int len;while ((len = fr.read()) != -1) {fw.write(chs, 0, len);}} catch (IOException e) {e.printStackTrace();}}
}//JDK7的改进方案private static void method3() {try(FileReader fr = new FileReader("fr.txt");FileWriter fw = new FileWriter("fw.txt");){char[] chs = new char[1024];int len;while ((len = fr.read()) != -1) {fw.write(chs, 0, len);}} catch (IOException e) {e.printStackTrace();}}
}//try...catch...finallyprivate static void method2() {FileReader fr = null;FileWriter fw = null;try {fr = new FileReader("fr.txt");fw = new FileWriter("fw.txt");char[] chs = new char[1024];int len;while ((len = fr.read()) != -1) {fw.write(chs, 0, len);}} catch (IOException e) {e.printStackTrace();} finally {if(fw!=null) {try {fw.close();} catch (IOException e) {e.printStackTrace();}}if(fr!=null) {try {fr.close();} catch (IOException e) {e.printStackTrace();}}}}//抛出处理private static void method1() throws IOException {FileReader fr = new FileReader("fr.txt");FileWriter fw = new FileWriter("fw.txt");char[] chs = new char[1024];int len;while ((len = fr.read()) != -1) {fw.write(chs, 0, len);}fw.close();fr.close();}
}


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部