黑马程序员技术交流社区

标题: 线程池,File类,Io流总结整理 [打印本页]

作者: 月寒水影    时间: 2018-8-7 16:00
标题: 线程池,File类,Io流总结整理
Day07线程池Lambda表达式线程间通信:概念:多个线程在处理同一个资源,但是处理的动作(线程的任务)却各不相同(需要协作);必要性:当我们需要多个线程来共同完成一件任务,并且我们希望他们有规律的执行,那么多线程之间需要一些协调通信,以此达到多线程共同操作一份数据;

等待唤醒机制:
概念:一个线程进行操作之后,就进入等待状态(wait()),等待其他线程执行完他们的代码过后,再将其唤醒(notify());
方法:
[Java] 纯文本查看 复制代码
java.lang.Object类:
// 成员方法 (只能通过"锁对象"调用)
void notify(): 随机唤醒在同一个锁对象上的某一个处于等待状态的线程;
void notifyAll(): 唤醒所有在同一个锁对象上处于等待状态的线程;
void wait(): 让当前线程处于无限等待状态, 同时释放锁;

注意:
1. wait() 与 notify() 必须要由"同一个锁对象"调用因为对应的锁对象可以通过 notify() 唤醒使用同一个锁对象调用的 wait() 后的线程 ;
2. wait() 与 notify() 是属于Object类的方法因为锁对象可以是任意对象, 而任意对象的所属类都是继承了Object类的 ;
3. wait() 与 notify() 必须要在"同步代码;


线程池
概念:一个容纳多个线程的容器,其中的线程可以反复使用, 省去了频繁创建线程对象的操作, 无需反复创建线程而消耗过多资源;
原理:提前创建好多个线程对象, 放在集合中. 多个任务来了反复使用这些线程对象来执行;
方法:
[Java] 纯文本查看 复制代码
java.util.concurrent.Executors类: 线程池工厂类, 用于管理线程池
// 静态方法:
static ExecutorService newFixedThreadPool(int nThreads): 创建固定数量线程的线程池(常用)
[Java] 纯文本查看 复制代码
java.util.concurrent.ExecutorService接口: 真正执行任务的线程池服务
// 成员方法:
Future submit(Runnable task): 提交一个Runnable任务
void shutdown(): 通知线程执行完任务后关闭. 如不调此方法, 则线程执行完任务后仍在运行以便重复使用

线程池的创建和使用步骤:
1. 使用Executors的静态方法 newFixedThreadPool(int nThreads) 创建线程池ExecutorService ;
2. 创建一个任务类, 实现Runnable接口, 重写run()方法 ;
3. 调用ExecutorService对象的 submit(Runnable task) 方法, 传递任务给线程池, 执行任务 ;
4. 调用ExecutorService对象的 shutdown() 方法, 销毁线程池 (不建议执行) ;
函数式编程思想: Lambda表达式
Lambda标准格式
Lambda表达式的3个部分:
1. 一些参数 ()接口中抽象方法的参数列表. 没参数就空着; 有参数就写, 多个参数用逗号分隔
2. 一个箭头 ->将参数传递给方法体
3. 一段代码 {}重写接口抽象方法的方法体
格式:// 写成一行(参数列表) -> {
               一些重写方法的代码
      }// 写成多行(参数列表) -> {
              一些重写方法的代码  
      }
Lambda省略格式和使用前提 :
可以省略的部分:
1. (参数列表): 参数"类型"可以省略
2. (参数列表): 如果参数只有1个, 则"类型"和"小括号"都可以省略 a -> sout(a)
3. {一些代码}: 如果只有一条代码, 则"大括号", "return", "分号"都可以"一起省略"
Lambda表达式的使用前提:
1. Lambda只能用于接口, 且"接口中有且仅有一个抽象方法"(也称为"函数式接口")普通类, 抽象类不能用
2. 使用Lambda必须具有上下文推断方法的参数或局部变量类型必须为Lambda对应的接口类型,才能使用Lambda作为该接口的实例(简而言之: 作为参数类型的接口, 必须是函数式接口)
Day08File类 递归笔记 File类

             java.io.File类: 文件和目录的路径名的抽象表现形式, 主要用于文件和目录的创建, 查找和删除等操作;
