JAVA中字符流详解
字符流:就是在字节流的基础上,加上编码,形成的数据流
字符流出现的意义:因为字节流在操作字符时,可能会有中文导致的乱码,所以由字节流引申出了字符流。
字符输入流:Reader
常用子类:FileReader
文件字符输入流常用方法:
read();
read(char[ ]);
read(char[ ] ,offset,len);
字符输出流: Writer
常用子类:文件字符输出流: Filewriter
文件字符输出常用方法:
writer();
writer(char[ ]);
writer(char[ ],offset,len);
writer(string);
flush()刷新缓冲区
注意:close()方法默认调用了flush()方法,但是flush()方法只刷新缓冲区,而close()还会关闭IO流
字符输入流代码示例:
1 import java.io.File; 2 import java.io.FileReader; 3 import java.io.IOException; 4 5 public class Demo5 { 6 7 public static void main(String[] args) throws IOException{ 8 FileReader fr=new FileReader(new File("1.txt")); 9 char[] ca=new char[1024]; 10 int count=0; 11 while((count=fr.read(ca))!=-1) { 12 System.out.println(new String(ca,0,count)); 13 } 14 } 15 }
运行结果:
字符输出流代码示例:
1 import java.io.File; 2 import java.io.FileReader; 3 import java.io.FileWriter; 4 import java.io.IOException; 5 6 public class Demo6 { 7 8 public static void main(String[] args) throws IOException{ 9 FileReader fr=new FileReader(new File("1.txt")); 10 FileWriter fw=new FileWriter(new File("2.txt")); 11 char[] ca=new char[1024]; 12 int count; 13 while((count=fr.read(ca))!=-1) { 14 fw.write(ca,0,count); 15 } 16 fr.close(); 17 fw.close(); 18 } 19 }
执行结果:
字符流与字节流的区别:字符流虽然以字节流为基础创建的,但是字节流可以支持声音,视频,图片,文本等所有文件类型,而字符流只支持文本文件。
带缓冲区的字符流:
BufferedReader/BufferedWriter 带缓冲区的字符输入流与字符输出流。
带缓冲区的字符输入流:BufferedReader:常用方法:readLine() 读取一行,如果为文件末尾,返回值为null。
带缓冲区的字符输出流:BufferedWriter:常用方法:writer(string)将字符串写入 到输出流。 newLine()根据系统的行分割符进行换行。
BufferReader代码示例:
1 import java.io.BufferedReader; 2 import java.io.File; 3 import java.io.FileReader; 4 import java.io.IOException; 5 6 public class Demo7 { 7 8 public static void main(String[] args) throws IOException{ 9 BufferedReader br=new BufferedReader(new FileReader(new File("1.txt"))); 10 String value; 11 while((value=br.readLine())!=null) { 12 System.out.println(value); 13 } 14 br.close(); 15 } 16 }
BufferedWriter代码示例:
1 import java.io.BufferedReader; 2 import java.io.BufferedWriter; 3 import java.io.FileReader; 4 import java.io.FileWriter; 5 import java.io.IOException; 6 7 public class Demo8 { 8 9 public static void main(String[] args)throws IOException { 10 BufferedWriter bw=new BufferedWriter(new FileWriter("3.txt")); 11 BufferedReader br=new BufferedReader(new FileReader("1.txt")); 12 String value=""; 13 while((value=br.readLine())!=null) { 14 bw.write(value); 15 bw.newLine(); 16 } 17 bw.close(); 18 br.close(); 19 } 20 }
编码与乱码:
乱码:编码与解码不一致,导致的乱码问题,每一种编码格式都有自己独特的编码,如果编码与解码不一致,势必会导致乱码,例如用Unicode编码,用gbk解码,就会字符与码值不匹配,从而导致乱码。
编码表:编码和解码使用的规则:
ASCII码:美国信息交换标准代码。单字节编码,不支持中文。
gbk:国标码;
Unicode/utf-8 :双字节编码,支持中文(万国码)
代码示例:
1 public class 读取不同编码的文本文件 { 2 public static void main(String[] args) throws IOException { 3 // BufferedReader br=new BufferedReader(new FileReader(new File("C:\\Users\\Administrator\\De 4 sktop\\6.txt"))); 5 // 改进 6 BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream(new File("C:\ 7 \Users\\Administrator\\Desktop\\6.txt")),"gbk")); 8 String st = br.readLine(); 9 System.out.println(st); 10 } 11 }
转换流
1.InputStreamReader 将字节流转换成字符流 输入
2.OutputStreamWriter 将字节流转换成字符流 输出
3. 构造方法:
① InputStreamReader(InputStream in)
② InputStreamReader(InputStream in, String cs)
③ OutputStreamWriter(OutputStream out)
④ OutputStreamWriter(OutputStream out, String charsetName)
4. 作用:
① 可以将字节流转换成字符流
② 可以使用指定的编码来读取或写入流。
代码示例:
1 public class 转换流 { 2 public static void main(String[] args) throws IOException { 3 InputStreamReader is=new InputStreamReader(new FileInputStream(new File("C:\\Users\\Administ 4 rator\\Desktop\\6.txt")),"gbk"); 5 char[] c=new char[1024]; 6 int value = is.read(c); 7 System.out.println(Arrays.toString(c)); 8 } 9 }
字节数组字节输出流
ByteArrayOutputStream
字节数组字节输出流:
特点: 可以将数据写入到 byte 数组中,并且该缓冲区可以随着写入的数据而自增
① 构造方法 :
ByteArrayOutputStream()
② 注意:此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException
③ 常用方法:
1 》 write(byte[]) 将 byte[] 中的值写入缓冲区字节数组,该缓冲区随着数据的增多而自增。
2 》 toString() 要想获取缓冲区的字节数据,可以通过该方法将其转换为字符串。
代码示例:
1 public class 字节数组字节输出流 { 2 public static void main(String[] args) throws IOException { 3 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 4 String s="abc"; 5 byte[] b=s.getBytes(); 6 System.out.println(Arrays.toString(b)); 7 bos.write(b); 8 bos.write(b); 9 bos.close(); 10 System.out.println(Arrays.toString(b)); 11 System.out.println(bos.toString()); 12 } 13 }
对象流 / 序列化与反序列化流
1. 对象流 / 序列化流
ObjectInputStream: 反序列化流
② ObjectOutputStream: 序列化流
1 》常用方法:
writeObject(obj) 将 obj 对象写入到流中
readObject 读取流中的数据
① EOFException 表示读取流意外读到了文件的末尾 ( 就是一个空文件。 )
2 》构造方法
ObjectOutputStream(OutputStream out)
ObjectInputStream(InputStream in)
3 》序列化版本号:
serialVersionUID 序列化版本号:保证序列化流与反序列化流读写一致,保证版本一致性。
代码示例一:
1 public class 用序列化流与反序列化流操作集合 { 2 public static void main(String[] args) { 3 ArrayList<Teacher> list=new ArrayList<>(); 4 list.add(new Teacher(" 张三 ", 18, new ClassRoom("0318java"))); 5 list.add(new Teacher(" 李四 ", 18, new ClassRoom("0318java"))); 6 list.add(new Teacher(" 王五 ", 18, new ClassRoom("0318java"))); 7 // writeToFile(list,"stu.txt"); 8 // 读取 9 System.out.println(readTeacher("stu.txt")); 10 } 11 // 带异常处理的 ,序列化 12 public static void writeToFile(ArrayList<Teacher> list,String fileName) { 13 // 序列化流进行写入 14 try( 15 ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(new File(fileName))); 16 ){ 17 oos.writeObject(list); 18 }catch (Exception e) { 19 e.printStackTrace(); 20 } 21 } 22 // 反序列化 23 public static ArrayList<Teacher> readTeacher(String fileName) { 24 ArrayList<Teacher> list=null; 25 // 反序列化流读取文件中的集合 26 try( 27 ObjectInputStream ois=new ObjectInputStream(new FileInputStream(new File(fileName))); 28 ){ 29 list = (ArrayList<Teacher>) ois.readObject(); 30 }catch (Exception e) { 31 e.printStackTrace(); 32 } 33 return list; 34 } 35 } 36 class Teacher implements Serializable{ 37 /** 38 * 序列化版本号:默认版本号为 1l 39 */ 40 private static final long serialVersionUID = 1L; 41 private String name; 42 private int age; 43 private ClassRoom cn;// 班级 44 public String getName() { 45 return name; 46 } 47 public void setName(String name) { 48 this.name = name; 49 } 50 public int getAge() { 51 return age; 52 } 53 public void setAge(int age) { 54 this.age = age; 55 } 56 public ClassRoom getCn() { 57 return cn; 58 } 59 public void setCn(ClassRoom cn) { 60 this.cn = cn; 61 } 62 @Override 63 public String toString() { 64 return "Teacher [name=" + name + ", age=" + age + ", cn=" + cn + "]"; 65 } 66 public Teacher() { 67 super(); 68 // TODO Auto-generated constructor stub 69 } 70 public Teacher(String name, int age) { 71 super(); 72 this.name = name; 73 this.age = age; 74 } 75 } 76 public Teacher(String name, int age, ClassRoom cn) { 77 super(); 78 this.name = name; 79 this.age = age; 80 this.cn = cn; 81 } 82 } 83 class ClassRoom implements Serializable{ 84 /** 85 * 序列化版本号:保证序列化流与反序列化流读写一致 86 */ 87 private static final long serialVersionUID = 3359646767342429683L; 88 private String no; 89 public ClassRoom() { 90 super(); 91 // TODO Auto-generated constructor stub 92 } 93 public ClassRoom(String no) { 94 super(); 95 this.no = no; 96 } 97 @Override 98 public String toString() { 99 return "ClassRoom [no=" + no + "]"; 100 } 101 public String getNo() { 102 return no; 103 } 104 public void setNo(String no) { 105 this.no = no; 106 }// 班级号码 107 }
代码示例二:
1 import java.io.File; 2 import java.io.FileInputStream; 3 import java.io.FileOutputStream; 4 import java.io.IOException; 5 import java.io.ObjectInputStream; 6 import java.io.ObjectOutputStream; 7 import java.io.Serializable; 8 import java.util.ArrayList; 9 import java.util.Iterator; 10 11 public class Demo9 { 12 13 public static void main(String[] args)throws IOException, Exception { 14 ArrayList<Student6> list=new ArrayList<>(); 15 list.add(new Student6("张三","1001",18)); 16 list.add(new Student6("李四","1002",19)); 17 list.add(new Student6("王五","1003",20)); 18 ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(new File("4.txt"))); 19 oos.writeObject(list); 20 oos.close(); 21 22 ObjectInputStream ois=new ObjectInputStream(new FileInputStream(new File("4.txt") )); 23 ArrayList<Student6> list2=(ArrayList<Student6>) ois.readObject(); 24 Iterator<Student6> it=list2.iterator(); 25 while(it.hasNext()) { 26 Student6 stu=it.next(); 27 System.out.println("姓名:"+stu.getName()+"\t学号:"+stu.getStuNo()+"\t年龄+\t:"+stu.getAge()); 28 } 29 } 30 } 31 class Student6 implements Serializable{ 32 /** 33 * 34 */ 35 private static final long serialVersionUID = 2658878058482366562L; 36 private String name; 37 private String stuNo; 38 private int age; 39 40 public Student6() { 41 super(); 42 } 43 public Student6(String name,String stuNo,int age) { 44 this.name=name; 45 this.stuNo=stuNo; 46 this.age=age; 47 48 } 49 public void setName(String name) { 50 this.name=name; 51 } 52 public String getName() { 53 return name; 54 } 55 public void setStuNo(String stuNo) { 56 this.stuNo=stuNo; 57 } 58 public String getStuNo() { 59 return stuNo; 60 } 61 public void setAge(int age) { 62 this.age=age; 63 } 64 public int getAge() { 65 return age; 66 } 67 @Override 68 public String toString() { 69 return "Student6 [name=" + name + ", stuNo=" + stuNo + ", age=" + age + "]"; 70 } 71 }
EOFException表示输入过程中意外地到达文件尾或流尾的信号
字符流写入 要刷新/关流才能写入(刷新也是调用了flush(刷新)方法)
就像水龙头带软管,开水龙头要等一会儿水才能流出来,就和需要刷新一样
字节流不需要刷新,是因为字节流是一个字节一个字节读和写的,而字符流是三个字节或者两个字节读和写的,所以
字符流需要刷新,而字节流不需要刷新