Java学习的第二十四天(JavaSE最终篇_IO流之标准输入输出流_打印流_Properties集合和乱码解决方案)

一、标准字节输入输出流

1.概念引入--结合System类中的in和out进行理解

标准输入输出流
in:  System.in----标准输入流  InputStream--字节流
out: System.out---标准输出流  PrintStream(继承了OutputStream)--字节流

2.标准输出流的代码演示

package com.bianyiit.cast;

import java.io.*;
import java.util.Scanner;

public class BiaoZhunInAndOutIO {
    public static void main(String[] args) throws IOException {
        /*标准输入流
        *   in:  System.in----标准输入流  InputStream--字节流
        *   out: System.out---标准输出流  PrintStream(继承了OutputStream)--字节流
        * */
         System.out.println("haha");  //字符输出流
	     PrintStream ps = System.out;  //返回的是一个输出流的对象
	     /*ps.println("exit");  //调用println(),往控制台写数据(并非之前的文本文件了)
	     ps.print(1);   //print:不换行*/
	     /*System.out.print();  //没有print()这个方法,必须带参数
	     System.out.println();   //有println()这个方法,可以不带参数,用来换行*/
	     ps.write("hello".getBytes());  //也是往控制台写数据  字节输出流
	     //标准的输出流调用println()和print()底层使用的是字符流,而write()底层使用的是字节流
    }
}

总结:

//输出方式一
PrintStream ps = System.out; 
ps.println("hello");

//输出方式二
System.out.println("hello");

1.1 上述两种输出方式产生的效果是一样的
1.2 System.out返回的是一个输出流的对象,也就是PrintStream
1.3 通过PrintStream对象调用println()直接往控制台写数据了,并且之前字节/字符流写入时的文本文件了,且这个方法可以不带参数
1.4 通过PrintStream对象调用print()不进行换行,且这个方法必须带参数
1.5 通过PrintStream对象调用write()往控制台写入数据,参数的是byte(字节),所以这个是字节输出流
1.6 标准的字节输出流调用println()和print()底层使用的是字符流,而write()底层使用的是字节流

3.标准输入流的代码演示

package com.bianyiit.cast;

import java.io.*;
import java.util.Scanner;

public class BiaoZhunInAndOutIO {
    public static void main(String[] args) throws IOException {
        /*标准输入流
        *   in:  System.in----标准输入流  InputStream--字节流
        *   out: System.out---标准输出流  PrintStream(继承了OutputStream)--字节流
        * */
        Scanner sc=new Scanner(System.in);
        //真正从控制台读数据的原因是System.in---标准输入流
        InputStream is = System.in;  //从控制台读数据
        //通过标准输入流对象实现键盘录入的效果
        //把字节流转换成字符流
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(isr);
        System.out.print("请输入内容:");
        String s = br.readLine();
        int a=Integer.parseInt(s);
        br.close();
        System.out.println("输入的内容是:"+a);
    }
}

总结:

//方式一:使用Scanner和System.in来实现键盘录入效果
Scanner sc=new Scanner(System.in);
int a=sc.nextInt();
System.out.println(a);

//方式二:直接使用字节输入流来实现键盘录入效果
InputStream is = System.in;  
InputStreamReader isr = new InputStreamReader(is);  //字节转字符(转换流)
BufferedReader br = new BufferedReader(isr);  //字符高效流(缓冲流)
System.out.print("请输入内容:");  //提示信息
String s = br.readLine();   //读一行String类型的数据
int a=Integer.parseInt(s);  //使用Integer.parseInt(s)将String类型的数据转换成Int类型的数据
br.close();  //字符输入流最好要刷新才能正常读出来
System.out.println("输入的内容是:"+a);

二、字符打印流

package com.bianyiit.cast;