File类的静态成员变量
[Java] 纯文本查看 复制代码
java.io.File类: 文件和目录的路径名的抽象表现形式, 主要用于文件和目录的创建, 查找和删除等操作
// 静态成员变量
static String pathSeparator: 路径分隔符的字符串形式
static char pathSeparatorChar: 路径分隔符的char形式
Windows系统是 分号;
Linux系统是 冒号:
static String separator: 文件名称分隔符的字符串形式
static char separatorChar: 文件名称分隔符的char形式
Window系统是 反斜杠\
Linux系统是 正斜杠/
绝对路径和相对路径
绝对路径:以盘符开始的路径如: "D:\\a\\hi.txt"
相对路径:不以盘符开始的简化路径. 相对于项目的根目录如: "a\\1.mp3", "123.txt"
注意事项:
1. 路径不区分大小写 (在Windows系统中不区分大小写, Linux, Mac区分)
2. 路径一般写成字符串, 而字符串中一个\是转义, 所以要写两个\\
File类: 构造方法
[Java] 纯文本查看 复制代码
java.io.File类: 文件和目录的路径名的抽象表现形式, 主要用于文件和目录的创建, 查找和删除等操作
// 构造方法(创建了File对象, 并将其指向该路径. 不会真正在磁盘上创建这个文件)
File File(String pathname): 根据 路径字符串 封装一个File对象
File File(String parent, String child): 根据 父路径字符串 和 子路径字符串 封装File对象
File File(File parent, String child): 根据 父路径的File对象 和 子路径 封装File对象

File类: 获取方法
[Java] 纯文本查看 复制代码
java.io.File类
// 常用获取方法
String getAbsolutePath(): 返回此File的绝对路径名字符串
String getPath(): 获取File对象的封装路径 (创建对象时传入的路径)
String getName(): 获取File对象的文件名或目录名
long length(): 获取File表示的文件大小的字节数 (不能获取目录的大小)

File类: 判断方法
[Java] 纯文本查看 复制代码
java.io.File类
// 常用判断方法
boolean exists(): 判断File对象代表的文件或目录是否实际存在
boolean isDirectory(): 判断File表示的是否为目录
boolean isFile(): 判断File表示的是否为文件

File类: 创建删除方法
[AppleScript] 纯文本查看 复制代码
java.io.File类
// 常用创建删除方法
boolean createNewFile(): 当文件不存在时, 创建一个新的空文件
boolean delete(): 删除由此File表示的文件或目录. (删除目录时必须是空目录)
boolean mkdir(): 创建File表示的目录
boolean mkdirs(): 创建File表示的多级目录

File类: 遍历目录方法
[Java] 纯文本查看 复制代码
java.io.File类
// 常用获取目录中内容的方法
String[] list(): 获取当前File目录下的所有子文件或目录的名字数组
File[] listFiles(): 获取当前File目录中的所有子文件或目录的File对象数组

注意:只能用表示目录的File对象调用用文件的File对象, 或者路径不存在, 调用会报错;


递归
概念:方法内部调用方法自己 (所以必须定义方法);
递归的分类:直接递归: 方法自己调用方法间接递归: A方法调用B方法, B方法调用C方法, C方法调用A方法 ;
递归时的注意事项:
1. 递归要有限定条件(出口), 保证递归能够停止(就是在某种情况下方法不再调用自己), 否则会栈内存溢出;
2. 递归次数不能太多, 否则会栈内存溢出 ;
3. 构造方法不能递归;
递归的使用前提:
调用方法时, 方法的主体不变, 但每次传递的参数值不同, 可以使用递归;


