Java SE入门(十八)——字符流和字节流
iwehdio的博客园:https://www.cnblogs.com/iwehdio/
1、标准输入输出流
-
类字段:静态修饰的成员变量。
-
标准输入流:
public static final InputStream in
:字节输入流。- 用来读取键盘录入的数据:
Scanner sc = new Scanner(System.in);
。
- 用来读取键盘录入的数据:
-
标准输出流:
public static final OuputStream out
:字节输出流。- 将数据输出到命令行:
System.out.println();
。
- 将数据输出到命令行:
-
OutputStreamWriter
:转换流,把字符输出流转换为字节输出流。- 构造方法:
OutputStreamWriter(OutputStream out)
。转换后的字节输出流在 out 中。 - 字符数据 > 字符流 > OutputStreamWriter > 字节流 > 文件。
- 虽然是以字符的输出流形式,操作字节流输出流,但是实际上还是以字节的形式输出。
- 构造方法:
-
读取文本文件并输出到命令行:
BufferedReader br = new BufferedReader(new FileReader("A.java")); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); String line; while((line =br.line())!=null){ bw.writer(line); bw.newLine(); } br.close(); bw.close();
-
IntputStreamReader
:转换流,把字节输入流转换为字符输入流。- 构造方法:
InputStreamReader(InputStream in)
。 - 字符数据 < 字符流 < OutputStreamWriter < 字节流 < 文件。
- 字符的输入流虽然是以字符的形式操作,但是还是使用了字节流。
- 在传输或者从文件读取数据的时候,文件里真正保存的数据永远是字节,终端点实际上是以字节的形式进行的。
- 构造方法:
-
读取键盘输入并输出到文本文件:
InputStream is = System.in; Reader r = new InputStreamReader(is); FileWriter fw = new FileWriter("A.txt"); char[] chs = new char[1024]; int len; while((len = r.read(chs)) != -1){ fw.write(chs, 0, len); fw.flush(); } fw.close(); is.close();
2、打印流
-
只能输出,不能输入。
-
字符打印流:
PrintWriter
。字节打印流:PrintStream
。 -
字符打印流:
-
可以自动换行,
println()
。 -
不能输出字节,但可以输出其他任意类型。
-
通过某些配置,可以自动刷新(仅调用 println 、printf 、format时)。
-
是包装流,不具有写出功能。
-
可以把字节输出流转换成字符输出流。
-
例:
PrintWriter pw = new PrintWriter("a.txt"); pw.writer("ABC"); pw.println("DEF"); //换行 pw.close();
-
配置自动刷新:
- 构造方法:
PrintWriter(Writer out, boolean autoFlush)
和PrintWriter(OutputStream out, boolean autoFlush)
,并设定自动刷新为 true 。 - 例:
PrintWriter pw = new PrintWriter(new FileWriter("a.txt"), true);
。
- 构造方法:
-
打印流复制文本文件:
BufferedRead br = new BufferedReader(new FileReader("source.java")); PrintWriter pw = new PrintWriter(new FileWriter("copy.java"), true); String line; while((line = br.readLine()) != null){ pw.println(line); } pw.close(); br.close();
3、对象操作流
用于读写任意类型的对象
-
ObjecctOutputStream
:对象字节输出流。writeObject
:写入方法。ObjecctOutputStream(OutputStream out)
:构造方法,输入为字节输出流。
-
ObjecctInputStream
:对象字节输入流。readObject
:读取方法。ObjecctInputStream(InputStream in)
:构造方法,输入为字节输入流。
-
使用对象输出流写出对象,只能使用对象输入流读取对象。
-
只能支持实现 java.io.Serializable 接口的对象,这个接口被称为序列化接口,是一个标识接口,只起标识作用,没有方法。。
-
对象输出流写入,例:
// 实现序列化接口 class Student implements Serializable{ String name; int age; public Student(String name, int age){ this.name = name; this.age = age; } @Override public String toString(){ return name + age; } } // 写入对象 ObjecOutputStream oos = new ObjecOutputStream(new FileOutputStream("a.txt")); Student s1 = new Student("name1", 0); Student s2 = new Student("name2", 1); oos.writeObject(s1); oos.writeObject(s2); oos.close(); // 读取对象 ObjecInputStream ois = new ObjectInputStream(new FileInputStream("a.txt")); try { while(true){ Object obj = ois.readObject(); System.out.println(obj); } } catch(EOFException e){ // 读取文件末尾异常 System.out.println("到达文件末尾"); }
-
解决对象输入流读取对象出现异常的问题:用集合存储多个对象,这样写入的只有一个集合对象。
ObjecOutputStream oos = new ObjecOutputStream(new FileOutputStream("a.txt")); ArrayList<Student> list = new ArrayList<Student>(); list.add(new Student("name1", 0)); list.add(new Student("name2", 1)); oos.writeObject(list); oos.close(); ObjecInputStream ois = new ObjectInputStream(new FileInputStream("a.txt")); Object obj = ois.readObject(); ArrayList getlist = (ArrayList<Student>) obj; for(Student s : getlist){ System.out.println(s); }
-
实现 Serializable 序列化接口时,会根据类中的成员赋予一个序列化编号。如果不想改变类中的成员时导致更改前后无法读取,需要固定序列编号。例:
private static final long serialVersionUID = 编号L;
。
4、Properties集合
-
这个类表示了一个持久的属性集,,实现了 map 接口。属性列表中的键值对都是字符串。
-
例:
// 创建属性列表对象,并添加映射关系 Properties prop = new Properties(); prop.put("A", 1); prop.put("B", 2); // 获取keys,遍历属性列表 Set<Object> keys = prop.keySet(); for(Object obj : keys){ Object value = prop.get(key); System.out.println(key + value); }
-
Properties 集合与 IO 流结合:
void list(PrintWriter out)
:将属性列表写入到文件。void load(Read reader)
:将文件中的数据写入属性列表。void store(Writer writer, String comments)
:将属性列表写入到文件,comments为描述文本,没有时置为 null 。
5、编码表
计算机底层二进制编码转换成对应的字符
-
ASCII :最基础的编码表。
-
GBK:中国标准编码表。
-
Unicode:通用编码表,所有字符都占两个字节。
-
UTF-8:长度可变的码表。
-
ANSI:本地编码表。
-
Java中字符串默认使用ANSI(对于简体中文是 gbk)。
-
指定编码写入:
String s = "abc简体中文"; byte[] bys1 = s.getBytes(); // 默认编码 byte[] bys2 = s.getBytes("UTF-8"); // 设置编码 FileOutputStream fos = new FileOutputStream("a.txt"); fos.write(bys); fos.close();
-
指定编码读取:
FileInputStream fis = new FileInputStream("a.txt"); byte[] bys = new byte[1024]; int len = fis.read(bys); System.out.println(new String(bys, 0, len, "UTF-8"));
-
-
对于乱码,编码保持前后一致即可。
-
字符流中的编码:
-
按编码把字符串转成字节数组,再把字节数组转回字符串。
FileWriter fw = new FileWriter("a.txt"); String s = "编码"; byte[] bys = s.getBytes("UTF-8"); fw.write(new String(bys)); fw.close();
-
使用转换流,设置输入的字节流编码。
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("a.txt"), "UTF-8"); String s = "编码"; osw.write(s); osw.close();
-
字符流可以理解为字节流加编码。
-
iwehdio的博客园:https://www.cnblogs.com/iwehdio/