- java将流按照读写单位划分位字节流与字符流
- 字节流的超类
- InputStream
- OutputStream
- 字符流的超类
- java.io.Reader
- java.io.Writer
- 这四个是平级关系
Reader 和 Writer是两个抽象类,里面规定了所有字符流都必须具备的读写字符的相关方法
字符流最小读写单位为字符(char),但是底层实际读写的还是读写字节,
只是字符与字节的转换工作由字符流完成
- 字符转换流:作用是用来连接低级流(比如文件流)用来做字节字符转换的
- InputStreamReader
- OutputStreamWriter
转换流:
java.io.InputStreamReader和OutputStreamWriter
他们是字符流非常常用的一对实现类,同时也是一对高级流,实际开发中我们不直接操作他们
但是,他们在流连接中是非常重要的一环
转换流的意义:
实际开发中我们还有功能更好的字符高级流,但是其他的字符高级流都有一个共同点
不能直接连接在字节流上。而实际操作设备的流都是低级流,同时也都是字节流,因此不能直接在流连接中
串联起来;
转换流是一对可以连接在字节流上的字符流;
其他的高级字符流可以连接在转换流上;
而转换流可以连接在字节流上,在流连接中起到“转换器”的作用(负责字符与字节的实际转换)
- 转换流写字符串,转换流指定编码格式
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("bos.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");
String s = "asdf";
char[] c = {'a','b','c'};
osw.write("可不可以,和你在一起");
osw.write("ke");
osw.write(c);
System.out.println("写出完毕");
osw.close();
}
- 转换字符流输入,可以将读取的字节按照指定的字符集转换为字符
public static void main(String[] args) throws IOException {
//将osw.txt文件中的所有文字读取回来
FileInputStream fis = new FileInputStream("./bos.txt");
//指定utf-8字符集
InputStreamReader isr = new InputStreamReader(fis,"utf-8");
/**
* 字符流读一个字符的read方法:
* int read()
* 读取一个字符,返回的int值实际上表示的是一个char(低16位的 Unicode 字符集)。如果返
* 回的int值表示的是-1,则说明EOF文件末尾
*/
int i = isr.read(); //int值实际上表示的是一个char 21487
System.out.println((char)i); //可
int c;
while ((c=isr.read())!=-1){
System.out.print((char)c); //可不可以,和你在一起keabc
}
isr.close();
}
- 字符流写数组用char数组
// 字符流完成文件复制 用char数组来接收
public static void main(String[] args) throws IOException {
InputStreamReader isr = new InputStreamReader(new FileInputStream("./b.txt"));
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("./c.txt"),"utf-8");
// 字符流写数据,一次写一组 用char数组来接收
char[] chs = new char[1024];
int len;
while ((len=isr.read(chs))!=-1){
osw.write(chs, 0, len);
osw.flush();
}
isr.close();
osw.close();
}
- 缓冲字符流:
- BufferedWriter
- BufferedReader
- 缓冲字符流内部有一个缓冲区,读写文本数据以块读写形式加快效率,并且缓冲流有一个特别的功能,可以按行读写文本数据
- java.io.PrintWriter具有自动换行刷新的缓冲字符输出流
- 实际开发中更常用,它内部总是会自动连接BufferedWriter作为块写加速使用
public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
//向文件中写入文本数据
/**
* pw 直接提供了方便向文件中写入数据的构造方法
* PrintWriter(String fileNmae)
* PrintWriter(File file)
* this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), charset)),
* false);
*/
PrintWriter pw = new PrintWriter("bat.txt","utf-8");
String str = "然后天空又再涌起密云";
pw.println(str);
str = "密云";
pw.println(str);
pw.close();
}
- 文件流--转换流--缓冲流字符流--缓冲字符输出流
- 在流连接中使用PrintWriter
- 提供了void println(str);实现写入自动换行
public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
//fos 会自动创建 文件,没有的话
FileOutputStream fos = new FileOutputStream("./1121.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");
BufferedWriter bw = new BufferedWriter(osw);
PrintWriter pw = new PrintWriter(bw);
String str = "夜空中最亮的星";
pw.println(str);
str = "点亮你的梦想";
pw.println(str);
pw.close();
}
- 读文件流--转换流--缓冲字符流
- 提供了String readLine();
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("./src/main/java/day06/BRDemo3.java");
InputStreamReader isr = new InputStreamReader(fis,"utf-8");
BufferedReader br = new BufferedReader(isr);
/**
* BufferedReader提供了一个读取一行字符串的方法
* String readLine()
* 该方法会返回一行字符串,返回的字符串不含有最后的换行符。
* 当某一行是空行时,该行内容只有一个换行符,则返回值为空字符串
* 如果流读取到了末尾,则返回值为null
*/
String line ;
while ((line = br.readLine())!=null){
System.out.println(line);
}
}
- 记事本
public static void main(String[] args) throws Exception{
System.out.println("请输入记事本的名字:");
Scanner scanner = new Scanner(System.in);
String txt = scanner.nextLine();
//文件流
FileOutputStream fos = new FileOutputStream("./"+txt+".txt");
//转换流字节 转 字符
OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");
//缓冲流
BufferedWriter bw = new BufferedWriter(osw);
//换行刷新
/**
* 重载构造方法,true 写入内容记事本被及时刷新
* 会自动调用flush方法
*/
PrintWriter pw = new PrintWriter(bw,true);
System.out.println("请输入记事本内容:");
while (true){
txt = scanner.nextLine();
if(!txt.equalsIgnoreCase("exit")){
pw.println(txt);
System.out.println();
}else {
System.out.println("记事本已生成!");
pw.close();
break;
}
}
}
- 字节流与字符流:
- 读写单位不同:
- 字符流以字符为单位,根据码表映射字符,一次可能读多个字节
- 字节流以字节(8bit)为单位
- 处理对象不同:
- 字符流只能处理字符类型的数据
- 字节流能处理所有类型的数据(字符、image、视频等)
- 处理纯文本数据,优先使用字符流
- 其余都使用字节流
- 读写单位不同:
- java异常捕获处理
- Throwable:java中所有的错误的超类;
- 旗下两个子类:
- Error
- Exception
- Error的子类描述的都是系统错误,比如虚拟机内存溢出等
- Exception的子类描述的都是程序错误,比如空指针异常、数组下标越界、类型转换一场等
- 通常我们程序中处理的异常都是Exception
- 注意:异常是从小到大定义的,不能是从大到小
- 即:catch 空指针,再catchException,不能倒过来
public static void main(String[] args) {
String str = null;
//当JVM执行代码出现错误时,就会实例化对应问题的异常实例,并找出出错的位置将其抛出
//遇到问题后会找到出错的代码,找到是哪个方法调用它的,就会把异常跑出去
try{
str = "a";
System.out.println(str.length());
System.out.println(str.charAt(1));
}catch (NullPointerException e){
System.out.println(e);
/**
* catch可以定义多个,针对try中不同异常由不同处理方式时,可以分别捕获并处理
*/
}catch (StringIndexOutOfBoundsException e){
System.out.println(e);
/**
* 通常一下情况我们可以捕获一个超类异常:
* 当try中出现了几种不同的异常,但是它们的解决办法相同时,我们可以catch他们
* 共同的超类异常
* 在最后一个catch出捕获Exception 可以避免因为一个未处理的异常导致程序中断
* 一旦错误,有错误的处理办法
*/
}catch(Exception e){
}
}
- 异常处理机制中的finally块
- finally块定义在异常处理机制中的最后一块。它可以直接跟在try之后,或者最后一个catch之后
- finally可以保证只要程序执行到了try语句块中,无论try语句块中的代码时否出现异常或者return;finally最终都会执行
- 通过finally用来做释放资源这类操作
- 标准的IO操作时异常处理机制如下
- 注意:关源时候也需要处理异常
public static void main(String[] args) {
//FileOutputStream必须定义在try前边
//如果在try里边,因为它的作用域在try里,出了try,就不认识了
//而资源释放标准是放在finall块里,因为最终肯定会被执行
//写在try里finally就不认识了,所以要放在外边
FileOutputStream fos = null;
try {
fos = new FileOutputStream("fos3.dat");
fos.write(1);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
//注意:如果fos = new FileOutputStream("fos.dat");报错了比如说拒绝访问
//fos 依旧等于null 此时关闭fos.close();会报空指针异常
//所以此处需要加上条件判断;
if(fos!=null){ //fos等于null的情况,调用close方法肯定会报空指针
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}