FileFilter文件过滤器的原理和使用
[Java] 纯文本查看 复制代码
java.io.File类: Filter过滤器
File[] listFiles(FileFilter filter): 通过File对象过滤, 返回文件过滤器过滤后的File对象数组
File[] listFiles(FilenameFilter filter): 通过File对象的文件名过滤, 返回文件过滤器过滤后的File对
象数组
java.io.FileFilter接口: 用于File对象的过滤器
boolean accept(File pathName): true则会将参数的File对象加入返回的File[], false则不加入
java.io.FilenameFilter接口:
boolean accept(File dir, String name): true则会将参数的File对象加入返回的File[], false则不加入

Day09字节流 字符流 Properties
IO流

概念:IO流: 输入(In)输出(Out)流      流: 数据流        输入: 从硬盘读取到内存               输出: 从内存写入到硬盘
分类:
字节流 (读写字节: byte, 可以读写所有类型的文件, 包括视频, 图片, 音频, 文本等)
字节输入流: java.io.InputStream 抽象类
字节输出流: java.io.OutputStream 抽象类


字符流 (读写字符: char, String, 只能读写文本文件)
字符输入流: java.io.Reader 抽象类
字符输出流: java.io.Writer 抽象类
计算机中一切皆为字节 ;
字节输出流: OutputStream和FileOutputStream
方法:
[Java] 纯文本查看 复制代码
java.io.OutputStream抽象类: 字节输出流 (顶层类)
// 成员方法
void close() :释放资源
void flush() :刷新缓冲区(对于字节流来说没有作用)
// 写字节的成员方法
abstract void write(int b): 一次写一个字节 (参数是int是为了代码中写表示byte的整数方便不用强转)
void write(byte[] b): 一次写一个字节数组
void write(byte[] b, int off, int len): 一次写一个字节数组的一部分
java.io.FileOutputStream类: 文件字节输出流 (向文件写数据)
// 构造方法
FileOutputStream(String name): 通过文件路径创建文件字节输出流
FileOutputStream(File file): 通过File对象创建文件字节输出流
构造方法的作用:
1. 创建一个FileOutputStream对象
2. 根据构造方法传递的路径, 在磁盘上创建一个空文件 ("如果文件存在则会清空数据")
3. 将创建的FileOutputStream对象指向这个磁盘上的文件



字节输出流: 一次写一个字节到文件
写数据的原理:
Java程序 -> JVM虚拟机 -> OS操作系统 -> OS调用写数据的方法 -> 将数据写入文件
使用字节输出流写数据到文件的步骤:
1. 创建对象: 创建FileOutputStream对象, 构造方法中传递文件路径
2. 写入数据: 使用FileOutputStream对象调用 write(int b) 方法, 将字节写入文件
3. 释放资源: 使用FileOutputStream对象调用 close() 方法, 关闭流对象释放资源


文件存储原理和记事本打开文件的原理
向文件中写入字节数据时, 十进制的数字会被转换为"二进制"的数字写入文件
文本编辑器打开文本文件时, 会先查询编码表, 将二进制数字转换为对应的字符进行显示
    0-127: 查询ASCII码表
   其他: 查询系统默认码表
Windows简体中文系统的程序打开是按 GBK 码表 ,IDEA中使用的是 UTF-8 码表
字节输出流: 一次写多个字节
方法:
[Java] 纯文本查看 复制代码
java.io.FileOutputStream类: 文件字节输出流 (向文件写数据)
void write(byte[] b): 一次写一个字节数组
void write(byte[] b, int off, int len): 一次写一个字节数组的一部分
java.lang.String类:
byte[] getBytes(): 使用平台的默认字符集将此String编码为byte数组

字节输出流: 续写操作
方法:
[Java] 纯文本查看 复制代码
java.io.FileOutputStream类: 文件字节输出流
// 带有 续写 功能的构造方法, 不会清空文件
FileOutputStream(String name, boolean append): 通过文件路径创建文件字节输出流, true可以续写
FileOutputStream(File file, boolean append): 通过File对象创建文件字节输出流, true可以续写

