字符流解决中文乱码问题、字符缓冲流提高读写效率、IO流小结、转换流、对象操作流、Properties集合与IO流集合的方法

您所在的位置:网站首页 java字符串流 字符流解决中文乱码问题、字符缓冲流提高读写效率、IO流小结、转换流、对象操作流、Properties集合与IO流集合的方法

字符流解决中文乱码问题、字符缓冲流提高读写效率、IO流小结、转换流、对象操作流、Properties集合与IO流集合的方法

2024-06-17 03:26| 来源: 网络整理| 查看: 265

1. 为什么字节流读取纯文本文件,可能会出现乱码? 计算机中储存的信息都是用二进制数表示的按照某种规则,将字符存储到计算机中,称为编码。按照同样的规则,将存储在计算机中的二进制数解析显示出来,称为解码 。编码和解码的方式必须一致,否则会导致乱码。

 ASCII(美国信息交换标准代码):包括了数字,大小写字符和一些常见的标点符号, ASCII码表中没有中文

GBK:window系统默认的码表,兼容ASCII码表,也包含了21003个汉字,一个中文以两个字节的形式存储

Unicode码表:由国际组织ISO 制定,是统一的万国码,IDEA默认使用Unicode的UTF-8编解码格式。以UTF-8编码后一个中文以三个字节的形式存储

因为字节流一次读一个字节,而不管GBK还是UTF-8一个中文都是多个字节,用字节流每次只能读其中的一部分,所以就会出现乱码问题。

