• Java学习笔记(二十四)


    在完成对C语言的学习后,我最近开始了对C++和Java的学习,目前跟着视频学习了一些语法,也跟着敲了一些代码,有了一定的掌握程度。现在将跟着视频做的笔记进行整理。本篇博客是整理Java知识点的第二十四篇博客。

    本篇博客介绍了Java的字符流

    本系列博客所有Java代码都使用IntelliJ IDEA编译运行,版本为2022.1。所用JDK版本为JDK11

    目录

    字符流

    出现字符流的原因

    编码表

    字符串的编码解码问题

    字符流的编码解码问题

    字符流写数据的五种方式

    字符流读数据的二种方式

    字符流复制Java文件

    字符缓冲流

    字符缓冲流特有功能

    IO流小结


    字符流

    出现字符流的原因

    字节流操作中文等语言不是特别方便,因此提供了字符流。字符流 = 字节流 + 编码表

    字节流复制文件出现中文时,结果没有问题,因为最终底层操作通过编码表自动拼接成中文。

    编码表

    计算机存储的信息都是二进制表示的,屏幕上的内容都是进行了转换的结果。

    按照某种规则,将字符存储到计算机中,称为编码。将存储到计算机中的二进制数按照某种规则解析显示出来,就是解码。使用哪种码进行编码,就使用哪种码进行解码,否则会出现乱码。

    字符编码是字符与数字的对应规则。

    字符集是系统支持的所有字符的集合,包括各国语言文字,标点符号,数字等。计算机要准确存储各种字符集符号,就要进行字符编码,常见的有ASCII字符集,GBXXX字符集,Unicode字符集等。

    ASCII码是美国信息交换标准代码,基于拉丁字母,用于显示现代英语。包括控制字符和可显示字符(大小写,数字,英文符号等)。

    GB2312是信息交换用汉字编码字符集。用两个字节表示一个汉字。组合了7000多个简体汉字,并兼容ASCII码。

    GBK是汉字内码扩展规范,是最常用的中文码表,在GB2312的标准上进行扩展。收录了2万多个汉字,兼容GB2312,支持繁体汉字。

    GB18030是信息技术 中文编码字符集,收录超过7万个汉字,用多字节编码,每个字可以有1个,2个或4个字节组成。支持繁体字和我国少数民族文字。

    Unicode字符集是为了表达任意语言的任意字符设计的,称为统一码。最多4个字节来表示每个字母,符号,文字。有UTF-8,UTF-16和UTF-32三种方案,最常用的是UTF-8。

    UTF-8编码可以表示Unicode标准中的任意字符。所有互联网协议都支持UTF-8编码。使用1-4个字节编码。128个ASCII码字符使用一个字节,拉丁文等字符使用两个字节,大部分常用字,包括中文,使用三个字节,极少使用的用四个字节。

    字符串的编码解码问题

    byte[] getBytes()使用平台的默认字符集将String编码,结果存至byte数组中。

    byte[] getBytes(String charsetName)使用指定字符集将String编码,结果存至byte数组中。

    String(byte[] bytes)使用默认字符集解码指定的字节数组。

    String(byte[] bytes,String charsetName)通过指定字符集解码指定的字节数组。

    本机使用IDEA所用编码为UTF-8。

    1. import java.io.UnsupportedEncodingException;
    2. public class codetest1 {
    3. public static void main(String[] args) throws UnsupportedEncodingException {
    4. String s = "奥运会";
    5. byte[] byte1 = s.getBytes();
    6. System.out.println(new String(byte1));
    7. System.out.println(new String(byte1,"GBK"));
    8. byte[] byte2 = s.getBytes("GBK");
    9. System.out.println(new String(byte2));
    10. System.out.println(new String(byte2,"GBK"));
    11. }
    12. }

    程序的输出是:

    奥运会
    濂ヨ繍浼�
    ���˻�
    奥运会

    字符流的编码解码问题

    Reader是字符输入流的抽象类。Writer是字符输出流的抽象类。

    字符流中和编码解码问题相关的输入类是InputStreamReader,相关输出类是OutputStreamWriter

    使用这两个类也要导包,import java.io.InputStreamReaderimport java.io.OutputStreamWriter。

    1. import java.io.*;
    2. public class codetest2 {
    3. public static void main(String[] args) throws IOException {
    4. OutputStreamWriter osw1 = new OutputStreamWriter(new FileOutputStream("test3.txt"),"UTF-8");
    5. osw1.write("上午和下午");
    6. osw1.close();
    7. OutputStreamWriter osw2 = new OutputStreamWriter(new FileOutputStream("test3.txt",true),"GBK");
    8. osw2.write("上午和下午");
    9. osw2.close();
    10. InputStreamReader isr1 = new InputStreamReader(new FileInputStream("test3.txt"),"UTF-8");
    11. int ch;
    12. while((ch = isr1.read()) != -1){
    13. System.out.print((char)ch);
    14. }
    15. System.out.println();
    16. isr1.close();
    17. InputStreamReader isr2 = new InputStreamReader(new FileInputStream("test3.txt"),"GBK");
    18. while((ch = isr2.read()) != -1){
    19. System.out.print((char)ch);
    20. }
    21. System.out.println();
    22. isr2.close();
    23. }
    24. }

    程序使用OutputStreamWriter以UTF-8和GBK向文件中写入上午和下午。随后使用InputStreamReader从文件中以UTF-8和GBK的方式读入。

    程序的输出是:

    上午和下午���������
    涓婂崍鍜屼笅鍗埳衔绾拖挛�
    test3.txt的内容是:

    涓婂崍鍜屼笅鍗埳衔绾拖挛?

    字符流写数据的五种方式

    void write(int c)写入一个字符,ASCII码值为c。

    void write(char[] cbuf)写入一个字符数组。

    void write(char[] cbuf,int off,int len)将cbuf从off开始的len个字符写入。

    void write(String str)写入一个字符串。

    void write(String str,int off,int len)将str从off开始的len个字符写入。

    flush()刷新流,将数据保存,之后还可以继续写入数据。

    close()关闭流,释放资源。关闭前会刷新,关闭后无法继续写数据。

    1. import java.io.*;
    2. public class writetest6 {
    3. public static void main(String[] args) throws IOException {
    4. OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("test3.txt"));
    5. osw.write(50);
    6. char[] ch = new char[]{'a','b','c','d','e'};
    7. osw.write(ch);
    8. osw.write(ch,2,2);
    9. osw.write("北京冬奥会");
    10. osw.write("Beijing 2022",2,3);
    11. osw.close();
    12. }
    13. }

    程序无输出,文件中的内容是:

    2abcdecd北京冬奥会iji

    字符流读数据的二种方式

    int read()一次读一个字符数据,并将其码值返回。

    int read(char[] cbuf)一次读一个字符数组数据,并返回读取的字符数量。

    读到文件结尾后都返回-1。

    1. import java.io.*;
    2. public class readtest3 {
    3. public static void main(String[] args) throws IOException {
    4. InputStreamReader isr1 = new InputStreamReader(new FileInputStream("test3.txt"));
    5. int ch;
    6. while((ch = isr1.read()) != -1){
    7. System.out.print((char)ch);
    8. }
    9. System.out.println();
    10. isr1.close();
    11. InputStreamReader isr2 = new InputStreamReader(new FileInputStream("test3.txt"));
    12. char[] chr = new char[1024];
    13. int len;
    14. while((len = isr2.read(chr)) != -1){
    15. System.out.println(new String(chr, 0, len));
    16. }
    17. isr2.close();
    18. }
    19. }

    程序的输出是:

    2abcdecd北京冬奥会iji
    2abcdecd北京冬奥会iji

    字符流复制Java文件

    字符流的名字比较长,我们通常使用本地默认编码。因此Java提供了对应子类。

    FileReader用于读取字符文件,构造方法为FileReader(String fileName),需要导包,import java.io.FileReader

    FileWriter用于写入字符文件,构造方法为FileWriter(String fileName),需要导包,import java.io.FileWriter

    1. import java.io.*;
    2. public class readwritetest2 {
    3. public static void main(String[] args) throws IOException {
    4. FileReader fr = new FileReader("pokertest2.Java");
    5. FileWriter fw = new FileWriter("pokertest3.Java");
    6. char[] chs = new char[1024];
    7. int len;
    8. while((len = fr.read(chs)) != -1){
    9. fw.write(chs,0,len);
    10. }
    11. fr.close();
    12. fw.close();
    13. }
    14. }

    同样使用两个流处理,一个读一个写。程序无输出。由于内容太长,就不再展示,复制成功。

    字符缓冲流

    BufferedWriter将文本写入字符输出流,缓冲字符以提供高效写入。可以指定缓冲区大小,或者使用默认大小。默认值足够大。需要导包,import java.io.BufferedWriter。构造方法是:

    BufferedWriter(Writer out)

    BufferedReader从字符输入流读取文本,缓冲字符以提供高效读取。可以指定缓冲区大小或使用默认大小,默认值足够大。需要导包,import java.io.BufferedReader。构造方法是:

    BufferedReader(Reader in)

    1. import java.io.*;
    2. public class buffertest2 {
    3. public static void main(String[] args) throws IOException {
    4. BufferedWriter bw = new BufferedWriter(new FileWriter("test3.txt"));
    5. bw.write(97);
    6. bw.write(98);
    7. bw.write(99);
    8. bw.write(100);
    9. bw.write(10);
    10. bw.write("Hello Java");
    11. bw.write("\n");
    12. bw.close();
    13. BufferedReader br = new BufferedReader(new FileReader("test3.txt"));
    14. char[] chr = new char[1024];
    15. int len = 0;
    16. while((len = br.read(chr)) != -1){
    17. System.out.print(new String(chr, 0, len));
    18. }
    19. br.close();
    20. }
    21. }

    程序先向一个文件中写数据,然后从这个文件中读数据。

    程序的输出是:

    abcd
    Hello Java

    文件操作也成功。

    字符缓冲流特有功能

    BufferedWriter的void newLine()进行换行。

    BufferedReader的public String readLine()读一行文字,将结果返回。结果不包含换行符,到末尾后返回null。

    1. import java.io.*;
    2. public class bufferreadwrite {
    3. public static void main(String[] args) throws IOException {
    4. BufferedWriter bw = new BufferedWriter(new FileWriter("test3.txt"));
    5. bw.write("Hello Java");
    6. bw.newLine();
    7. bw.write("2022 07 18");
    8. bw.newLine();
    9. bw.write("After 17");
    10. bw.newLine();
    11. bw.write("This is in JDK11");
    12. bw.close();
    13. BufferedReader br = new BufferedReader(new FileReader("test3.txt"));
    14. String s;
    15. while((s = br.readLine()) != null){
    16. System.out.println(s);
    17. }
    18. br.close();
    19. }
    20. }

    程序同样先向一个文件写数据,然后从这个文件中读数据。

    程序的输出是:

    Hello Java
    2022 07 18
    After 17
    This is in JDK11

    文件内容也成功改变。

    1. import java.io.*;
    2. public class buffertest3 {
    3. public static void main(String[] args) throws IOException {
    4. BufferedWriter bw = new BufferedWriter(new FileWriter("pokertest3.java"));
    5. BufferedReader br = new BufferedReader(new FileReader("pokertest2.java"));
    6. String s;
    7. while((s = br.readLine()) != null){
    8. bw.write(s);
    9. bw.newLine();
    10. }
    11. bw.close();
    12. br.close();
    13. }
    14. }

    可以据此改进复制Java文件的程序,程序复制成功。

    IO流小结

    字节流分为字节输入流InputStream和字节输出流OutputStream。InputStream包括FileInputStreamBufferedInputStream。OutputStream包括FileOutputStreamBufferedOutputStream

    字符流包括字符输入流Reader和字符输出流Writer。Reader包括InputStreamReaderBufferedReader,InputStreamReader包括FileReader。Writer包括OutputStreamWriterBufferedWriter,OutputStreamWriter包括FileWriter

    一般使用字节缓冲流和字符缓冲流。另外,IO流的名字容易混。

  • 相关阅读:
    服务器硬件基础知识:从零开始了解你的数字工作马
    CAN测量模块总线负载率,你关注了吗?
    linux之权限管理命令
    因软件缺陷,736名员工被起诉,超40人被送进监狱
    Lab: Xv6 and Unix utilities
    2.4 赋值
    面试 - 对象的扩展方法
    认识WebSocket 以及怎么使用WebSocket
    ESP8266-Arduino编程实例-RFID-RC522模块驱动
    面向过程词条
  • 原文地址:https://blog.csdn.net/m0_71007572/article/details/126408122