字节输入流: InputStream和FileInputStream
方法:
[Java] 纯文本查看 复制代码
java.io.InputStream抽象类: 字节输入流 (顶层类)
// 常用成员方法
void close(): 释放资源
// 读数据的方法
int read(): 一次读一个字节
读到文件末尾返回-1 (返回int也是为了代码编写方便)
int read(byte[] b): 一次读一个字节数组
读到的字节存放在参数中的字节数组中, 返回int值是本次读到的字节的个数. 读到文件末尾返回-1
java.io.FileInputStream类: 文件字节输入流
// 构造方法
FileInputStream(String name): 使用文件路径创建文件字节输入流
FileInputStream(File file): 使用File对象创建文件字节输入流
构造方法的作用:
1. 创建FileInputStream对象
2. 将FileInputStream对象指向磁盘上的文件

字节输入流: 一次读取一个字节
方法:
// 一次读一个字节:
int by; // int变量用来存储每次读到的数据
while ((by = fis.read()) != -1) {
System.out.print((char)by); // 不要换行, 文件中自带换行的byte
}
fis.close();
[/mw_shl_code]

Java程序从文件读取数据的原理:Java程序 -> JVM虚拟机 -> OS(操作系统) -> OS调用读取的方法 -> 读取磁盘文件数据
java.io.InputStream抽象类: 字节输入流 (顶层类)int read(): 一次读一个字节读到文件末尾返回-1 (返回int也是为了代码编写方便)
FileInputStream读数据步骤:
1. 创建FileInputStream对象
2. 使用FileInputStream对象, 调用 int read() 方法, 一次读取一个byte
3. 释放资源
[Java] 纯文本查看 复制代码
FileInputStream fis = new FileInputStream("模块名\\文件名");
字节输入流: 一次读取一个字节数组
方法:
[mw_shl_code=java,true]java.io.InputStream抽象类: 字节输入流 (顶层类)
int read(byte[] b): 一次读一个字节数组
参数 byte[] b 作用: 存储每次读到的字节, 起到缓冲作用
返回值作用: 每次读到的字节个数, 读到文件末尾返回-1
java.lang.String类:
String(byte[] bytes): 使用平台默认字符集解码将byte数组转换为String
String(byte[] bytes, int offset, int length): 使用平台默认字符集将byte数组的一部分转换为String

字节流复制图片文件
文件复制的步骤:
1.创建一个字节输入流对象,构造方法中绑定要读取的数据源
2.创建一个字节输出流对象,构造方法中绑定要写入的目的地
3.使用字节输入流对象中的方法read读取文件
4.使用字节输出流中的方法write,把读取到的字节写入到目的地的文件中
5.释放资源
[Java] 纯文本查看 复制代码
// 创建输入流和输出流
FileInputStream fis = new FileInputStream("c:\\1.jpg"); // 输入流指向要读的数据源文件
FileOutputStream fos = new FileOutputStream("d:\\1.jpg"); // 输出流指向要写的目的地文件
// 一次读写一个字节数组
byte[] bytes = new byte[1024];
int len = 0;
while((len = fis.read(bytes))!=-1){
fos.write(bytes,0,len);
}
// 释放资源
fos.close();
fis.close();

字符流
字符输入流: Reader和FileReader
方法:
[Java] 纯文本查看 复制代码
java.io.Reader抽象类: 字符输入流 (顶层)
// 常用成员方法
void close() :关闭此流并释放与此流相关联的任何系统资源
// 读
int read(): 一次读一个字符char, 返回读到的字符.
读到文件末尾返回-1 (返回int为了代码编写方便)
int read(char[] cbuf): 一次读取一个字符数组char[]
返回读取的字符个数. 读到文件末尾返回-1
java.io.FileReader类: 文件字符输入流
// 构造方法
FileReader(File file): 根据File对象创建文件字符输入流
FileReader(String fileName): 根据File对象创建文件字符输入流
构造方法的作用:
1. 创建FileReader对象
2. 将FileReader对象指向磁盘上的文件

