• java学习--字符流


    字符流

    为什么会出现字符流

    字符流的介绍

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

    ​ 字符流=字节流+编码表

    中文的字节存储方式

    用字节流复制文本是,文本文件会有中文,汉子在存储时候,无论选择那种编码存储,第一个字节都是负数。

    编码表

    什么是字符集

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

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

    常见的字符集
    • ASCll字符集

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

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

    • GBXXX字符集:

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

    • Unicode字符集

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

    编码规则:

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

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

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

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

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

    代码演示

    public static void main(String[] args) throws UnsupportedEncodingException {
            String s="菲菲";
             byte [] bys=s.getBytes();
             byte [] by=s.getBytes("UTF-8");
             byte [] bytes=s.getBytes("GBK");
            System.out.println(Arrays.toString(bys));
            System.out.println(Arrays.toString(by));
            System.out.println(Arrays.toString(bytes));
    
            String ss=new String(bys);
            String ss1=new String(by,"UTF-8");
            String ss2=new String(bytes,"GBK");
            System.out.println(ss);
            System.out.println(ss1);
            System.out.println(ss2);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    字符流写数据
    • 介绍

      Writer:用于鞋服字符流的抽象父类

      FileWriter:用于写入字符流的常用子类

    • 构造方法

      方法名说明
      FileWriter(File file)根据给定的File对象构造一个FileWriter对象
      FileWriter(File file,boolean append)根据给定的File对象构造一个FileWriter对象
      FileWriter(String fileName)根据给定的文件名构造一个FileWriter对象
      FileWriter(String fileName,boolean append)根据给定的文件名以及指示是否附加写入数据的Boolean值来构造FIleWriter对象
    • 成员方法

      方法名说明
      void write()写一个字符
      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 static void main(String[] args) throws IOException {
              FileWriter fw=new FileWriter("E:\\Java\\IO\\practice\\java.txt");
              //写一个字符
              //fw.write(98);
      
              //写入一个字符串数组
              char [] chars={'I','c','h','L','i','e','b','e','D','i','s','h'};
              fw.write(chars);
      
              //写入一个字符串
              fw.write("Minaracastan Sinua");
      
              fw.close();
          }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
    字符流读数据
    • 介绍

      ​ Reader:用于读取字符流的抽象父类

      ​ FileReader:用于读取字符流的常用子类

    • 构造方法

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

      方法名说明
      int read()一次读取一个字符数据
      int read(char[] cbuf)一次读取一个字符数组数据
    • 代码演示

      public static void main(String[] args) throws IOException {
              FileReader fr=new FileReader("E:\\Java\\IO\\practice\\java.txt");
              //一次读取一个数据
              int ch;
              while((ch=fr.read())!=-1){
                  System.out.println((char)ch);
              }
              //一次读取一个字符数组
              char [] chars=new char[1024];
              int len;
              while((len=fr.read())!=-1){
                  System.out.println(new String(chars,0,len));
              }
      
              fr.close();
          }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      字符流用户注册案例
      • 案例需求

        • 将键盘录入的用户名和密码保存到本地实现永久存储
      • 实现步骤

        • 获取用户输入的用户名和密码
        • 将用户输入的用户名和密码写入到本地的文件中
        • 关流释放资源
      • 代码实现

        public static void main(String[] args) throws IOException {
                Scanner sc=new Scanner(System.in);
                System.out.println("请输入用户名:");
                String username=sc.next();
                System.out.println("请输入密码:");
                String password=sc.next();
        
                FileWriter fw=new FileWriter("E:\\Java\\IO\\practice\\java1.txt");
                //写入信息
                fw.write(username);
                fw.write("\r\n");
                fw.write(password);
                //资源刷新
                fw.flush();
                //关闭流
                fw.close();
        
        
            }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
    字符缓冲流
    • 字符缓冲流介绍
      • ​ BufferedWriter:将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入,可以指定缓冲区的大小,或者可以接受默认大小,默认值足够大,可用于大多数用途
      • BufferedReader:从祖父输入流读取文本,缓冲字符,一提供字符,数组和行的高效读取,可以指定缓冲区的大小,默认值足够大,可用于大多数用途
    • 构造方法
      方法名说明
      BufferedWriter(Writer out)创建字符缓冲输出流对象
      BufferedReader(Reader in)创建字符缓冲输入流对象
    • 代码演示
      public static void main(String[] args) throws IOException {
              BufferedWriter bw=new BufferedWriter(new
                      FileWriter("E:\\Java\\IO\\practice\\java.txt"));
              bw.write("Ik hou van jou\r\n");
              bw.write("Minarastan Sinua");
              bw.close();
      
              //读取文件
      
              BufferedReader br=new BufferedReader(
                      new FileReader("E:\\Java\\IO\\practice\\java.txt"));
      
              //按字符数组读取
              char [] chars=new char[1024];
              int len;
              while((len=br.read())!=-1){
                  System.out.print(new String(chars,0,len));
              }
              br.close();
          }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
    字符缓冲流特有功能
    • 方法介绍

      ​ BufferedWriter:

      方法名说明
      void newLine()写一行行分隔符,行分隔字符串有系统属性定义

      BufferedReader:

      方法名说明
      String readLine()读一行文字,结果包含行的内容的字符串,不包括任何终止字符如果流的结尾已经到达,则为null
    • 代码演示

    public static void main(String[] args) throws IOException {
            //创建字符缓冲流
            BufferedWriter bw=new BufferedWriter(
                    new FileWriter("E:\\Java\\IO\\practice\\java.txt"));
    
            //写数据
            for (int i = 0; i < 10; i++) {
                bw.write("Ich liebe Dish" +i);
                bw.newLine();
                bw.flush();
            }
    
            //释放资源
            bw.close();
    
            //创建字符缓冲输入流
            BufferedReader br=new BufferedReader(
                    new FileReader("E:\\Java\\IO\\practice\\java.txt")
            );
    
            String line;
            while ((line=br.readLine())!=null){
                System.out.println(line);
            }
    
            //释放资源
            br.close();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    字符缓冲刘操作文件中数据排序案例
    • 案例需求

      • 使用字符缓冲流读取文件中的数据,排序后再次写到本地文件
    • 实现步骤

      • 将文件中的数据读取到程序中
      • 对读取到的数据进行处理
      • 将处理后的数据添加到集合中
      • 对集合中的数据进行排序
      • 将排序后的集合中的数据写入到文件中
    • 代码实现

      public static void main(String[] args) throws IOException {
              //读取文件
              BufferedReader br=new BufferedReader(
                      new FileReader("E:\\Java\\IO\\practice\\java.txt")
              );
              String line=br.readLine();
              System.out.println("读取到的数据为:"+line);
              br.close();
      
              //按照空格进行切割
              String [] split=line.split(" ");
      
              //把字符串类型的数据变成int类型
              int [] arr=new int[split.length];
              //遍历split数组,可以进行类型转换
              for (int i = 0; i < split.length; i++) {
                  String smallStr=split[i];
                  int number=Integer.parseInt(smallStr);
                  arr[i]=number;
              }
      
              //排序
              Arrays.sort(arr);
              System.out.println(Arrays.toString(arr));
      
              //排序过后写入本地
              BufferedWriter bw=new BufferedWriter(
                      new FileWriter("E:\\Java\\IO\\practice\\java.txt"));
              for (int i = 0; i < arr.length; i++) {
                  bw.write(arr[i]+" ");
                  bw.flush();
              }
              bw.close();
      
          }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35

    转换流

    字符流中的编码解码问题两个相关的两个类
    • InputStreamReader:是从字节流到字符流的桥梁,父类是Reader,它读取字节,并使用指定的编码将其解码为字符

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

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

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

    转换流写数据

    构造方法

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

    代码演示

    public static void main(String[] args) throws IOException {
            OutputStreamWriter osw=new OutputStreamWriter(
                    new FileOutputStream("E:\\Java\\IO\\practice\\sinua.txt"));
            osw.write("Miluji te");
            osw.close();
    
            InputStreamReader isr=new InputStreamReader(
                    new FileInputStream("E:\\Java\\IO\\practice\\sinua.txt"),"GBK");
            char [] chars=new char[1024];
            int length;
            while((length=isr.read())!=-1){
                System.out.println(new String(chars,0,length));
    
            }
            isr.close();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    对象操作流

    对象序列化流
    • 对象序列化介绍

      • 对象序列化:将对象保存到磁盘中,或者在网络传输对象
      • 这种机智就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型,对象的数据和对象中存储的属性等信息
      • 字节序列写到文件后,相当于文件中持久保存了一个对象的信息
      • 反之, 该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化
    • 对象序列化流:ObjectOutputStream

      • 将java对象的原始数据类型和图形写入OutputStream,可以使用ObjectInputStream读取(重构)对象。可以通过使用流的文件来实现对象的持久储存。如果是网络套接字流,则可以在另一进程中重构对象。
    • 构造方法

      方法名说明
      ObjectOutputStream(OutputStream out)创建一个写入指定的OutPutStream的ObjecdtOutputStream
    • 序列化对象方法

      方法名说明
      void writeObject(object obj)将指定的对象写入ObjectOutputStream
    对象反序列化流
    • 对象反序列化流:ObjectInputStream

      • ObjectInputStream反序列化先前使用ObjectOuputStream编写的原始数据和对象
    • 构造方法

      方法名说明
      ObjectInputStream(InputStream in)创建从指定的InputStream读取的ObjectInputStream
    • 反序列化对象的方法

      方法名说明
      Object readObject()从ObjectInputStream读取一个对象

    示例代码

    OutputStreamWriter osw=new OutputStreamWriter(
                    new FileOutputStream("E:\\Java\\IO\\practice\\sinua.txt"));
            osw.write("Miluji te");
            osw.close();
    
            InputStreamReader isr=new InputStreamReader(
                    new FileInputStream("E:\\Java\\IO\\practice\\sinua.txt"),"GBK");
            char [] chars=new char[1024];
            int length;
            while((length=isr.read())!=-1){
                System.out.println(new String(chars,0,length));
    
            }
            isr.close();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    serivalVersionUID&transient
    • servalVersionUID

      • 用对象序列化流序列化了一个对象后,加入我们修改了对象所属的类的文件,读取数据会不会出现问题呢?

        • 会出问题,会抛出InvalidClassException异常
      • 如果出问题了,如何解决呢

        • 重新序列化

        • 给对象所属的类加一个servalVersionUID

          • private static final long servalVersionUID=42L;
      • transient

        • 如果一个对象中的某个成员变量的值不想被序列化,又该如何实现?

          • 给该成员变量加transient官架子修饰,该关键字标记的成员变量不参与序列化过程

      示例代码

      学生类

      public class Student implements Serializable {
          private static final long servalVersionUID=42L;
          private String name;
          //private int age;
          //不想年龄被序列化
          private transient int age;
      
          public Student() {
          }
      
          public Student(String name, int age) {
              this.name = name;
              this.age = age;
          }
      
          public String getName() {
              return name;
          }
      
          @Override
          public String toString() {
              return "Student{" +
                      "name='" + name + '\'' +
                      ", age=" + age +
                      '}';
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public int getAge() {
              return age;
          }
      
          public void setAge(int age) {
              this.age = age;
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      public class Test {
          public Test() throws IOException {
          }
      
          public static void main(String[] args) throws IOException, ClassNotFoundException {
              write();
              read();
      
          }
      
          private static void write() throws IOException {
              ObjectOutputStream oos = new ObjectOutputStream(new
                      FileOutputStream("E:\\Java\\IO\\practice\\java1.txt"));
              Student s = new Student("佟丽娅", 30);
              oos.writeObject(s);
              oos.close();
          }
      
          private static void read() throws IOException, ClassNotFoundException {
              //反序列化
              ObjectInputStream ois=new ObjectInputStream(
                      new FileInputStream("E:\\Java\\IO\\practice\\java1.txt")
              );
              Object obj=ois.readObject();
              Student student=(Student) obj;
              System.out.println(student.getName());
              ois.close();
          }
      
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30

      Properties集合

      Properties作为Map集合的使用
      • Properties介绍

        • 是一个Map体系的集合类
        • Properties可以保存到流中或从流中加载
        • 属性列表中的每个键以及对应的值都是一个字符串
      • Properties的基本使用

         public static void main(String[] args) {
                Properties prop =new Properties();
                prop.put("法语","Je t'aime");
                prop.put("德语","Ich Liebe Dish");
                prop.put("芬兰","Minaracastan Sinua");
                prop.put("荷兰","Ik hou van jou");
                prop.put("捷克","Miluji te");
        
                Set<Map.Entry<Object, Object>> entries = prop.entrySet();
                for (Map.Entry<Object, Object> key : entries) {
                     String value=(String)prop.get(key);
                    System.out.println(key);
                }
        
        
            }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        Properties作为Map集合的特有方法
        • 特有方法

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

          示例代码

          public static void main(String[] args) {
                  Properties prop =new Properties();
                  prop.put("法语","Je t'aime");
                  prop.put("德语","Ich Liebe Dish");
                  prop.put("芬兰","Minaracastan Sinua");
                  prop.put("荷兰","Ik hou van jou");
                  prop.put("捷克","Miluji te");
          
                  System.out.println(prop.getProperty("芬兰"));
                  System.out.println(prop.getProperty("捷克"));
          
                  System.out.println(prop);
                  Set<String> names = prop.stringPropertyNames();
                  for (String name : names) {
          
                      String value=prop.getProperty(name);
                      System.out.println(name+","+value);
                  }
          
          
          
              }
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          Properties和IO流相结合的方法

          和IO结合的方法

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

          示例代码

          public class Exam3 {
              public static void main(String[] args) throws IOException {
          
                  myLoad();
                  //myStore();
          
              }
          
              private static void myStore() throws IOException {
                  Properties prop=new Properties();
                  prop.put("法语","Je t'aime");
                  prop.put("德语","Ich Liebe Dish");
                  prop.put("芬兰","Minaracastan Sinua");
                  prop.put("荷兰","Ik hou van jou");
                  prop.put("捷克","Miluji te");
          
                  FileWriter fw=new FileWriter("E:\\Java\\IO\\practice\\java.txt");
                  prop.store(fw,null);
                  fw.close();
              }
          
              private static void myLoad() throws IOException {
                  Properties prop =new Properties();
                  FileReader fr=new FileReader("E:\\Java\\IO\\practice\\java.txt");
                  prop.load(fr);
                  fr.close();
                  System.out.println(prop);
              }
          
          }
          
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
  • 相关阅读:
    xilinx axi_iic IP使用分享
    B3624 猫粮规划(深度优先)
    第三章 类和对象
    竞赛选题 基于深度学习的动物识别 - 卷积神经网络 机器视觉 图像识别
    java计算机毕业设计无人智慧药柜系统设计源码+lw文档+系统+数据库
    Linux应用
    13数据结构与算法刷题之【动态规划】篇
    Socks5代理IP在网络安全、跨境电商和游戏中的应用
    OKR在项目管理中的应用:精准化目标管理
    ArrayList源码解析
  • 原文地址:https://blog.csdn.net/wode39/article/details/128145774