课程回顾
List:
有序可重复
ArrayList 基于数组存储,默认长度10,扩容1.5倍;
LinkedList 基于双向链表存储的,节点用的是静态内部类Node:包括三部分①prev上一个节点的引用②e表示数据③next下一个节点的引用,
Vector 线程安全的List, 核心方法都是加锁synchronized, 扩容2倍。
Set:
HashSet TreeSet LinkedHashSet ConcurrentHashSet; 这些本身不存储都依赖于对应的Map结构存储数据。
特点: 无序、不允许重复
Map:
键值对,key—value的映射关系; 鹿晗-----关晓彤
HashMap、TreeMap( 默认是自然顺序 Comparable接口,所有的基本数据类型的包装类都实现该接口 )可以进行比较。自定义的比较器: ①自身具备比较性,实现Comparable接口。②通过第三方的比较器: 实现接口Comparator,在创建TreeMap的时候传入这个比较器。可以是Lambad表达式简化编码。
本章简介
File类
File类是用来描述磁盘上的目录和文件,可以表示目录也可以表示文件。File类的常用方法
- 创建文件
- 删除文件
- 判断文件是否存在、是否可读、可写
- 创建目录
- 列举目录的文件
- 获取磁盘的信息: 包括多少分区、分区的总大小、可用大小
- 获取文件的绝对路径
案例:
package ch005io;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
public class Demo1 {
//check异常、非check异常; IOExecption编译期异常
public static void main(String[] args) throws IOException {
listFile("D:\\eclipse-workspace\\web1");//调用递归方法
}
private static void test4() {
//获取磁盘空间信息
File[] roots = File.listRoots();
for (File file : roots) {
long totalSpace = file.getTotalSpace();
System.out.print(file.getAbsolutePath()+":");
// byte kb mb gb
System.out.print("分区总大小:"+(totalSpace/1024/1024/1024));
long freeSpace = file.getFreeSpace();
System.out.print(",剩余总大小:"+(freeSpace/1024/1024/1024));
long usableSpace = file.getUsableSpace();
System.out.print(",可用空间大小:"+(usableSpace/1024/1024/1024)+"\n");
}
}
private static void test3() {
File dirs = new File("D:\\eclipse-workspace\\web1");
String[] fileName =dirs.list((dir,name) -> name.endsWith("java"));
for (String string : fileName) {
System.out.println(string);
}
}
//递归调用列举指定目录下的所有文件和文件夹的文件
public static void listFile(String path) {
File files = new File(path);
File[] listFiles = files.listFiles();
for (File file : listFiles) {
if(file.isDirectory()) {
//如果是目录:
listFile(file.getAbsolutePath());
}else {
//不是目录就是文件
System.out.println("==="+file.getAbsolutePath());
}
}
}
private static void test2() {
//1.创建目录的方法
File dir = new File("d:\\kong\\fu\\zi");
System.out.println("创建文件夹:"+dir.mkdir());
System.out.println("创建多级目录:"+dir.mkdirs());
//2.列举目录的文件:只能是当前目录
File dirs = new File("D:\\eclipse-workspace\\web1");
String[] files = dirs.list();
for (String string : files) {
System.out.println(string);
}
//3.列举指定的文件
String[] fileName =dirs.list(new FilenameFilter() {
//两个参数: dir路径,name文件名
@Override
public boolean accept(File dir, String name) {
return name.endsWith("java");
}
});
System.out.println("所有的java文件:");
for (String string : fileName) {
System.out.println(string);
}
}
private static void test1() throws IOException {
//1.创建文件
File file =new File( "d:" + File.separator + "abc.doc" );
//windows路径分隔符";", Linux用的是":"
//windows文件 \ linux: /
System.out.println("路径分隔符:"+ File.pathSeparator);
boolean result = file.createNewFile();
System.out.println(result);
//2.获取文件信息
System.out.println("绝对路径:"+file.getAbsolutePath());
System.out.println("相对路径:"+file.getPath());
System.out.println("文件名称:"+file.getName());
System.out.println("文件父路径:"+file.getParent());
System.out.println("文件大小:"+file.length());
//3.是否可读
System.out.println("是否可读:"+file.canRead());
System.out.println("是否可写:"+file.canWrite());
System.out.println("是否可执行:"+file.canExecute());
System.out.println("得到规范文件:"+file.getCanonicalFile());
//4.删除文件
System.out.println("删除文件:"+file.delete());
}
}
创建目录的源代码,这就是调用操作系统的接口, JNI,
/**
* Create a new directory denoted by the given abstract pathname,
* returning <code>true</code> if and only if the operation succeeds.
*/
public abstract boolean createDirectory(File f);
继续跟踪代码的实现:
@Override
public native boolean createDirectory(File f);
native是本地的意思,表单调用本地方法,就是操作系统的接口,C语言的接口。
流的使用参考:
字节流
区分 Java 的输入和输出:把自己当成程序,武术的最高境界:人剑合一,编码的最高境界: 人码合一,司机的最高境界:人车合一。 当你从外边读数据到自己这里就用输入(InputStream/Reader), 向外边写数据就用输出(OutputStream/Writer)。
Stream:Java 中将数据的输入输出抽象为流,流是一组有顺序的,单向的,有起点和终点的数据集合,就像水流。按照流中的最小数据单元又分为字节流和字符流。
1,字节流:以 8 位(即 1 byte,8 bit)作为一个数据单元,数据流中最小的数据单元是字节。
2,字符流:以 16 位(即 1 char,2 byte,16 bit)作为一个数据单元,数据流中最小的数据单元是字符, Java 中的字符是 Unicode 编码,一个字符占用两个字节。
FileOutputStream
定义:
public class FileOutputStream extends OutputStream
public abstract class OutputStream extends Object implements Closeable, Flushable
文件输出流是用于将数据写入到输出流File
或一个FileDescriptor
。文件是否可用或可能被创建取决于底层平台。特别是某些平台允许一次只能打开一个文件来写入一个FileOutputStream
(或其他文件写入对象)。在这种情况下,如果所涉及的文件已经打开,则此类中的构造函数将失败。
FileOutputStream
用于写入诸如图像数据的原始字节流。 对于写入字符流,请考虑使用FileWriter
。
OutputStream的方法
Modifier and Type | Method and Description |
---|---|
void | close() 关闭此输出流并释放与此流相关联的任何系统资源。 |
void | flush() 刷新此输出流并强制任何缓冲的输出字节被写出。 |
void | write(byte[] b) 将 b.length 字节从指定的字节数组写入此输出流。 |
void | write(byte[] b, int off, int len) 从指定的字节数组写入 len 个字节,从偏移 off 开始输出到此输出流。 |
abstract void | write(int b) 将指定的字节写入此输出流。 |
FileOutputStream常用方法
Constructor and Description |
---|
FileOutputStream(File file) 创建文件输出流以写入由指定的 File 对象表示的文件。 |
FileOutputStream(File file, boolean append) 创建文件输出流以写入由指定的 File 对象表示的文件。 |
FileOutputStream(FileDescriptor fdObj) 创建文件输出流以写入指定的文件描述符,表示与文件系统中实际文件的现有连接。 |
FileOutputStream(String name) 创建文件输出流以指定的名称写入文件。 |
FileOutputStream(String name, boolean append) 创建文件输出流以指定的名称写入文件。 |
方法摘要
Modifier and Type | Method and Description |
---|---|
void | close() 关闭此文件输出流并释放与此流相关联的任何系统资源。 |
protected void | finalize() 清理与文件的连接,并确保当没有更多的引用此流时,将调用此文件输出流的 close 方法。 |
FileChannel | getChannel() 返回与此文件输出流相关联的唯一的FileChannel 对象。 |
FileDescriptor | getFD() 返回与此流相关联的文件描述符。 |
void | write(byte[] b) 将 b.length 个字节从指定的字节数组写入此文件输出流。 |
void | write(byte[] b, int off, int len) 将 len 字节从位于偏移量 off 的指定字节数组写入此文件输出流。 |
void | write(int b) 将指定的字节写入此文件输出流。 |
案例:
package ch005io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo2 {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("d:\\abc.txt");
byte [] b = new byte[9];
int len = 0;
//while的表达式执行过程: ①先读取9个字节②把9赋值给len③len和-1比较,true或false
while( ( len = fis.read(b)) !=-1 ) {
System.out.println("==len=="+len);
System.out.println("==="+new String(b,0,len));
}
fis.close();
}
private static void test2() throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream("d:\\abc.txt");
byte [] b = new byte[1024];
int len = fis.read(b);
System.out.println(len);
System.out.println("==="+new String(b,0,len));
fis.close();
}
private static void test1() {
FileOutputStream fos = null ;
try {
//默认是覆盖模式,追加模式 new FileOutputStream("d:\\abc.txt",true);
fos = new FileOutputStream("d:\\abc.txt");
String name ="古力娜扎";
fos.write(name.getBytes());
String address = "XinJiang";
fos.write(address.getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(fos != null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
FileInputStream
FileInputStream
用于读取诸如图像数据的原始字节流。
Constructor and Description |
---|
FileInputStream(File file) 通过打开与实际文件的连接创建一个 FileInputStream ,该文件由文件系统中的 File 对象 file 命名。 |
FileInputStream(FileDescriptor fdObj) 创建 FileInputStream 通过使用文件描述符 fdObj ,其表示在文件系统中的现有连接到一个实际的文件。 |
FileInputStream(String name) 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name 命名。 |
常用方法:
Modifier and Type | Method and Description |
---|---|
int | available() 返回从此输入流中可以读取(或跳过)的剩余字节数的估计值,而不会被下一次调用此输入流的方法阻塞。 |
void | close() 关闭此文件输入流并释放与流相关联的任何系统资源。 |
protected void | finalize() 确保当这个文件输入流的 close 方法没有更多的引用时被调用。 |
FileChannel | getChannel() 返回与此文件输入流相关联的唯一的FileChannel 对象。 |
FileDescriptor | getFD() 返回表示与此 FileInputStream 正在使用的文件系统中实际文件的连接的 FileDescriptor 对象。 |
int | read() 从该输入流读取一个字节的数据。 |
int | read(byte[] b) 从该输入流读取最多 b.length 个字节的数据为字节数组。 |
int | read(byte[] b, int off, int len) 从该输入流读取最多 len 字节的数据为字节数组。 |
long | skip(long n) 跳过并从输入流中丢弃 n 字节的数据。 |
案例:注意一个UTF8字符占3个字节
private static void test3() throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream("d:\\abc.txt");
byte[] b = new byte[9];
int len = 0;
// while的表达式执行过程: ①先读取9个字节②把9赋值给len③len和-1比较,true或false
while ((len = fis.read(b)) != -1) {
System.out.println("==len==" + len);
System.out.println("===" + new String(b, 0, len));
}
fis.close();
}
read读取源码分析:
/**
* Reads up to <code>b.length</code> bytes of data from this input
* stream into an array of bytes. This method blocks until some input
* is available.
*
* @param b the buffer into which the data is read.
* @return the total number of bytes read into the buffer, or
* <code>-1</code> if there is no more data because the end of
* the file has been reached.
* @exception IOException if an I/O error occurs.
*/
public int read(byte b[]) throws IOException {
return readBytes(b, 0, b.length);
}
//继续跟踪代码
/**
* Reads a subarray as a sequence of bytes.
* @param b the data to be written
* @param off the start offset in the data
* @param len the number of bytes that are written
* @exception IOException If an I/O error has occurred.
* 可以看出调用本地方法,native
*/
private native int readBytes(byte b[], int off, int len) throws IOException;
这就是JVM的本地方法栈的主要工作,参考文献
文件复制
public static void main(String[] args) {
//从jdk1.7引入自动关闭的,不用在finally里关闭
try(FileInputStream fis = new FileInputStream("d:\\1.jpg");
FileOutputStream fos = new FileOutputStream("e:\\xxx.jpg");){
//建缓冲字节数组
byte [] b = new byte[1024];
int len = 0;
while( (len=fis.read(b)) != -1 ) {
fos.write(b,0,len);
}
}
catch(Exception e) {
e.printStackTrace();
}
}
字节缓冲流
有缓冲可以提高效率,否则每次读写都要访问磁盘,缓冲流在内部创建一个容器: 8192kb,容器临时存储,从而减少访问磁盘的次数。
public static void main(String[] args) throws Exception {
//创建带缓冲的输入流
FileInputStream fis = new FileInputStream("d:\\1.jpg");
BufferedInputStream bis = new BufferedInputStream(fis);
//创建带缓冲的输出流 使用匿名对象,因为没有直接用到fis的方法,所以可以简化编码
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("E:\\YYY.jpg"));
//建缓冲字节数组
byte [] b = new byte[1024];
int len = 0;
while( (len=bis.read(b)) != -1 ) {
bos.write(b,0,len);
}
bos.close();
bis.close();
}
复制视频:
public static void main(String[] args) throws Exception {
long start = System.currentTimeMillis();
//创建带缓冲的输入流
String file = "E:\\OOP\\第4章 集合框架\\视频\\1.设置工作空间编码.mp4";
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
//创建带缓冲的输出流 使用匿名对象,因为没有直接用到fis的方法,所以可以简化编码
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("E:\\YYY.mp4"));
//建缓冲字节数组
byte [] b = new byte[8192];
int len = 0;
while( (len=bis.read(b)) != -1 ) {
bos.write(b,0,len);
}
bos.close();
bis.close();
long end = System.currentTimeMillis();
System.out.println("耗时:"+ (end-start) );
}
对象序列化
对象序列化就是把内存中的对象携带的属性信息,持久化到磁盘文件,下次再可以从文件中恢复一个对象。美国有一个富豪: 把他冷冻起来,200年之后再解冻,恢复。还有一些有故事情节的RPG游戏,可以保存磁盘。
如果一个对象要序列化则必须实现Serializable接口;相应的其关联对象也要实现Serializable接口。
序列化的实体类:
package ch005io;
import java.io.Serializable;
public class Emp implements Serializable {
/**
* 这个ID号是为了在反序列化的时候进行验证的。
*/
private static final long serialVersionUID = 7641462444428635110L;
private Integer id;
private String name;
private Dept dept;
public Emp(Integer id, String name,Dept dept) {
super();
this.id = id;
this.name = name;
this.dept = dept;
}
public Integer getId() {
return id;
}
@Override
public String toString() {
return "Emp [id=" + id + ", name=" + name + ", dept=" + dept + "]";
}
}
//====================
package ch005io;
import java.io.Serializable;
public class Dept implements Serializable{
private static final long serialVersionUID = -7949058275393267252L;
private Integer deptNo;
private String dname;
private String loc;
public Dept(Integer deptNo, String dname, String loc) {
super();
this.deptNo = deptNo;
this.dname = dname;
this.loc = loc;
}
@Override
public String toString() {
return "Dept [deptNo=" + deptNo + ", dname=" + dname + ", loc=" + loc + "]";
}
}
案例:
package ch005io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class Demo3 {
public static void main(String[] args) throws Exception {
test2();
}
//反序列化
private static void test2() throws IOException, FileNotFoundException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:\\game.bin"));
Emp emp = (Emp) ois.readObject();
System.out.println(emp);
ois.close();
}
//序列化
private static void test1() throws FileNotFoundException, IOException {
//节点流
FileOutputStream fos = new FileOutputStream("d:\\game.bin");
//包装流
ObjectOutputStream oos = new ObjectOutputStream(fos);
Dept dept = new Dept(1000,"市场部","乌鲁木齐");
Emp emp = new Emp(1001,"迪丽热巴",dept);
oos.writeObject(emp);
oos.close();
}
}
序列化的时候,对象的所有属性都进行序列化了;有些特殊、关键、涉密属性最好别序列化;这就涉及到自定义序列化的属性。只需在属性上加transite即可,变成瞬时状态。
package ch005io;
import java.io.Serializable;
public class Emp implements Serializable {
/**
* 这个ID号是为了在反序列化的时候进行验证的。
*/
private static final long serialVersionUID = 7641462444428635110L;
private Integer id;
private String name;
//不进行序列化的属性
private transient String bankCard;
//关联属性,也要实现序列化接口
private Dept dept;
public Emp(Integer id, String name,String bankCard,Dept dept) {
super();
this.id = id;
this.name = name;
this.bankCard = bankCard;
this.dept = dept;
}
public Integer getId() {
return id;
}
@Override
public String toString() {
return "Emp [id=" + id + ", name=" + name + ", bankCard=" + bankCard + ", dept=" + dept + "]";
}
}
测试类:
package ch005io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class Demo3 {
public static void main(String[] args) throws Exception {
test2();
}
//反序列化
private static void test2() throws IOException, FileNotFoundException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:\\game.bin"));
Emp emp = (Emp) ois.readObject();
System.out.println(emp);
ois.close();
}
//序列化
private static void test1() throws FileNotFoundException, IOException {
//节点流
FileOutputStream fos = new FileOutputStream("d:\\game.bin");
//包装流
ObjectOutputStream oos = new ObjectOutputStream(fos);
Dept dept = new Dept(1000,"市场部","乌鲁木齐");
Emp emp = new Emp(1001,"迪丽热巴","1123433234",dept);
oos.writeObject(emp);
oos.close();
}
}
输出结果:
Emp [id=1001, name=迪丽热巴, bankCard=null, dept=Dept [deptNo=1000, dname=市场部, loc=乌鲁木齐]]
可以看到bankCard没有序列化。如果序列化多个对象,可以放到List集合中,反序列化再用List集合接收。
字符流
字符流的由来: Java中字符是采用Unicode标准,一个字符是16位,即一个字符使用两个字节来表示。为此,JAVA中引入了处理字符的流。因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。
FileWriter类的用法
Constructor and Description |
---|
FileWriter(File file) 给一个File对象构造一个FileWriter对象。 |
FileWriter(File file, boolean append) 给一个File对象构造一个FileWriter对象。 |
FileWriter(FileDescriptor fd) 构造与文件描述符关联的FileWriter对象。 |
FileWriter(String fileName) 构造一个给定文件名的FileWriter对象。 |
FileWriter(String fileName, boolean append) 构造一个FileWriter对象,给出一个带有布尔值的文件名,表示是否附加写入的数据。 |
案例:
private static void test2() throws FileNotFoundException, IOException {
FileReader reader = new FileReader("hehe.txt");
char [] buffer = new char[1024];
//一次读取,也可以循环读取,参考字节流
int len = reader.read(buffer);
System.out.println(new String(buffer,0,len));
reader.close();
}
private static void test1() throws IOException {
FileWriter writer = new FileWriter("hehe.txt");
writer.write("Java基础知识面试题(2020最新版)");
writer.write("\n");
writer.write("这些插件太强了,Chrome 必装!尤其程序员!");
char [] sex = {'男','女'};
writer.write(sex);
writer.append("Firebug 的年代,我是火狐(Mozilla Firefox)浏览器的死忠");
writer.flush();
writer.close();
}
字符缓冲流
优势一次可以读取一行,提高效率。
private static void test3() throws IOException, FileNotFoundException {
BufferedWriter bw = new BufferedWriter(new FileWriter("d:\\123.txt"));
bw.write("Chrome 浏览器有一个好处,就是插件极其丰富,只有你想不到的");
bw.newLine();
bw.write("言归正传,今天来给大家推荐 10 款我自己珍藏的 Chrome 浏览器插件。");
bw.newLine();
bw.close();
//读取文件
BufferedReader br =new BufferedReader(new FileReader("d:\\123.txt"));
String line = null;//存储读取的数据
while(br.ready()) {
line = br.readLine();
System.out.println(line);
}
br.close();
}
转换流
字节到字符的转换
public static void main(String[] args) throws Exception {
//把字节流转换成字符流,页可以是FileInputStream
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
System.out.println("亲,请说话,输入exit退出系统。");
String line = br.readLine();
while(line != null) {
if("exit".equals(line)) {
break;
}
System.out.println(line);
line = br.readLine();
}
}
字符到字节的转换
public static void main(String[] args) throws Exception {
//字符流到字节流的转换
OutputStreamWriter osw = new OutputStreamWriter(System.out);
BufferedReader br = new BufferedReader(new FileReader("d:\\abc.txt"));
String line = br.readLine();
while(line != null) {
osw.write(line);
osw.write("\n");
line = br.readLine();
}
br.close();
osw.close();
}
private static void test5() throws IOException {
//字符流到字节流的转换
OutputStreamWriter osw = new OutputStreamWriter(System.out);
String str ="Chrome 浏览器有一个好处,就是插件极其丰富,只有你想不到的,";
osw.write(str);
osw.close();
}
打印流
public static void main(String[] args) throws Exception {
//字符打印流,PrintStream 字节打印流
PrintWriter out = new PrintWriter("d:\\haha.txt");
out.println(" crxMouse Chrome™ 手势");
out.println(" crxMouse Chrome™ 手势");
out.println(" crxMouse Chrome™ 手势");
out.println(100);
out.println(3.14);
out.close();
}
管道流
public static void main(String[] args) throws Exception {
PipedOutputStream pos = new PipedOutputStream();
PipedInputStream pis = new PipedInputStream(pos);
//张三向外倒水
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
pos.write("迪丽热巴".getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
});
//李四向里接水
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
byte[] b = new byte[1024];
int len = pis.read(b);
System.out.println("李四接收数据:"+new String(b,0,len));
} catch (IOException e) {
e.printStackTrace();
}
}
});
//启动线程
t1.start();
t2.start();
Thread.sleep(500);//确保两个子线程先跑
pis.close();
}
合并流
package ch005io;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.SequenceInputStream;
public class Demo5 {
public static void main(String[] args) {
FileInputStream fistream1 = null;
FileInputStream fistream2 = null;
SequenceInputStream sistream = null;
FileOutputStream fostream = null;
try {
fistream1 = new FileInputStream("d:/A.txt");
fistream2 = new FileInputStream("d:/B.txt");
sistream = new SequenceInputStream(fistream1, fistream2);
fostream = new FileOutputStream("d:/C.txt");
int temp;//一次读取一个字符
while ((temp = sistream.read()) != -1) {
System.out.print((char) temp);
fostream.write(temp);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fostream.close();
sistream.close();
fistream1.close();
fistream2.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
}
总结
字节流对应关系
字符流对应关系
常见面试题
1、字节流和字符流的区别?
(1)读写单位不同:字节流以字节(8 bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
(2)处理对象不同:字节流能处理所有类型的数据(如图片、avi 等),而字符流只能处理字符类型的数据。
(3)字节流没有缓冲区,是直接输出的,而字符流是输出到缓冲区的。因此在输出时,字节流不调用 colse() 方法时,信息已经输出了,而字符流只有在调用 close() 方法关闭缓冲区时,信息才输出。要想字符流在未关闭时输出信息,则需要手动调用 flush() 方法。
2、什么是节点流,什么是处理流,它们各有什么用处,处理流的创建有什么特征?
见上文:节点流和处理流;
注意:处理流的构造器必须要 传入节点流的子类
3、什么叫对象序列化,什么是反序列化,实现对象序列化需要做哪些工作?
- 对象序列化:将对象以二进制的形式保存在硬盘上;
- 反序列化:将二进制的文件转化为对象读取;
- 实现 serializable 接口可以实现对象序列化,其中没有需要实现的方法,implements Serializable 只是为了标注该对象是可被序列化的。
例如,在 web 开发中,如果对象被保存在了 Session 中,tomcat 在重启时要把 Session 对象序列化到硬盘,这个对象就必须实现 Serializable 接口。如果对象要经过分布式系统进行网络传输,被传输的对象就必须实现 Serializable 接口。
4、什么是 Filter 流有哪些?
FilterStream 是一种 IO 流,主要作用是用来对存在的流增加一些额外的功能,像给目标文件增加源文件中不存在的行数,或者增加拷贝的性能等。在 java.io 包中主要由 4 个可用的 filter Stream。两个字节 filter stream,两个字符 filter stream.
分别是:FilterInputStream,FilterOutputStream,FilterReader and FilterWriter. 这些类是抽象类,不能被实例化的。
FilterInputStream 流的子类:
- DataInputStream 可以把包括基本类型在内的数据和字符串按顺序从数据源读入,它有一些特殊的方法如 readInt(),readDouble() 和 readLine() 等可以读取一个 int,double 和一个 string。
- BufferedInputStream 增加性能。
- PushbackInputStream 推送要求的字节到系统中。
- 注:其它子类见 Java io 分类图。
6、说说 RandomAccessFile?
它在 java.io 包中是一个特殊的类,既不是输入流也不是输出流,它两者都可以做到。他是 Object 的直接子类。通常来说,一个流只有一个功能,要么读,要么写。但是 RandomAccessFile 既可以读文件,也可以写文件。
而且 RandomAccessFile 支持对文件的随机访问,实例可见上文:例 5,随机读写文件。
总结
很多初学者刚刚学习 java 的 IO 时会比较茫然,确实 IO 类很多,不容易记忆,不过我们可以尝试对其进行总结记忆,把流式部分概括为:两对应一桥梁一随机。
两个对应指:
- 字节流(Byte Stream)和字符流(Char Stream)的对应;
- 输入和输出的对应。
- 一个桥梁指:从字节流到字符流的桥梁。对应于输入和输出为InputStreamReader和OutputStreamWriter;
- 一个随机是:RandomAccessFile。可以随机读取文件。
增加拷贝的性能等。在 java.io 包中主要由 4 个可用的 filter Stream。两个字节 filter stream,两个字符 filter stream.
分别是:FilterInputStream,FilterOutputStream,FilterReader and FilterWriter. 这些类是抽象类,不能被实例化的。
FilterInputStream 流的子类:
- DataInputStream 可以把包括基本类型在内的数据和字符串按顺序从数据源读入,它有一些特殊的方法如 readInt(),readDouble() 和 readLine() 等可以读取一个 int,double 和一个 string。
- BufferedInputStream 增加性能。
- PushbackInputStream 推送要求的字节到系统中。
- 注:其它子类见 Java io 分类图。
6、说说 RandomAccessFile?
它在 java.io 包中是一个特殊的类,既不是输入流也不是输出流,它两者都可以做到。他是 Object 的直接子类。通常来说,一个流只有一个功能,要么读,要么写。但是 RandomAccessFile 既可以读文件,也可以写文件。
而且 RandomAccessFile 支持对文件的随机访问,实例可见上文:例 5,随机读写文件。
总结
很多初学者刚刚学习 java 的 IO 时会比较茫然,确实 IO 类很多,不容易记忆,不过我们可以尝试对其进行总结记忆,把流式部分概括为:两对应一桥梁一随机。
两个对应指:
- 字节流(Byte Stream)和字符流(Char Stream)的对应;
- 输入和输出的对应。
- 一个桥梁指:从字节流到字符流的桥梁。对应于输入和输出为InputStreamReader和OutputStreamWriter;
- 一个随机是:RandomAccessFile。可以随机读取文件。