字符输入流: 2种方式读取文本文件
方法:
[Java] 纯文本查看 复制代码
java.io.Reader抽象类: 字符输入流 (顶层)
int read(): 一次读一个字符char, 返回读到的字符.
读到文件末尾返回-1 (返回int为了代码编写方便)
int read(char[] cbuf): 一次读取一个字符数组char[]
返回读取的字符个数. 读到文件末尾返回-1
java.lang.String类:
String(char[] value): 将char数组转换为String
String(char[] value, int offset, int count): 将char数组的一部分转换为String
FileReader fr = new FileReader("a.txt");
// 一次读一个字符
int ch; // 定义变量保存每次读到的字符
while ((ch = fr.read()) != -1) {
System.out.print((char)ch);
}
// 一次读一个字符数组
char[] cs = new char[1024];
int len;
while ((len = fr.read(cs)) != -1) {
String s = new String(cs, 0, len);
System.out.print(s);
}
// 释放资源
fr.close();

字符输出流: Writer和FileWriter
方法:
[Java] 纯文本查看 复制代码
java.io.Writer抽象类: 字符输出流 (顶层类)
// 常用成员方法
abstract void close(): 刷新缓冲区并释放资源
abstract void flush() :刷新缓冲区
// 写
void write(int c): 写一个字符 (int类型为了代码编写方便)
void write(char[] cbuf): 写一个字符数组
abstract void write(char[] b, int off, int len): 写一个字符数组的一部分
void write(String str): 写一个字符串
void write(String str, int off, int len): 写一个字符串的一部分
注意: write()方法只是将数据写到内存缓冲区, 最后必须调用flush()或close()才能将数据真正写入磁盘
java.io.FileWriter类: 文件字符输出流
// 构造方法
FileWriter(File file): 通过File对象创建文件字符输出流
FileWriter(String fileName): 通过文件路径创建文件字符输出流
作用:
1. 创建FileWriter对象
2. 根据构造方法中的路径, 在磁盘上创建文件 ("如果文件已存在, 则清空文件内容")
3. 将FileWriter对象指向磁盘上的文件

字符输出流: 一次写一个字符
void write(int c): 写一个字符 (int类型为了代码编写方便)
FileWriter使用步骤:
1.创建FileWriter对象, 构造方法中绑定要写入数据的目的地
2.使用FileWriter中的方法 write(), 把数据写入到"内存缓冲区"中(字符转换为字节的过程)
3.使用FileWriter中的方法 flush(), 把内存缓冲区中的数据,"刷新到文件中"
4.释放资源 close() (会先把内存缓冲区中的数据刷新到文件中)
方法:
[Java] 纯文本查看 复制代码
FileWriter fw = new FileWriter("09_IOAndProperties\\d.txt");
fw.write(97); // int ch 用int值代表char
//fw.flush();
fw.close();

字符输出流: flush与close区别
区别:
        flush(): 刷新缓冲区 (将数据从内存中写入到磁盘)
        close(): 刷新缓冲区, 并释放资源. 关闭流后不能再用同一个流对象操作
flush()可以省略, 只用close()来刷新并释放资源
字符输出流: 其他方法
[Java] 纯文本查看 复制代码
写的其他方法:
void write(char[] cbuf): 写一个字符数组
abstract void write(char[] b, int off, int len): 写一个字符数组的一部分
void write(String str): 写一个字符串
void write(String str, int off, int len): 写一个字符串的一部分

字符输出流: 续写和换行
方法:
[Java] 纯文本查看 复制代码
FileWriter中带有续写功能的构造:
FileWriter(File file, boolean append): 通过File对象创建文件字符输出流. 第二个参数为true可以续写
FileWriter(String fileName, boolean append): 通过文件路径创建文件字符输出流. 第二个参数为true可
以续写
换行:
windows: "\r\n"直接写入