2. 字符串中的编码解码问题 方法名说明byte[] getBytes()使用平台的默认字符集将该 String编码为一系列字节byte[] getBytes(String charsetName)使用指定的字符集将该 String编码为一系列字节String(byte[] bytes)使用平台的默认字符集解码指定的字节数组来创建字符串String(byte[] bytes, String charsetName)通过指定的字符集解码指定的字节数组来创建字符串 import java.io.UnsupportedEncodingException; import java.util.Arrays; public class Demo01 { public static void main(String[] args) throws UnsupportedEncodingException { String str = "落霞与孤鹜齐飞,秋水共长天一色"; //解码 byte[] bytes1 = str.getBytes("utf-8"); byte[] bytes2 = str.getBytes("gbk"); System.out.println("utf-8:"+ Arrays.toString(bytes1)); System.out.println("gbk:"+ Arrays.toString(bytes2)); //编码 String s1 = new String(bytes1, "utf-8"); String s2 = new String(bytes2, "gbk"); System.out.println(s1); System.out.println(s2); } } 3. 字符流

字符流在读取纯文本文件时,当遇到中文时会根据码表,读取对应2个字节或者3个字节

对文件进行拷贝,一律使用字节流或者字节缓冲流把文件中的数据读到内存中打印或者读到内存中运算,使用字符输入流。把集合,数组,键盘录入等数据写到文件中,使用字符输出流 3.1 字符输出流写数据

Writer: 字符输出流的抽象父类

FileWriter: 字符输出流的常用子类

构造方法:

方法名说明FileWriter(File file)根据给定的 File 对象构造一个 FileWriter 对象FileWriter(String fileName)根据给定的文件名构造一个 FileWriter 对象

成员方法:

方法名说明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()关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据 import java.io.FileWriter; import java.io.IOException; public class Demo02 { public static void main(String[] args) throws IOException { //字符输出流对象 FileWriter fileWriter = new FileWriter("day12_exercise\\aaa.txt"); //一次写一个字符 int a = 97; fileWriter.write(a);//将97对应字符写到aaa.txt //一次写一个字符数组的一部分 char[] chars = {97, 98, 99, 100}; fileWriter.write(chars,0,2); //写一个字符串 String line = "落霞与孤鹜齐飞"; fileWriter.write(line);//直接将字符串写到aaa.txt //刷新 fileWriter.flush(); //释放资源 fileWriter.close(); } } 3.2 字符输入流读数据

Reader: 字符输入流的抽象父类

FileReader: 字符输入流的常用子类

构造方法:

方法名说明FileReader(File file)在给定从中读取数据的 File 的情况下创建一个新 FileReaderFileReader(String fileName)在给定从中读取数据的文件名的情况下创建一个新 FileReader

成员方法:

方法名说明int read()一次读一个字符数据int read(char[] cbuf)一次读一个字符数组数据 import java.io.FileReader; import java.io.IOException; public class Demo03 { public static void main(String[] args) throws IOException { FileReader fileReader = new FileReader("day12_exercise\\aaa.txt"); //一次读取一个字符 int cha; while ((cha = fileReader.read()) != -1){ System.out.println((char) cha); } fileReader.close(); System.out.println("========================"); FileReader fileReader1 = new FileReader("day12_exercise\\aaa.txt"); //一次读取一个字符数组 int len; char[] chars = new char[1024]; while ((len = fileReader1.read(chars)) != -1){ String s = new String(chars, 0, len); System.out.println(s); } fileReader1.close(); } } 3.3 字符缓冲流

BufferedWriter:将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入。

BufferedReader:从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取。

构造方法:

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

特有方法介绍:

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

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

案例:使用字符缓冲流读取文件中的数据,排序后再次写到本地文件

import java.io.*; import java.util.Arrays; public class Demo02 { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader( new FileReader("day12_exercise\\bbb.txt")); //读取一行数据 String line = br.readLine(); String[] strArr = line.split(" "); int[] intArr = new int[strArr.length]; for (int i = 0; i < strArr.length; i++) { intArr[i] = Integer.parseInt(strArr[i]); } //排序 Arrays.sort(intArr); //重新写回本地文件 BufferedWriter bw = new BufferedWriter( new FileWriter("day12_exercise\\bbb.txt")); for (int i = 0; i < intArr.length; i++) { bw.write(intArr[i]+" "); } bw.flush(); bw.close(); br.close(); } } 4. IO流小结

5. 转换流 InputStreamReader:是从字节流到字符流的桥梁,父类是Reader。它读取字节,并使用指定的编码将其解码为字符,它使用的字符集可以指定,或者接受平台的默认字符集OutputStreamWriter:是从字符流到字节流的桥梁,父类是Writer。它使用指定的编码将写入的字符编码为字节,它使用的字符集可以指定,或者接受平台的默认字符集JDK11以及以后FileReader可以直接指定

构造方法:

方法名说明InputStreamReader(InputStream in)使用默认字符编码创建InputStreamReader对象InputStreamReader(InputStream in,String chatset)使用指定的字符编码创建InputStreamReader对象OutputStreamWriter(OutputStream out)使用默认字符编码创建OutputStreamWriter对象OutputStreamWriter(OutputStream out,String charset)使用指定的字符编码创建OutputStreamWriter对象 import java.io.*; import java.nio.charset.Charset; public class Demo { public static void main(String[] args) throws IOException { //文件是什么码表,就指定一样的码表去读取 //字节输入流对象作为参数传入转换流对象 FileInputStream fis = new FileInputStream("day12_exercise\\dddcopy.txt"); InputStreamReader isr = new InputStreamReader(fis, "utf-8"); int ch; while ((ch = isr.read()) != -1) { System.out.println((char) ch); } isr.close(); //使用转换流,指定码表向文件写数据 //字节输出流对象作为参数传入装换流 FileOutputStream fos = new FileOutputStream("day12_exercise\\dddcopy.txt"); OutputStreamWriter osw = new OutputStreamWriter(fos, "utf-8"); osw.write("秋水共长天一色"); osw.close(); //JDK11之后字符流推出了一个新的构造方法,可以指定码表 FileReader fileReader = new FileReader( "day12_exercise\\dddcopy.txt", Charset.forName("utf-8")); int c; while ((c = fileReader.read()) != -1) { System.out.println((char) c); } fileReader.close(); } } 6. 对象操作流

对象操作流可以把对象以字节的形式写到本地文件,直接打开文件是读不懂的,需要再次用对象操作流将文件读到内存中。

对象操作输出流(对象序列化流):将对象写到本地文件中,或者在网络中传输对象对象操作输入流 (对象反序列化流):把写到本地文件中的对象读到内存中,或者接受网络中传输的对象

User类:

import java.io.Serializable; //如果想要一个类能够被序列化,必须实现接口Serializable //Serializable是一个标记性接口,没有任何抽象方法 public class User implements Serializable { //自定义序列号 private static final long serialVersionUID = 5586850569152704422L; private String name; private transient String password; public User(String name, String password) { this.name = name; this.password = password; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", password='" + password + '\'' + '}'; } public User() { } }

序列化和反序列化:

import java.io.*; public class Demo01 { public static void main(String[] args) throws IOException, ClassNotFoundException { User user = new User("王勃", "twgx"); //反序列化user对象 ObjectInputStream ois = new ObjectInputStream( new FileInputStream("day12_exercise\\ccc.txt")); User o = (User)ois.readObject(); System.out.println(o); ois.close(); } //序列化user对象 private static void writeObject(User user) throws IOException { ObjectOutputStream oos = new ObjectOutputStream( new FileOutputStream("day12_exercise\\ccc.txt")); oos.writeObject(user); oos.close(); } }

若不希望某个成员变量被序列化,可以在变量前加一个瞬态关键字 transient

案例:创建多个学生类对象写到文件中,再次读取到内存中

public class Demo{ /** * read(): * 读取到文件末尾返回值是 -1 * readLine(): * 读取到文件的末尾返回值 null * readObject(): * 读取到文件的末尾 直接抛出异常 * 如果要序列化的对象有多个,不建议直接将多个对象序列化到文件中,因为反序列化时容易出异常 * 建议: 将要序列化的多个对象存储到集合中,然后将集合序列化到文件中 */ public static void main(String[] args) throws Exception { // 序列化 //1.创建序列化流对象 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("myCode\\oos.txt")); ArrayList arrayList = new ArrayList(); //2.创建多个学生对象 Student s = new Student("佟丽娅",30); Student s01 = new Student("佟丽娅",30); //3.将学生对象添加到集合中 arrayList.add(s); arrayList.add(s01); //4.将集合对象序列化到文件中 oos.writeObject(arrayList); oos.close(); // 反序列化 //5.创建反序列化流对象 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("myCode\\oos.txt")); //6.将文件中的对象数据,读取到内存中 Object obj = ois.readObject(); ArrayList arrayList = (ArrayList)obj; ois.close(); for (Student s : arrayList) { System.out.println(s.getName() + "," + s.getAge()); } } } 7. Properties集合 Properties是一个Map体系的集合类Properties有和IO流相关的方法键及其对应的值通常都用于存储字符串类型

Properties作为Map集合的特有方法:

方法名说明Object setProperty(String key, String value)设置集合的键和值,都是String类型,底层调用 Hashtable方法 putString getProperty(String key)使用此属性列表中指定的键搜索属性Set stringPropertyNames()从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串

Properties 和IO流结合的方法:

方法名说明void load(Reader reader)从字符输入流读取属性列表(键和元素对)void store(Writer writer, String comments)将此属性列表(键和元素对)写入此 Properties表中,以适合使用 load(Reader)方法的格式写入输出字符流

将properties文件中的键值对,存到properties集合

import java.io.FileReader; import java.io.IOException; import java.nio.charset.Charset; import java.util.Properties; public class Demo01 { public static void main(String[] args) throws IOException { Properties prop = new Properties(); FileReader fr = new FileReader( "day12_exercise\\prop.properties", Charset.forName("utf-8")); prop.load(fr); fr.close(); System.out.println(prop); } }

将properties集合中的键值对,存到本地配置文件

import java.io.FileWriter; import java.io.IOException; import java.util.Properties; public class Demo02 { public static void main(String[] args) throws IOException { Properties prop = new Properties(); FileWriter fileWriter = new FileWriter("day12_exercise\\prop.properties"); prop.put("张三","123456"); prop.put("李四","123456"); //"abc为写入文件中的注释" prop.store(fileWriter, "abc"); fileWriter.close(); } }

如有错误欢迎留言评论,及时更正。2021年6月11日,羽露风



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3