1.字节缓冲流
构造方法
BufferedInterStream:
BufferedOutputStream(OutputStream out) 创建一个新的缓冲输出流,以将数据写入指定的底层输出流。 |
---|
BufferedOutputStream(OutputStream out, int size) 创建一个新的缓冲输出流,以便以指定的缓冲区大小将数据写入指定的底层输出流。 |
BufferedOutputedStream:
BufferedInputStream(InputStream in) 创建一个 BufferedInputStream 并保存其参数,输入流 in ,供以后使用。 |
---|
BufferedInputStream(InputStream in, int size) 创建 BufferedInputStream 具有指定缓冲区大小,并保存其参数,输入流 in ,供以后使用。 |
BufferOutputStream 内部带有缓冲区,写数据的时候先写入缓冲区,缓冲区满后才会把缓冲区的内容写到磁盘中。用 flush 或 close 方法可使未满缓冲区的数据写入磁盘
flush 方法 只刷新缓冲流,不释放资源
close 方法 在关闭流,释放资源之前,会先刷新缓冲流
缓冲流构造方法只需要字节流的原因:
字节缓冲流仅提供缓冲区,真正读写数据还是要字节流的对象的操作
2 字符流
2.1 为什么出现字符流
字节流操作中文不是特别方便,因此出现了字符流
字符流 = 字节流 + 字符集
中文字节存储方式
用字节流复制文本时,最终底层操作会自动进行字节拼接成中文
如何识别中文
汉字在存储时,无论是哪种编码存储,第一个字节都是负数
2.2 字符串中的编码和解码的问题
编码:将字符转换成字节数组
方法:
byte[] | getBytes() 使用平台的默认字符集将此 String 编码为字节序列,将结果存储到新的字节数组中。 |
---|---|
byte[] | getBytes(String charsetName) 使用命名的字符集将此 String 编码为字节序列,将结果存储到新的字节数组中。 |
解码:将字节数组转换为字符
方法:
String | String(byte[] bytes, String charsetName) 构造一个新的String 由指定用指定的字节的数组解码[charset] 。 |
---|
编码和解码必须使用相同码表,否则会乱码
2.3 字符流中的编码问题
字符流的抽象基类:
Reader:字符输入流的抽象基类
Writer:字符输出流的抽象基类
字符流中和编码相关的类:
- InputStreamReader是从字节流到字符流的桥:它读取字节,并使用指定的
charset
将其解码为[字符] 。它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。 - OutputStreamWriter是字符的桥梁流以字节流:向其写入的字符编码成使用指定的字节
charset
。 它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。
构造方法:
InputStreamReader:
-
InputStreamReader(InputStream in)
创建一个使用默认字符集的InputStreamReader。 -
InputStreamReader(InputStream in, String charsetName)
创建一个使用命名字符集的InputStreamReader。
OutputStreamReader:
-
OutputStreamWriter(OutputStream out)
创建一个使用默认字符编码的OutputStreamWriter。 -
OutputStreamWriter(OutputStream out, String charsetName)
创建一个使用命名字符集的OutputStreamWriter。
2.4 字符流的读写方式
写:
void | write(char[] cbuf, int off, int len) 写入字符数组的一部分。 |
---|---|
void | write(int c) 写一个字符 |
void | write(String str, int off, int len) 写一个字符串的一部分。 |
void | write(String str) 写一个字符串 |
void | write(char[] cbuf) 写入一个字符数组。 |
读:
int | read() 读一个字符 |
---|---|
int | read(char[] cbuf, int offset, int length) 将字符读入数组的一部分。 |
int | read(char[] cbuf) 将字符读入数组。 |
刷新和关闭:
void | close() 关闭流,先刷新。 |
---|---|
void | flush() 刷新流。 |
字符流可用于纯文本文件复制
字符流自带缓冲区
2.5 字符流操作的便捷类
FileReader 是InputStreamReader的简洁形式
FileWrite 是OutputStreamReader的简洁形式
2.6 字符缓冲流
BufferedReader
从字符输入流读取文本,缓冲字符,以提供 字符,数组和行的高效读取。
可以指定缓冲区大小,或者可以使用默认大小。
BufferedReader(Reader in)创建使用默认大小输入缓冲区的缓冲字符输入流 |
---|
String | readLine() 读一行文字。 |
---|
BufferedWriter
将文本写入字符输出流,缓冲字符,以提供 单个字符,数组和字符串的高效写入。
可以指定缓冲区大小,或者可以接受默认大小。
BufferedWriter(Writer out) 创建使用默认大小的输出缓冲区的缓冲字符输出流。 |
---|
void | newLine() 写一行行分隔符。 |
---|
2.7 IO流小结
字节流可以复制文件数据,有四种方式,一般采用字节缓冲流一次写一个字节数组的形式
字节流
- 字节输入流(InputStream)
- 方法:read()、read(byte[] b)、read(byte[] b,int off ,int len)
- FileInputStream
- BufferedInputStream(缓冲)
- 字节输出流(OutputStream)
- 方法:write()、write(byte[] b)、write(byte[] b,int off ,int len)、
- FileOutputStream
- BufferedOutputStream(缓冲)
字符流
- 字符输入流(Reader)
- 方法:read()、read(char[] cbuf)、read(char[] cbuf, int offset, int length)
- InputStreamReader / FileReader(简式)
- BufferedReader(缓冲)
- 字符输出流(Writer)
- 方法:writer(int c)、writer(char[] cbuf)、writer(char[] cbuf,int off,int len)、writer(String str)、writer(String str,int off,int len)
- OutputStreamWriter / FileWriter(简式)
- BufferedWriter(缓冲)
3 标准输入输出流
static PrintStream | err “标准”错误输出流。 |
---|---|
static InputStream | in “标准”输入流。 默认指的键盘 |
static PrintStream | out “标准”输出流。 默认是屏幕 |
3.1 标准输入流
InputStream is = System.in; (字节流输入)
InputStreamReader isr = new InputStreamReader(is) (字节流转字符流)
3.2 标准输出流
PrintStream ps = System.out;
4 打印流
打印流可分为字节打印流(PrintStream)和字符打印流(PrintWtriter)
打印流特点:
只能输出数据,不能读取数据
有一些特有的方法
5 对象的序列化流
对象序列化:将对象保存到磁盘或在网络中传输对象,为了对象保存的正确性和传输的安全性,将对象进行编码处理,这种处理方法称之为对象的序列化
反序列化:将序列化的目标解析为原对象
-
ObjectOutputStream (序列化)
-
ObjectInputStream (反序列化)
对于对象传输,对象必须实现java.io.Serializable 接口
6 Porperties
Porperties 是Map集合的一个实现类
Porperties可以保存到流中或从流中加载
属性列表中的键和对应的值都是字符串
Porperties 和 IO 流结合的方法:
void | load(InputStream inStream) 从输入字节流读取属性列表(键和元素对)。 |
---|---|
void | load(Reader reader) 以简单的线性格式从输入字符流读取属性列表(关键字和元素对)。 |
void | store(OutputStream out, String comments) 将此属性列表(键和元素对)写入此 Properties 表中,以适合于使用 load(InputStream) 方法加载到 Properties 表中的格式输出流。 |
void | store(Writer writer, String comments) 将此属性列表(键和元素对)写入此 Properties 表中,以适合使用 load(Reader) 方法的格式输出到输出字符流。 |
7 多线程
7.1 进程 线程 程序
程序:为了完成特定任务,用某种语言编写的一组指令的集合。 是一个静态过程
进程:是程序的一次执行过程或正在运行的程序。是一个动态过程,有自身的产生、存在、消亡的过程,称之为生命周期。作为资源分配单位,系统在运行时会为每个进程分配不同的内存区域。
线程(thread):是进程的进一步细化,是程序内部的一条执行路径。
若一个进程同一时间执行多个线程,就是支持多线程。
线程作为调度和执行的单位,每个线程拥有独立的运行栈和程序计数器,线程的切换开销比较小。
一个进程的多个线程共享相同的内存单元和内存地址空间,从同一个堆中分配对象,可以访问相同的变量和对象,这使得线程间的通信变得简便高效。但多线程操作共享的系统资源可能会有安全隐患,如多个线程同时选择同一变量或对象。
单核CPU(伪多线程处理器)和多核CPU(多线程处理器)
java中,一个程序至少有三个线程,主线程(main)、垃圾回收线程(gc)、异常处理线程
并行和并发
- 并行:多个CPU同时执行多个任务
- 并发:一个CPU在同一时刻,同时处理多个任务
多线程优点:
- 提高应用程序的响应
- 提高计算机CPU的利用率
- 改善程序结构
何时需要多线程
- 程序要同时执行两个或多个任务时
- 程序有需要等待的任务时 如:用户输入、文件读写、网络操作等
- 需要后台运行的程序时
7.2 实现多线程
创建多线程的两种方法:
- 一个是将一个类声明为
Thread
的子类。 这个子类应该重写Thread的run方法 。 然后可以分配并启动子类的实例 - 另一种方法来创建一个线程是声明实现类
Runnable
接口。 那个类然后实现了run
方法。 然后可以分配类的实例,在创建Thread
时作为参数传递,并启动
7.2.1 实现线程的方式一 :继承Thread类
步骤:
- 自定义一个线程类,继承 Thread 类,并重写 run 方法
- 在 main 方法中创建线程对象,创建时对象指向自定义线程类
- 调用线程对象的 start 语句
为什么要重写 run 方法
因为 run 方法是用来封装被线程执行的代码
run 方法和 start 方法的区别
run() 封装了线程执行的代码,直接调用相当于普通方法调用
start() 启动线程,然后由JVM调用此线程的run方法
7.2.2 实现线程的方式二:实现Runnable接口
Runnable
接口应由任何类实现,其实例将由线程执行。 该类必须定义一个无参数的方法,称为run
步骤:
- 自定义一个线程类,实现 Runnable 接口,并重写 run 方法
- 在 main 方法中创建实现类对象,并将实现类对象作为创建的线程对象的形参
- 调用线程对象的 statr 语句
- 或者在创建线程对象时用匿名内部类实现接口
7.3 设置和获取线程的名称
Thread(String name) 分配一个新的 Thread 对象。 |
---|
void | setName(String name) 将此线程的名称更改为等于参数 name 。 |
---|---|
void | setName(String name) 将此线程的名称更改为等于参数 name 。 |
static Thread | currentThread() 返回对当前正在执行的线程对象的引用。 |
7.4 线程的优先级
int | getPriority() 返回此线程的优先级。 |
---|---|
void | setPriority(int newPriority) 更改此线程的优先级。 |
每个线程都有优先权,具有较高优先级的线程由于优先级较低的线程执行
线程的两种调度模型
- 分时调度:所有线程轮流实现CPU的使用权,平均分配每个线程占有CPU的时间片
- 抢占式调度:随机选择一个线程执行,优先度高的线程被选中的概率更高
java是抢占式的调度模型
线程默认优先级为5,优先级范围是1~10