IO流操作中的异常处理
[Java] 纯文本查看 复制代码
JDK 7 增加的 "try-with-resource"
省略了 finally, 可自动释放资源
// 格式
try (创建流对象语句,如果多个,使用';'隔开) {
// 读写数据
} catch (IOException e) {
e.printStackTrace();
}
// 示例
try (FileWriter fw = new FileWriter("fw.txt");FileReader fr = new FileReader("fr.txt")) {
// IO操作
int ch = fr.read();
fw.write(ch);
} catch (IOException e) {
e.printStackTrace();
}
JDK 9 对于"try-with-resource"的改进:
流对象的声明和创建可以放在括号外面
流对象要求是有效final的.(即不要修改流对象的值)
FileWriter fw = new FileWriter("fw.txt");
FileReader fr = new FileReader("fr.txt");
try (fw; fr) {
// IO操作
int ch = fr.read();
fw.write(ch);
} catch (IOException e) {
e.printStackTrace();
}

Properties存储数据和遍历
方法:
[AppleScript] 纯文本查看 复制代码
java.util.Properties类: 属性集, 属于Map的双列集合, 继承自Hashtable
// 构造方法
Properties(): 创建一个Properties集合
// 可以使用Map接口中的方法
// 特有成员方法
Object setProperty(String key, String value): 保存/替换键值对
String getProperty(String key): 通过键获取值. 键不存在返回null
Set<String> stringPropertyNames(): 返回键的集合
void store(OutputStream out, String comments): 将集合数据用字节流写入文件(不能中文), 并写入注释
void store(Writer writer, String comments): 将集合数据用字符流写入文件(可以中文), 并写入注释
void load(InputStream inStream): 从配置文件中通过字节流加载数据到Properties集合(不能读中文)
void load(Reader reader): 从配置文件中通过字符流加载数据到Properties集合(可以读中文)

Properties: store()存储数据到文件
方法:
Properties将数据写入到文件的方法:
void store(OutputStream out, String comments): 将集合数据用字节流写入文件(不能中文), 并写入注释
void store(Writer writer, String comments): 将集合数据用字符流写入文件(可以中文), 并写入注释
使用步骤:
1.创建Properties集合对象,添加数据
2.创建字节输出流/字符输出流对象,构造方法中绑定要输出的目的地
3.使用Prop
Properties: load()从文件加载数据到集合
Properties将数据从文件加载到集合中的方法:
void load(InputStream inStream): 从配置文件中通过字节流加载数据到Properties集合(不能读中文)
void load(Reader reader): 从配置文件中通过字符流加载数据到Properties集合(可以读中文)
使用步骤:
1.创建Properties集合对象
2.使用Properties集合对象中的方法load读取保存键值对的文件
3.遍历Properties集合
Day10缓冲流 转换流 序列化流 打印流
缓冲流
缓冲流的原理: 底层也是使用基本流(FileXxx)来读写但缓冲流内部定义了一个缓冲数组, 在读的时候类似于我们一次读一个数组的方式, 减少了磁盘操作次数, 提高了程序效率;
缓冲字节输出流: BufferedOutputStream
java.io.BufferedOutputStream类:
缓冲字节输出流// 构造方法BufferedOutputStream(OutputStream out): 使用基本流创建一个缓冲字节输出流BufferedOutputStream(OutputStream out, int size): 使用基本流创建一个缓冲字节输出流, 设置缓冲区大小
BufferedOutputStream使用步骤:
1.创建FileOutputStream对象, 构造方法中绑定要输出的目的地
2.创建BufferedOutputStream对象, 构造方法中传递FileOutputStream对象, 提高FileOutputStream效率
3.使用BufferedOutputStream对象中的方法 write(), 把数据写入到内部缓冲区中
4.使用BufferedOutputStream对象中的方法 flush(), 把内部缓冲区中的数据,刷新到文件中
5.释放资源(会先调用flush方法刷新数据, 第4步可以省略)
FileOutputStream fos = new FileOutputStream("文件路径");
BufferedOutputStream bos = new BufferedOutputStream(fos);
bos.write("你好".getBytes());
// bos.flush(); // 可以省略
bos.close();
缓冲字节输入流: BufferedInputStream
java.io.BufferedInputStream类: 缓冲字节输入流
// 构造方法
BufferedInputStream(InputStream in): 使用基本流创建一个缓冲字节输入流
BufferedInputStream(InputStream in, int size): 使用基本流创建一个缓冲字节输入流, 设置缓冲区大小
使用步骤:
1.创建FileInputStream对象, 构造方法中绑定要读取的数据源
2.创建BufferedInputStream对象, 构造方法中传递FileInputStream对象, 提高FileInputStream效率
3.使用BufferedInputStream对象中的方法 read(), 读取文件
4.释放资源 close()
[Java] 纯文本查看 复制代码
FileInputStream fis = new FileInputStream("文件路径");
BufferedInputStream bis = new BufferedInputStream(fis);
byte[] bytes = new byte[1024];
int len;
while ((len = bis.read(bytes)) != -1) {
System.out.println(new String(bytes, 0, len));
}
bis.close();

