• java基础---节点流


    节点流

    类型字符流字节流
    File文件FileReader、FileWriter
    FileInputStream FileOutputStream
    内存数组

    CharArrayReader、

    CharArrayWriter

    ByteArrayInputStream
    ByteArrayOutputStream
    内存字串StringReader、StringWriter
    管道
    PipedReader PipedWriter
    PipedInputStream PipedOutputStream

    文件节点流

    FileInputStream FileOutputStream 是文件字节流,是一种节点流
    文件字节输入流的构造方法:
    • FileInputStream("文件名称"),如果文件不存在则FileNotFoundException
    • FileInputStream(File)
    文件字节输出流的构造方法 :
    • FileOutputStream(“文件名称”) 如果文件不存在则新建文件,如果文件存在则覆盖文件内容
    • FileOutputStream(String name文件名称, boolean append是否采用追加方式)
    FileReader FileWriter 类似
    FileInputStream FileOutputStream 两个类属于结点流,第一个类的源端和第二个类的目的端都是磁盘文件,它们的构造方法允许通过文件的路径名来构造相应的流。
    如:
    FileInputStream infile = new FileInputStream("myfile.dat");
    FileOutputStream outfile = new FileOutputStream("results.dat");
    要注意的是,构造 FileInputStream, 对应的文件必须存在并且是可读的,而构造 FileOutputStream 时,如输出文件已存在,则必须是可覆盖的。

    需求: 将存储路径下的data/calcCharNum.txt拷贝到data/cal.txt

    1. package com.yan2;
    2. import java.io.File;
    3. import java.io.FileNotFoundException;
    4. import java.io.FileReader;
    5. import java.io.FileWriter;
    6. import java.io.IOException;
    7. import java.io.Reader;
    8. import java.io.Writer;
    9. /*
    10. * 文件节点流
    11. * 字节 FileInputStream和FileOutputStream
    12. *
    13. * 文件字节输入流的构造方法:
    14. * - FileInputStream("文件名称"),如果文件不存在则FileNotFoundException
    15. * - FileInputStream(File)
    16. * throws或者try/catch
    17. * 文件字节输出流的构造方法:
    18. * - FileOutputStream(“文件名称”) 如果文件不存在则新建文件,如果文件存在则覆盖
    19. * 文件内容
    20. * - FileOutputStream(String name文件名称, boolean append是否采用追加方式)
    21. *
    22. * FileReader和FileWriter类似
    23. * 字符 FileReader和FileWriter
    24. */
    25. public class Test1 {
    26. public static void main(String[] args) {
    27. File file = new File("data/calcCharNum.txt");
    28. if (file.exists()) {
    29. try (Reader r = new FileReader(file); Writer w = new FileWriter("data/cal.txt", true)) {
    30. char[] arr = new char[8192];
    31. int len = 0;
    32. while ((len = r.read(arr)) > 0) {
    33. w.write(arr, 0, len);
    34. }
    35. } catch (FileNotFoundException e) {
    36. e.printStackTrace();
    37. } catch (IOException e) {
    38. System.out.println("出问题了:" + e.getMessage());
    39. }
    40. }
    41. }
    42. }
    43. //构造输出文件流时可以使用两种不同的方式
    44. //OutputStream os=new FileOutputStream("e:\\dd.txt"); 如果文件不存在则自动创建;如果文件存在则进行覆盖
    45. //OutputStream os=new FileOutputStream("e:\\dd.txt",true),这里的boolean类型参数 表示是否采用追加的方式写入文件

    内存数组节点

    如果文本则使用 char[] ,如果二进制则使用 byte[]
    构造器方法
    • CharArrayReader(char[] buf)其中char[]就是数据的来源,也就是说Reader就是从char[]中读取数据
    • CharArrayRead(char[] buf, int offset, int length)
    CharArrayWriter 用于实现向一个字符数组中写入数据,这个数组可以自动调整大小
    ByteArrayInputStream ByteArrayOutputStream CharArrayReader 以及 CharArrayWriter 类似,支持操作的内容不同而已,操作byte[] char[]
    1. package com.yan2;
    2. import java.io.CharArrayReader;
    3. import java.io.CharArrayWriter;
    4. import java.io.Reader;
    5. import java.io.Writer;
    6. import java.util.Scanner;
    7. /*
    8. * 内存数组节点
    9. *
    10. * 如果文本则使用char[],如果二进制则使用byte[]
    11. *
    12. * 构造器方法
    13. * - CharArrayReader(char[] buf)其中char[]就是数据的来源,
    14. * 也就是说Reader就是从char[]中读取数据
    15. * - CharArrayRead(char[] buf, int offset, int length)
    16. *
    17. * CharArrayWriter用于实现向一个字符数组中写入数据,这个数组可以自动调
    18. * 整大小
    19. *
    20. * ByteArrayInputStream、ByteArrayOutputStream和CharArrayReader以及
    21. * CharArrayWriter类似,支持操作的内容不同而已,操作byte[]与char[]
    22. */
    23. public class Test2 {
    24. public static void main(String[] args) throws Exception {
    25. String str = "abc中国人民解放军123";
    26. char[] arr = str.toCharArray();
    27. Reader r = new CharArrayReader(arr);
    28. while (true) {
    29. int kk = r.read();
    30. if (kk == -1)
    31. break;
    32. System.out.println((char) kk);
    33. }
    34. System.out.println("键盘录入数据");
    35. Scanner sc = new Scanner(System.in);
    36. Writer w = new CharArrayWriter();
    37. while (true) {
    38. String ss = sc.nextLine();
    39. if ("quit".equals(ss))
    40. break;
    41. w.write(ss);
    42. }
    43. sc.close();
    44. // 需要使用CharArrayWriter中定义的特殊方法,获取输出的目标数组
    45. if (w instanceof CharArrayWriter) {
    46. CharArrayWriter caw = (CharArrayWriter) w;
    47. caw.append("dsuhsad");// 向输出的数组末尾添加内容 StringBuilder
    48. // 获取输出的目标数组
    49. char[] target = caw.toCharArray();
    50. System.out.println(new String(target));
    51. }
    52. }
    53. }
    54. //ByteArrayInputStream、ByteArrayOutputStream和CharArrayReader以及
    55. //CharArrayWriter类似,支持操作的内容不同而已,操作byte[]与char[]

    内存字串流

    StringReader用于从一个字串String中读取数据

    StringWriter用于给一个StringBuffer中写入数据,实现一个可变长的字串

    1. package com.yan2;
    2. import java.io.IOException;
    3. import java.io.Reader;
    4. import java.io.StringReader;
    5. import java.io.StringWriter;
    6. import java.io.Writer;
    7. /*
    8. *内存字串流
    9. * StringReader用于从一个字串String中读取数据
    10. *
    11. * StringWriter用于给一个StringBuffer中写入数据,实现一个可边长的字串
    12. */
    13. public class Test4 {
    14. public static void main(String[] args) throws IOException {
    15. String str = "中abc国人民解放军";
    16. Reader r = new StringReader(str);
    17. while (true) {
    18. int kk = r.read();
    19. if (kk == -1) {
    20. break;
    21. }
    22. System.out.print((char) kk);
    23. }
    24. Writer w = new StringWriter();
    25. for (int i = 0; i < 26; i++) {
    26. w.write(('a' + i));
    27. }
    28. // 测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型
    29. if (w instanceof StringWriter) {
    30. // 创建StringWriter实例对象
    31. StringWriter sw = (StringWriter) w;
    32. // getBuffer()方法,返回流的字符缓冲对象StringBuffer
    33. StringBuffer ss = sw.getBuffer();
    34. System.out.println(ss);
    35. }
    36. }
    37. }

    总结

    • 读写文件使用节点流FileInputStream/FileOutputStreamFileReader/FileWriter,如果操作文本文件,建议使用FileReader/FileWriter,如果操作二进制文件建议使用FileInputStream/FileOutputStream
    • 需要建立缓冲区(建立临时文件的方式效率低),可以考虑使用内存节点,例如 CharArrayReader/CharArrayWriterStringReader/StringWriterByteArrayInputStream/ByteArrayOutputStream
    • 如果需要一个二进制缓冲区可以使用ByteArrayInputStream/ByteArrayOutputStream,如果需要一个字符缓存可以使用CharArrayReader/CharArrayWriterStringReader/StringWriter
    • 如果数据量不是特别大使用CharArrayReader/CharArrayWriter更为方便,如果数据量大而且可能需要直接操作缓冲区则使用StringReader/StringWriter
    • StringWriter中提供了方法getBuffer():StringBuffer

    过滤流类型

    过滤流就是在节点流的基础上附加功能

    处理类型字符流字节流
    缓存BufferedReader、BufferedWriterBufferedInputStream、BufferedOutputStream
    过滤处理FilterReader、FilterWriterFileInputStream、FileOutputStream
    桥接处理

    InputStreamReader、

    OutputStreamWriter

    对象序列化处理ObjectInputStream、ObjectOutputStream
    数据转换DataInputStream、DataOutputStream
    行数统计LineNumberReaderLineNumberInputStream
    回滚处理PushbackReaderPushbackInputStream
    打印功能PrintWriterPrintStream

    过滤流

    就是decorate模式中的抽象装饰角色

    FilterInputStream/FilterOutputStream和FilterReader/FilterWriter

    public class FilterInputStream extends InputStream { // 典型的装饰模式
            protected volatile InputStream in ; // 被装饰目标
            
            protected FilterInputStream ( InputStream in ) { // 通过构造器组装被装饰对象
                    this . in = in ;
            }
            public int read () throws IOException { // 调用 Filter 中的 read 方法时实际操作是由
    被装饰对象实现的
                    return in . read ();
            }
    }

    所谓的过滤流实际上就是类似上面的加密处理,在输入之后(后置处理,被装饰对象先执行)或者输出之前(前置处理,先处理然后被装饰对象执行)进行一下额外的处理,最终实际操作是调用被装饰对象的方法完成工作,依靠这种装饰模式实现在节点流的基础上附加额外功能。当然也允许多个过滤流嵌套从而达到功能累加的目的

    FilterInputStream实际上就是一个装饰抽象角色

    自定义流实现循环13加密

    • 读取数据不变 :FileReader---BufferedReader
    • 写出数据自定义过滤流Round13Reader(FilterReader)
    1. package com.yan3;
    2. import java.io.FileReader;
    3. import java.io.FilterReader;
    4. import java.io.IOException;
    5. import java.io.Reader;
    6. /*
    7. * 抽象装饰FilterInputStream和FilterOutputStream FilterReader和FilterWriter
    8. */
    9. public class Test2 {
    10. public static void main(String[] args) throws Exception {
    11. // Reader r = new Round13Reader(new FileReader("data/calcCharNum.txt"));
    12. Reader r = new Round13Reader(new FileReader("data/round13.txt"));
    13. // Writer w = new FileWriter("data/round13.txt");
    14. // char[] cc = new char[1024];
    15. int kk = -1;
    16. while ((kk = r.read()) != -1) {
    17. // w.write(kk);
    18. System.out.print((char) kk);
    19. }
    20. r.close();
    21. // w.close();
    22. }
    23. }
    24. class Round13Reader extends FilterReader {
    25. protected Round13Reader(Reader in) {
    26. super(in);
    27. }
    28. @Override
    29. public int read() throws IOException {
    30. int kk = super.read();
    31. // 判断是否是英文字符
    32. if (kk >= 'A' && kk <= 'Z') {
    33. return (kk - 'A' + 13) % 26 + 'A';
    34. } else if (kk >= 'a' && kk <= 'z') {
    35. return (kk - 'a' + 13) % 26 + 'a';
    36. }
    37. return kk;
    38. }
    39. }

     

     桥接转换流

    InputStreamReader OutputStreamWriter java.io 包中用于处理字符流的最基本的类,用来在字节流和字符流之间作为中介:从字节输入流读入字节,并按编码规范转换为字符;往字节输出流写字符时
    先将字符按编码规范转换为字节。使用这两者进行字符处理时,在构造方法中应指定一定的平台规范,以便把以字节方式表示的流转换为特定平台上的字符表示。
    转换流可以在构造时指定其编码字符集
    • InputStreamReader用于将一个InputStream类型的输入流自动转换为Reader字符流
    • OutputStreamWriter用于将一个Writer字符输出流转换为OutputStream字节输出流

    InputStreamReader构造器

    • InputStreamReader(InputStream)
    • InputStreamReader(InputStream, String)
    • InputStreamReader(InputStream, Charset)
    • InputStreamReader(InputStream, CharsetDecorder)
    1. package com.yan3;
    2. import java.io.FileInputStream;
    3. import java.io.InputStreamReader;
    4. import java.io.Reader;
    5. import java.nio.charset.Charset;
    6. /*
    7. * InputStreamReader构造器
    8. * - InputStreamReader(InputStream)
    9. * - InputStreamReader(InputStream, String)
    10. * - InputStreamReader(InputStream, Charset)
    11. * - InputStreamReader(InputStream, CharsetDecorder)
    12. */
    13. public class Test4 {
    14. public static void main(String[] args) throws Exception {
    15. // Reader r = new InputStreamReader(new FileInputStream("data/pavkage-info.java"), "UTF-8");
    16. Reader r = new InputStreamReader(new FileInputStream("data/package-info.java"), Charset.forName("UTF-8"));// Charset.defaultCharset()默认的字符集
    17. int kk = -1;
    18. while (true) {
    19. kk = r.read();
    20. if (kk == -1)
    21. break;
    22. System.out.print((char) kk);
    23. }
    24. }
    25. }

     

    Reader r = new InputStreamReader ( System . in );
    int kk = r . read (); // 例如输入的是 中国 ,这里实际读取的是 " "
    // 因为这里读取的是一个字节,所以输入 " 中国 " ,实际读取的是 " " 的一个字节,输出显示为 ?
    kk = System . in . read ();
    System . out . println ( " 输入的是: " + ( char ) kk );
    InputSteram is=new InputStreamReader(System.in,”iso8859-1”);
    注意:一般不建议自行设置编码字符集,除非是必须的
    Reader r = new InputStreamReader ( System . in , "gbk" );
    int kk = r . read (); // 例如输入的是 " 中国 " ,实际读取的是 " "
    System . out . println ( " 输入的是: " + ( char ) kk );
    1. package com.yan3;
    2. import java.io.FileInputStream;
    3. import java.io.FileOutputStream;
    4. import java.io.InputStream;
    5. import java.io.InputStreamReader;
    6. import java.io.OutputStream;
    7. import java.io.OutputStreamWriter;
    8. import java.io.Reader;
    9. import java.io.Writer;
    10. /*
    11. * ### 桥接转换流
    12. * InputStreamReader和OutputStreamWriter是java.io包中用于处理字符流的最基本的类,
    13. * 用来在字节流和字符流之间作为中介:从字节输入流读入字节,并按编码规范转换为字符;往字节输出流写字符时
    14. * 先将字符按编码规范转换为字节。使用这两者进行字符处理时,在构造方法中应指定一定的平台规范,以便把以字
    15. * 节方式表示的流转换为特定平台上的字符表示。
    16. * 转换流可以在构造时指定其编码字符集
    17. * InputStreamReader用于将一个InputStream类型的输入流自动转换为Reader字符流
    18. * OutputStreamWriter用于将一个Writer字符输出流转换为OutputStream字节输出流
    19. */
    20. public class Test3 {
    21. public static void main(String[] args) throws Exception {
    22. InputStream is = new FileInputStream("data/package-info.java");
    23. Reader r = new InputStreamReader(is);
    24. while (true) {
    25. // int kk = is.read();
    26. int kk = r.read();
    27. if (kk == -1) {
    28. break;
    29. }
    30. System.out.print((char) kk);
    31. }
    32. OutputStream os = new FileOutputStream("data/out.txt");
    33. Writer w = new OutputStreamWriter(os);
    34. w.write("中国人民解放军");
    35. w.close();
    36. }
    37. }
  • 相关阅读:
    CA周记 - Build 2022 上开发者最应关注的七大方向主要技术更新
    你的凭据不工作(Win10远程桌面Win10)详细解决路线
    Python 编写确定个位、十位以上方法及各数位的和程序
    Android gradle动态配置不同打包环境参数值
    Qt学习15 用户界面与业务逻辑的分离
    前端刷题 | 网站
    由注意力机制中scaled sqrt(dk)操作联想到期望与方差的本质推导
    【综合类型第 34 篇】喜讯!喜讯!!喜讯!!!,我在 CSDN 的第一个实体铭牌
    Vue项目流程8,导航守卫的使用,图片懒加载,利用vee-validate实现表单验证,路由懒加载,打包并处理map文件
    第三节:kafka sarama 遇到Bug?
  • 原文地址:https://blog.csdn.net/tiger_root/article/details/126187552