import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class PrintWriterDemo {
    public static void main(String[] args) throws IOException {
        PrintWriter pw = new PrintWriter("D:\\重要代码Demo\\文件IO对象\\打印流\\a.txt");
        pw.println("haha");    //println()使用的是字符流  可以自动换行
        //pw.close();
        //打印流也需要刷新的效果
        pw.write("java");   //write()使用的是字符流
        pw.close();
        //print()和write()使用的是都是字符流
        //不能输出字节,但是可以输出其它任意类型
        //pw.write("c".getBytes());  //这里如果输出字节会报错
        //只能输出不能输入,只能写不能读
    }
}

总结:

2.1 PrintWriter的对象调用println()使用的是字符流,可以实现自动换行的效果
2.2 字符打印流同样也需要刷新的效果
2.3 PrintWriter的对象调用write()使用的也是字符流
2.4 标准的字符输出流调用println()、print()和write()底层使用的都是是字符流
2.5 PrintWriter的对象调用write("c")不能输出字节,但是可以输出其它任意类型
2.6 pw.write("c".getBytes());  //这里如果调用getBytes()输出字节会报错
2.7 标准的字符输出流的输出不能输入,只能写不能读

三、Properties(键值对+流实现存储)—常用于配置文件

3.1 Properties分析

Properties:map的子类(经常用到)---配置文件
	1. 存储数据也是以键值对的方式
	2. 结合流对象对数据往文件中进行存储,也可以从文件中以键值对的方式把数据读出来
	3. Properties的父类是Hashtabel,它的父类是map图  properties表示一个持久的属性集,可保存在流中或者从流中加载
	4. properties的对象可以使用map集合的所有的方法
	5. 如果properties的对象要结合流使用的话,key和value是没有泛型的,只能是String类型
package com.bianyiit.cast;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public class PropertiesDemo1 {
    public static void main(String[] args) throws IOException {
        /*Properties:map的子类(经常用到)---配置文件
             存储数据也是以键值对的方式
             结合流对象对数据往文件中进行存储,也可以从文件中以键值对的方式把数据读出来*/
        //Properties的父类是Hashtabel,它的父类是map图  properties表示一个持久的属性集,可保存在流中或者从流中加载
        //method1();
        //加载a.txt里面的配置信息(从a.txt中读入内存)
        Properties pro=new Properties();
        //加载内容---结合输入流
        FileReader fr = new FileReader("D:\\重要代码Demo\\文件IO对象\\properties\\a.txt");
        //将文件中的内容加载到集合中
        pro.load(fr);
        //遍历集合的第一种方式(获取所有的key)
        /*Set<Object> keys = pro.keySet();
        for (Object key : keys) {
            Object value = pro.get(key);
            System.out.println(key+":"+value);
        }*/
        //遍历集合的第二种方式(获取单个的键值对)
        Set<Map.Entry<Object, Object>> entries = pro.entrySet();
        for (Map.Entry<Object, Object> entry : entries) {
            Object key = entry.getKey();
            Object value = entry.getValue();
            System.out.println(key+":"+value);
        }
    }

    private static void method1() throws IOException {
        //创建一个无默认值的空属性列表
        Properties pro = new Properties();
        //往pro集合中添加一个数据
        //1.properties的对象可以使用map集合的所有的方法
        //2.如果properties的对象要结合流使用的话,key和value是没有泛型的,只能是String类型
        pro.put("001","张三");
        pro.put("002","李四");
        pro.put("003","王五");
        pro.put("004","赵六");
        pro.put("005","孙七");
        //写入文件中去
        FileWriter fw = new FileWriter("D:\\重要代码Demo\\文件IO对象\\properties\\a.txt");
        pro.store(fw,"The Message's Introduction is:");  //comments:注释/介绍
        //出异常了 java.lang.ClassCastException 注意:当pro的内容需要写入到文件中是,那么pro的key值也只能是字符串类型
        System.out.println(pro);
    }
}

3.2 注意:当pro的内容需要写入到文件中是,那么pro的key值也只能是字符串类型

package com.bianyiit.cast;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