缓冲字符输出流: BufferedWriter
方法:
[Java] 纯文本查看 复制代码
java.io.BufferedWriter类:
// 构造方法
BufferedWriter(Writer out): 使用基本流创建一个缓冲字符输出流
BufferedWriter(Writer out, int size): 使用基本流创建一个缓冲字符输出流, 设置缓冲区大小
// 特有方法
void newLine(): 写入一个换行符, 换行符自动根据当前系统确定

缓冲字符输入流: BufferedReader
方法:
[Java] 纯文本查看 复制代码
java.io.BufferedReader类: 缓冲字符输入流
// 构造方法
BufferedReader(Reader in): 使用基本流创建一个缓冲字符输入流
BufferedReader(Reader in, int size): 使用基本流创建一个缓冲字符输入流, 设置缓冲区大小
// 特有方法
String readLine(): 一次读一行字符串, "不包含换行符". 读到文件末尾返回null

转换流
字符编码和字符集
字符集包含编码表
ASCII字符集
         ASCII编码表
ISO-8859-1字符集:
        Latin-1: 拉丁字符. 没有中文. 每个字符由1个byte组成
GB字符集
        GB2312编码表: 每个字符由2个byte组成
        GBK编码表: 每个字符由2个byte组成
        GB18030编码表: 每个字符由1, 2, 4个byte组成
Unicode
        UTF-8: ASCII字符占1个byte, 拉丁字符占2个byte, 中文占3个byte, 辅助字符占4个byte
        UTF-16
        UTF-32ANSI: 表示使用系统默认编码表
ANSI: 表示使用系统默认编码表
乱码问题: FileReader读取GBK编码
乱码原因: 读写编码不一致GBK文件中存储的是"你好"在GBK中对应的byte而IDEA中使用FileReader读取文件时, 是将byte按照UTF-8编码表查找字符, 结果找不到, 就显示了问号
OutputStreamWriter类介绍及使用
方法:
[Java] 纯文本查看 复制代码
java.io.OutputStreamWriter类: 输出转换流. 字符流通往字节流的桥梁
// 构造方法
OutputStreamWriter(OutputStream out): 使用默认编码表创建转换流
OutputStreamWriter(OutputStream out, String charsetName): 使用指定编码表创建转换流
write('a') -> "GBK" -> 97 OutputStream out -> 文件
// 使用默认UTF-8
OutputStreamWriter o = new OutputStreamWriter(new FileOutputStream("a.txt"));
// 使用指定的GBK
OutputStreamWriter o = new OutputStreamWriter(new FileOutputStream("a.txt"), "GBK");
o.write("你") -> GBK -> 7676 -> 文件
写数据: 字符流 -------> 字节流



