一、标准字节输入输出流
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.存和取统一使用一个编码表