public class PropertiesDemo2 {
    public static void main(String[] args) throws IOException {
        Properties pro = new Properties();
        //使用自己的方法往pro中添加元素
        //它本身的key和value只能是String类型
        pro.setProperty("1","张三");
        pro.setProperty("2","李四");
        pro.setProperty("3","王五");
        pro.setProperty("4","赵六");
        pro.setProperty("5","孙七");
        //结合流写入文件中
        FileOutputStream os = new FileOutputStream("D:\\重要代码Demo\\文件IO对象\\properties\\b.txt");
        pro.store(os,"信息介绍:");
        String s1 = pro.getProperty("6");  //通过getProperty(key)---通过key得到value
        System.out.println(s1);
    }
}
//本代码的输出结果:null
/*存储的txt文本文件中的内容如下:
   #\u4FE1\u606F\u4ECB\u7ECD\uFF1A(这个store()中的第二个参数Comments(注释)代表的是中文的十六进制编码)
   #Sat Nov 23 15:49:14 CST 2019
   5=\u5B59\u4E03
   4=\u8D75\u516D
   3=\u738B\u4E94
   2=\u674E\u56DB
   1=\u5F20\u4E09*/

四、乱码问题的解决办法

package com.bianyiit.cast;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class LuanMaDemo {
    public static void main(String[] args) throws IOException {
        //读数据
        InputStream is = new FileInputStream("D:\\重要代码Demo\\文件IO对象\\properties\\c.txt");
        byte[] arr = new byte[1024];
        int length;
        while((length=is.read(arr))!=-1){
            String s = new String(arr, 0, length);
            System.out.println(s);
        }
        //输出结果:����һ�����±��ļ�������
    }
}

原因分析

//输出结果:����һ�����±��ļ�������
//为什么会产生中文乱码的问题??
//txt自带的编码表是GBK 而程序中的设置的是UTF-8,两者不匹配导致的乱码
//UTF-8的特点:一个字符可能对应三个字节
//GBK:一个字符可能对应两个字节
//乱码的原因:存储数据的编码表和读取数据对应的编码表不一致导致的
//字符转字节:编码 GBK
//字节转字符:解码 UTF-8
//编码和解码使用的编码表不一致,所以产生了乱码问题

方法一:更改txt或者IDEA的编码表

1.更改txt的编码格式,打开txt文本文件,点击另存为弹出以下界面

2.默认为GBK(中国的编码表),将其设置为UTF-8(万国编码表)

3.打开IDEA的File,点击Settings,找到File Encodings,将所有GBK全部改为UTF-8,然后点击运行,就不会出现乱码现象了

方法二:编码和解码的代码规定为同一个编码表

package com.bianyiit.cast;

import java.io.*;

public class LuanMaDemo2 {
    public static void main(String[] args) throws IOException {
        //method1();
        method2();
        //记住:编码和解码的编码表一定要一致(IDEA中的程序要设置成UTF-8)
    }

    private static void method2() throws UnsupportedEncodingException {
        //如果没有使用编码表,写入数据的乱码行为
        String s="程序猿";
        //编码
        byte[] bytes = s.getBytes("GBK");
        String s1 = new String(bytes,"GBK");
        System.out.println(s1);
        /*BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\重要代码Demo\\文件IO对象\\properties\\c.txt"));
        bw.write(s);
        bw.close();*/
    }

    private static void method1() throws IOException {
        //读数据的处理乱码的行为,设置读的方式为UTF-8,最终的目的是让编码和解码使用的编码表一致,这样才不会导致乱码的情况
        InputStream is = new FileInputStream("D:\\重要代码Demo\\文件IO对象\\properties\\c.txt");
        InputStreamReader isr = new InputStreamReader(is,"UTF-8");
        BufferedReader br = new BufferedReader(isr);
        String s = br.readLine();
        System.out.println(s);
    }
}
//输出结果:没有出现乱码
	程序猿

乱码的原因:存储数据的编码表和读取数据对应的编码表不一致导致的
解决的方案:1.保持txt和IDEA的编码格式一致 2.存和取统一使用一个编码表

发布了73 篇原创文章 · 获赞 11 · 访问量 2468

猜你喜欢

转载自blog.csdn.net/weixin_43908333/article/details/103217189