InputStreamReader类介绍及使用
方法:
[Java] 纯文本查看 复制代码
java.io.InputStreamReader类: 输入转换流. 字节流通往字符流的桥梁
// 构造方法
InputStreamReader(InputStream in): 使用默认编码表创建转换流
InputStreamReader(InputStream in, String charsetName): 使用指定编码表创建转换流
// 使用默认UTF-8
InputStreamReader r = new InputStreamReader(new FileInputStream("a.txt"));
// 使用指定的GBK
InputStreamReader r = new InputStreamReader(new FileInputStream("a.txt"), "GBK");
bbb int ch = r.read() <------GBK- 字节byte 989898
r.read(chs)
读数据: 字符流 <------ 字节流



序列化和反序列化概述
序列化: 内存中的对象转换为字节序列, 以流的方式写入到磁盘的文件中对象转字节
反序列化: 磁盘文件中的字节序列, 以流的方式读取到内存中变成对象字节转对象
通过序列化流, 我们可以将内存中的数据方便的存储到磁盘上, 下次程序启动后也能从磁盘读取恢复之前的对象状态


对象序列化流: ObjectOutputStream
方法:

[Java] 纯文本查看 复制代码
java.io.ObjectOutputStream类: 对象字节输出流
// 构造方法
ObjectOutputStream(OutputStream out)
// 特有成员方法
void writeObject(Object obj): 将对象写出
// 创建对象输出流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("student.txt"));
// 写对象
Student s = new Student("小美女", 18);
oos.writeObject(s);
// 释放资源
oos.close();

注意:被读写的对象的类, 必须实现 java.io.Serializable 接口, 否则会抛出 NotSerializableException该类的所有属性也都必须是可序列化的. (实现 java.io.Serializable 接口)如果某个属性不需要序列化, 则需要用 transient 修饰为瞬态的如果要将集合序列化, 那么集合中存储的对象也必须是可序列化的


对象反序列化流: ObjectInputStream
方法:
[Java] 纯文本查看 复制代码
java.io.ObjectInputStream类: 对象字节输入流
// 构造方法
ObjectInputStream(InputStream in)
// 特有成员方法
Object readObject(): 读取对象
// 创建对象输入流
ObjectInputStream oos = new ObjectInputStream(new FileInputStream("student.txt"));
// 读对象
Object o = oos.readObject();
Student s = (Student)o;
System.out.println(s);

// 释放资源
oos.close();



transient瞬态关键字: 避免属性序列化
static 修饰的成员变量属于类不属于对象, 所以不能序列化transient 修饰的成员变量, 不能被序列化如果对象的某个属性不希望被序列化, 可以使用transient修饰, 这样就不会被对象流写到文件中


InvalidClassException异常: 原因和解决方案
serialVersionUID序列号的作用:序列化操作时, 会根据类生成一个默认的 serialVersionUID 属性, 写入到文件中.该版本号是根据类中成员计算出来的一个数值. 当类的成员发生改变时, 序列版本号也会发生变化当代码中的类和读取的对象序列版本号不一致时, 就会抛出InvalidClassException


打印流PrintStream: 概述和使用
PrintStream特点:1. 只有输出流, 没有输入流2. PrintStream永远不会抛出IOException3. 有特殊方法 print(), println(), 可以输出任意类型的值
[Java] 纯文本查看 复制代码
java.io.PrintStream类: 字节打印流
// 构造方法
PrintStream(File file): 创建字节打印流, 输出到一个文件
PrintStream(OutputStream out): 创建字节打印流, 输出到一个字节输出流
PrintStream(String fileName): 创建字节打印流, 输出到一个文件路径
注意事项:
如果用 write() 方法, 会查编码表
如果用 print(), println(), 则原样输出
java.lang.System类:
// 静态方法
static void setOut(PrintStream out): 设置System.out的输出目的地为参数的打印流



















作者: 雨后光    时间: 2018-8-7 23:37
看总结贴当复习,很棒!




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2