目录
前言
1.字符流
1.1?为什么会出现字符流
1.2?编码表
1.3 编码解码问题
1.3.1?字符串中的编码解码问题
1.3.2?字符流中的编码解码问题
1.4 字符流读写数据的方式
1.4.1?字符流写数据的5种方式
1.4.2?字符流读数据的2种方式
1.5 字符流案例——复制Java文件
1.5.1?字符流复制Java文件
1.5.2?字符流复制Java文件改进版
2.字符缓冲流
2.1?字符缓冲流概述
2.2?字符缓冲流特有功能复制Java文件
3.IO流小结及常见面试题
3.1?IO流小结
3.2 常见面试题
前言
????????上一期博客当中,给大家简要分享了下Java IO流中的File类和字节流,这期博客我将给大家介绍Java IO流中剩下的最后一个重要的流:字符流。字符流的出现主要是为了解决字节流传输中文以及其他不常用符号数据后发生乱码的问题。所以字符流也是比较重要的一个IO流,大家一定要熟练掌握!
1.字符流
1.1?为什么会出现字符流
-
字符流的介绍 由于字节流操作中文不是特别的方便,可能会出现乱码的情况,所以Java就提供字符流。 字符流 = 字节流 + 编码表(字符流的底层最终还是要通过字节流来传输数据,但是它会根据默认或指定编码表将字符编码成字节或者将字节解码成可读字符。) -
中文的字节存储方式 用字节流复制文本文件时,文本文件也会有中文,但是没有问题,原因是最终底层操作会自动进行字节拼接成中文,如何识别是中文的呢? 汉字在存储的时候,无论选择哪种编码存储,第一个字节都是负数。
1.2?编码表
1.3 编码解码问题
1.3.1?字符串中的编码解码问题
-
相关方法
方法名 | 说明 |
---|
byte[] getBytes() | 使用平台的默认字符集将该 String编码为一系列字节 | byte[] getBytes(String charsetName) | 使用指定的字符集将该 String编码为一系列字节 | String(byte[] bytes) | 使用平台的默认字符集解码指定的字节数组来创建字符串 | String(byte[] bytes, String charsetName) | 通过指定的字符集解码指定的字节数组来创建字符串 |
-
代码演示
public class StringDemo {
public static void main(String[] args) throws UnsupportedEncodingException {
//定义一个字符串
String s = "中国";
//byte[] bys = s.getBytes(); //[-28, -72, -83, -27, -101, -67]
//byte[] bys = s.getBytes("UTF-8"); //[-28, -72, -83, -27, -101, -67]
byte[] bys = s.getBytes("GBK"); //[-42, -48, -71, -6]
System.out.println(Arrays.toString(bys));
//String ss = new String(bys);
//String ss = new String(bys,"UTF-8");
String ss = new String(bys,"GBK");
System.out.println(ss);
}
}
1.3.2?字符流中的编码解码问题
????????由于每个平台所使用的默认编码表可能不一样,因此在不同平台之间传输展示字符数据时可能会出现乱码的情况。解决办法就是使用下面将介绍的两个类来指定字符集进行编码和解码。
public class ConversionStreamDemo {
public static void main(String[] args) throws IOException {
//OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("myCharStream\\osw.txt"));
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("myCharStream\\osw.txt"),"GBK");
osw.write("中国");
osw.close();
//InputStreamReader isr = new InputStreamReader(new FileInputStream("myCharStream\\osw.txt"));
InputStreamReader isr = new InputStreamReader(new FileInputStream("myCharStream\\osw.txt"),"GBK");
//一次读取一个字符数据
int ch;
while ((ch=isr.read())!=-1) {
System.out.print((char)ch);
}
isr.close();
}
}
1.4 字符流读写数据的方式
1.4.1?字符流写数据的5种方式
public class OutputStreamWriterDemo {
public static void main(String[] args) throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("myCharStream\\osw.txt"));
//void write(int c):写一个字符
// osw.write(97);
// osw.write(98);
// osw.write(99);
//void writ(char[] cbuf):写入一个字符数组
char[] chs = {'a', 'b', 'c', 'd', 'e'};
// osw.write(chs);
//void write(char[] cbuf, int off, int len):写入字符数组的一部分
// osw.write(chs, 0, chs.length);
// osw.write(chs, 1, 3);
//void write(String str):写一个字符串
// osw.write("abcde");
//void write(String str, int off, int len):写一个字符串的一部分
// osw.write("abcde", 0, "abcde".length());
osw.write("abcde", 1, 3);
//释放资源
osw.close();
}
}
1.4.2?字符流读数据的2种方式
-
方法介绍
方法名 | 说明 |
---|
int read() | 一次读一个字符数据 | int read(char[] cbuf) | 一次读一个字符数组数据 |
-
代码演示
public class InputStreamReaderDemo {
public static void main(String[] args) throws IOException {
InputStreamReader isr = new InputStreamReader(new FileInputStream("myCharStream\\ConversionStreamDemo.java"));
//int read():一次读一个字符数据
// int ch;
// while ((ch=isr.read())!=-1) {
// System.out.print((char)ch);
// }
//int read(char[] cbuf):一次读一个字符数组数据
char[] chs = new char[1024];
int len;
while ((len = isr.read(chs)) != -1) {
System.out.print(new String(chs, 0, len));
}
//释放资源
isr.close();
}
}
1.5 字符流案例——复制Java文件
1.5.1?字符流复制Java文件
public class CopyJavaDemo01 {
public static void main(String[] args) throws IOException {
//根据数据源创建字符输入流对象
InputStreamReader isr = new InputStreamReader(new FileInputStream("myCharStream\\ConversionStreamDemo.java"));
//根据目的地创建字符输出流对象
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("myCharStream\\Copy.java"));
//读写数据,复制文件
//一次读写一个字符数据
// int ch;
// while ((ch=isr.read())!=-1) {
// osw.write(ch);
// }
//一次读写一个字符数组数据
char[] chs = new char[1024];
int len;
while ((len=isr.read(chs))!=-1) {
osw.write(chs,0,len);
}
//释放资源
osw.close();
isr.close();
}
}
1.5.2?字符流复制Java文件改进版
public class CopyJavaDemo02 {
public static void main(String[] args) throws IOException {
//根据数据源创建字符输入流对象
FileReader fr = new FileReader("myCharStream\\ConversionStreamDemo.java");
//根据目的地创建字符输出流对象
FileWriter fw = new FileWriter("myCharStream\\Copy.java");
//读写数据,复制文件
// int ch;
// while ((ch=fr.read())!=-1) {
// fw.write(ch);
// }
char[] chs = new char[1024];
int len;
while ((len=fr.read(chs))!=-1) {
fw.write(chs,0,len);
}
//释放资源
fw.close();
fr.close();
}
}
2.字符缓冲流
2.1?字符缓冲流概述
-
字符缓冲流介绍
-
构造方法
方法名 | 说明 |
---|
BufferedWriter(Writer out) | 创建字符缓冲输出流对象 | BufferedReader(Reader in) | 创建字符缓冲输入流对象 |
2.2?字符缓冲流特有功能复制Java文件
????????字符缓冲流除了可以使用字符流的方法外,它还可以使用自己特有的读写方法。字符缓冲流的特有功能使得读写变得非常方便,读写效率大大提高。
-
方法介绍 BufferedWriter:
方法名 | 说明 |
---|
void newLine() | 写一行行分隔符,行分隔符字符串由系统属性定义 |
BufferedReader:
方法名 | 说明 |
---|
String readLine() | 读一行文字。 结果包含行的内容的字符串,不包括任何行终止字符如果流的结尾已经到达,则为null |
public class CopyJavaDemo02 {
public static void main(String[] args) throws IOException {
//根据数据源创建字符缓冲输入流对象
BufferedReader br = new BufferedReader(new FileReader("myCharStream\\ConversionStreamDemo.java"));
//根据目的地创建字符缓冲输出流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("myCharStream\\Copy.java"));
//读写数据,复制文件
//使用字符缓冲流特有功能实现
String line;
while ((line=br.readLine())!=null) {
bw.write(line);
bw.newLine();
bw.flush();
}
//释放资源
bw.close();
br.close();
}
}
3.IO流小结及常见面试题
3.1?IO流小结
? ▲ 字节流
? ▲ 字符流
3.2 常见面试题
以下常见面试题参考链接:JavaIO流常见面试题 - pipizhou - 博客园
1.字节流和字符流哪个好?怎么选择?
- 大多数情况下使用字节流会更好,因为大多数时候 IO 操作都是直接操作磁盘文件,所以这些流在传输时都是以字节的方式进行的(图片等都是按字节存储的)。
- 如果对于操作需要通过 IO 在内存中频繁处理字符串的情况使用字符流会好些,因为字符流具备缓冲区,提高了性能。
2.什么是缓冲区?有什么作用?
- 缓冲区就是一段特殊的内存区域,很多情况下当程序需要频繁地操作一个资源(如文件或数据库)则性能会很低,所以为了提升性能就可以将一部分数据暂时读写到缓存区,以后直接从此区域中读写数据即可,这样就显著提升了性。
- 对于 Java 字符流的操作都是在缓冲区操作的,所以如果我们想在字符流操作中主动将缓冲区刷新到文件则可以使用 flush() 方法操作。
3.什么是Java序列化,如何实现Java序列化?
- 序列化就是一种用来处理对象流的机制,将对象的内容进行流化。可以对流化后的对象进行读写操作,可以将流化后的对象传输于网络之间。序列化是为了解决在对象流读写操作时所引发的问题。
- 序列化的实现:将需要被序列化的类实现Serialize接口,没有需要实现的方法,此接口只是为了标注对象可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,再使用ObjectOutputStream对象的write(Object obj)方法就可以将参数obj的对象写出。
4.流一般需不需要关闭,如果关闭的话用什么方法,一般要在哪个代码块里面关闭比较好,如果有多个流互相调用传入是怎么关闭的?
- 流一旦打开就必须关闭,使用close方法
- 放入finally语句块中(finally 语句一定会执行)
- 多个流互相调用只关闭最外层的流
????????关于Java IO流的主要内容博主就介绍到这里了,Java IO流中除了我讲的字节流、字符流之外还有一些特殊操作流,感兴趣的小伙伴可以自己去了解下哦!
|