22.01_IO流(序列流)(了解)
序列流可以把多个字节输入流整合成一个, 从序列流中读取数据时, 将从被整合的第一个流开始读, 读完一个之后继续读第二个, 以此类推.
- 整合两个:
SequenceInputStream
(InputStream
,InputStream
)
FileInputStream fis1 = new FileInputStream("a.txt");
FileInputStream fis2 = new FileInputStream("b.txt");
SequenceInputStream sis = new SequenceInputStream(fis1, fis2); //整合2个输入流
FileOutputStream fos = new FileOutputStream("c.txt"); //输出流
int a ;
while((a = sis.read()) != -1) {
fos.write(a);
}
sis.close(); //sis关闭的时候,会将内部的输入流都关闭掉
fos.close();
22.02_IO流(序列流整合多个)(了解)
- 整合多个: SequenceInputStream(Enumeration)
Vector<FileInputStream> v = new Vector<>();
v.add(new FileInputStream("a.txt"));
v.add(new FileInputStream("b.txt"));
v.add(new FileInputStream("c.txt"));
// 利用枚举,将多个输入流整合成一个
SequenceInputStream sis = new SequenceInputStream(v.elements());
FileOutputStream fos = new FileOutputStream("d.txt");
int data ;
while( (data = sis.read()) != -1) {
fos.write(data);
}
sis.close();
fos.close();
22.03_IO流(内存输出流)(掌握)
该输出流可以向内存中写数据, 把内存当作一个缓冲区, 写出之后可以一次性获取出所有数据
- 2.使用方式
- 创建对象:
new ByteArrayOutputStream()
- 写出数据:
write(int)
,write(byte[])
- 获取数据:
toByteArray()
- 创建对象:
FileInputStream fis = new FileInputStream("a.txt");
ByteArrayOutputStream baos = new ByteArrayOutputStream(); //相当于在内存中创建了可以增长的数组
int b ;
while( (b = fis.read()) != -1) {
baos.write(b); // 此时其实是写数据到了内存里面
}
byte[] arr = baos.toByteArray(); //将缓冲区的数组全部拿出来, 并赋值给arr数组
System.out.println(new String(arr));
System.out.println(baos.toString()); //使用平台默认码表将缓冲区内容转为字符串
fis.close();
22.04_IO流(内存输出流之面试题)(掌握)
- 定义一个文件输入流,调用
read(byte[] b)
方法,将a.txt文件中的内容打印出来(byte数组大小限制为5)
FileInputStream fis = new FileInputStream("a.txt"); //创建字节输入流,关联a.txt
ByteArrayOutputStream baos = new ByteArrayOutputStream(); //创建内存输出流
byte[] arr = new byte[5]; //创建字节数组,大小为5
int len;
while((len = fis.read(arr)) != -1) { //将文件上的数据读到字节数组中
baos.write(arr, 0, len); //将字节数组的数据写到内存缓冲区中
}
System.out.println(baos); //将内存缓冲区的内容转换为字符串打印
fis.close();
22.05_对象操作流ObjecOutputStream(了解)
该流可以将一个对象写出, 或者读取一个对象到程序中. 也就是执行了序列化和反序列化的操作.
- 写出:
new ObjectOutputStream(OutputStream)
,writeObject()
//无论是字节输出流,还是字符输出流都不能直接写出对象
Person p1 = new Person("我啊", 20);
Person p2 = new Person("你啊", 56);
// 这个其实也是装饰模式
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.txt"));
oos.writeObject(p1);
oos.writeObject(p2);
oos.close();
22.06_对象操作流ObjectInputStream(了解)
- 读取:
new ObjectInputStream(InputStream)
,readObject()
// 读取对象(反序列化)
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("a.txt"));
Person p1 = (Person) ois.readObject(); //可能有ClassNotFoundException
Person p2 = (Person) ois.readObject(); //当读取到文件末尾,继续读取,会出现EOFException
System.out.println(p1);
System.out.println(p2);
ois.close();
22.07_对象操作流优化(了解)
// 1.读写多个对象时,将对象添加到集合里,写出集合,就不用考试多少个对象问题
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("我啊", 20));
list.add(new Person("你啊", 56));
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.txt"));
oos.writeObject(list);
oos.close();
// 2.读取多个对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("a.txt"));
@SuppressWarnings("unchecked")
ArrayList<Person> aList = (ArrayList<Person>) ois.readObject();
for (Person person : aList) { //泛型在运行期会被擦除,索引运行期相当于没有泛型
System.out.println(person);
}
ois.close();
关于Java泛型的一点思考
其实学好、学扎实编程语言的基础,十分重要,对日后编程有十分有帮助。如果你掌握了编程语言的高级语法,基础十分扎实(内功深厚),那么你写出的代码,将比其他人写的代码有水平很多。
另外就是如果你又扎实深厚的基础,那么也能大大减少日后编程中犯低级错误。
ArrayList<Integer> l1 = new ArrayList<>();
l1.add(100);
ArrayList l2 = null;
l2 = l1; //泛型擦除 ,证明Java泛型是伪泛型,JVM编译时,并没有核对泛型信息,绕过了类型检查
从反射也能说明Java泛型,只是编译时有效,运行后会去泛型化
l2.add("dftd");
//
System.out.println(l2.get(0).getClass());
System.out.println(l2.get(1).getClass());
System.out.println(l1.size());
Integer temp = l1.get(1); //泛型擦除,带来的隐患,报错
22.08_IO流(加上id号)(了解)
- 要写出的对象必须实现
Serializable
接口才能被序列化 - 不用必须加id号
/**
* serialVersionUID 序列化版本号,为了序列化时,如果增加了属性,或方法,反序列化之前的版本,能提示出问题所在。
* 其实不加也行,因为加不加,在反序列老版本对象都会出现异常错误。
*/
private static final long serialVersionUID = 1L;
22.09_IO流(打印流的概述和特点)(掌握)
该流可以很方便的将对象的toString()
结果输出, 并且自动加上换行, 而且可以使用自动刷出的模式
System.out就是一个PrintStream, 其默认向控制台输出信息
PrintStream ps = System.out;
ps.println("xxoo");
ps.println(97); // 底层将 数字97 转为了字符串
ps.write(97); //打印 a
ps.close();
----------------------分割线--------------------
PrintWriter pw2 = new PrintWriter(new FileOutputStream("a.txt"), true);
pw2.println(97); // 自动刷出功能,只针对 println() 方法
pw2.write(97); // 并不会写到文件里
pw2.close(); // 因为流操作都会要close,所以自定刷出其实没有什么卵用
// PrintStream 和 PrintWriter分别打印的是字节流和字符流
// 二者只操作数据目的,不操作 数据源
22.10_标准输入输出流概述和输出语句
-
System.in
是InputStream
, 标准输入流, 默认可以从键盘输入读取字节数据 -
System.out
是PrintStream
, 标准输出流, 默认可以向Console中输出字符和字节数据 - 2.修改标准输入输出流(了解)
System.setIn(new FileInputStream("a.txt")); //改变标准输入流
System.setOut(new PrintStream("b.txt")); //改变标准输出流
InputStream is = System.in; //此时已经指向文件了,而不是键盘了
PrintStream ps = System.out; //此时不再指向控制台,而是b.txt
int data ;
while( (data = is.read()) != -1) {
ps.write(data);
}
is.close(); // 因为关联的文件,所以要关闭输入流和输出流
ps.close();
22.11_IO流(修改标准输入输出流拷贝图片)(了解)
System.setIn(new FileInputStream("xxoo.jpg")); //改变标准输入流
System.setOut(new PrintStream("copy.jpg")); //改变标准输出流
InputStream is = System.in;
PrintStream ps = System.out;
byte[] data = new byte[1024 * 10];
int len;
while( (len = is.read(data)) != -1) {
ps.write(data, 0, len);
}
is.close();
ps.close();
22.11_IO流(两种方式实现键盘录入)(了解)
// 2种键盘录入
// InputStreamReader转换流
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = br.readLine();
br.close();
System.out.println(str);
Scanner sc = new Scanner(System.in); // 第二种键盘输入
String str2 = sc.nextLine();
sc.close();
System.out.println(str2);
22.12_随机访问流概述和读写数据)(了解)
-
RandomAccessFile
类不属于流,是Object
类的子类。但它融合了InputStream
和OutputStream
的功能。 - 支持对随机访问文件的读取和写入。
- 这个
seek()
跳字节读取的功能,可以用于多线程下载和上传。
RandomAccessFile raf = new RandomAccessFile("a.txt", "rw");
raf.write(97); //写入 a
int x = raf.read(); // 读取 (发现读取的不是97,说明指针移到了下一个字节)
System.out.println(x);
raf.seek(10); //当当前指针遇到10的位置
raf.write(120);
raf.close();
22.13_IO流(数据输入输出流)(了解)
- DataInputStream, DataOutputStream可以按照基本数据类型大小读写数据
- 例如按Long大小写出一个数字, 写出时该数据占8字节. 读取的时候也可以按照Long类型读取, 一次读取8个字节.
DataOutputStream dos = new DataOutputStream(new FileOutputStream("a.txt"));
dos.writeInt(997); //写入真实的 997 ,
dos.writeInt(998);
dos.close();
DataInputStream dis = new DataInputStream(new FileInputStream("a.txt"));
System.out.println(dis.readInt()); // 按照 int读取一个值
System.out.println(dis.readInt());
dis.close();
// 因为write(int a) 虽然接收是int,但是实际是byte类型的转换,实际写入时,不会超过byte的取值范围
// 00000000 00000000 00000011 11100101 int类型的997
// 11100101 真实写入的值, write写入会去掉int的前24位,而11100101找不到对应的码表,就会是乱码
// 00000000 00000000 00000000 11100101 读取之后的int已经是 229了
FileOutputStream fos = new FileOutputStream("a.txt");
fos.write(997); //结果发现写入之后是乱码的
fos.close();
22.14_Properties的概述和作为Map集合的使用(了解)
-
Properties
类表示了一个持久的属性集,本质是一个双列集合,因为键值都是字符串,所以没有泛型。 -
Properties
可保存在流中或从流中加载。 - 属性列表中每个键及其对应值都是一个字符串。
Properties pp = new Properties();
pp.put("verson", "2.3.0");
System.out.println(pp);
22.15_Properties的特殊功能使用(了解)
-
Properties
的特殊功能
Properties pp = new Properties();
pp.setProperty("verson", "3.2.0"); //向里面添加键值对
pp.setProperty("type", "android");
// 遍历 (强转是因为泛型问题)
Enumeration<String> enu = (Enumeration<String>) pp.propertyNames();
while(enu.hasMoreElements()){
String key = enu.nextElement() ;
System.out.println( key + "-->" + pp.get(key)); // 根据key,获取value
}
22.16_Properties的load()和store()功能(了解)
Properties pp = new Properties();
pp.load(new FileInputStream("config.list")); //将文件上的键值对读取到集合中
System.out.println(pp);
// 修改配置
pp.setProperty("name", "Java EE");
// 写入配置文件
pp.store(new FileOutputStream("config.list"), "我是描述信息,可以为null");
END。
我是小侯爷。
在魔都艰苦奋斗,白天是上班族,晚上是知识服务工作者。
如果读完觉得有收获的话,记得关注和点赞哦。
非要打赏的话,我也是不会拒绝的。
网友评论