栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 软件开发 > 后端开发 > Java

0803(023天 输入输出流03 节点流+过滤流)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

0803(023天 输入输出流03 节点流+过滤流)

0803(023天 输入输出流03 节点流+过滤流)

每日一狗(田园犬西瓜瓜)

文章目录
  • 0803(023天 输入输出流03 节点流+过滤流)
  • 节点流
    • 1. 文件节点流
      • 1.1 构造方法
      • 1.2 基本方法
    • 2. 内存流
      • 2.1 可变长数组
      • 2.2 内存字符串流(来源和去处都是字符串)
      • 2.3 缓冲区
  • 过滤流类型
    • 1. 过滤流的实现
      • 2.1 装饰模式复习
      • 2.2 案例:自定义流实现循环13加密:
    • 2. 读取中文处理乱码
      • 2.1 FileReader
      • 2.2 new String(btye[])
      • 2.3 桥接流
    • 3. 缓冲流
      • 3.1 缓冲流
      • 3.2 构造方法
      • 3.2 缓冲输入流
        • 键盘录入
        • 为文本文件打上行标签
    • 4. 数据流
      • 4.1 一些方法
      • 4.2 操作字符串
    • 6. 打印流
    • 扩展小芝士

复习:

应用场景

  • 字节流:针对二进制位文件 (音频,视频)
  • 字符流:针对文本文件(txt文件。。。)
节点流

课前小练习(文件的词频统计)

package com.yang1;

import java.io.FileReader;
import java.io.Reader;

public class 课前小练习 {

	public static void main(String[] args) {
		myRead();
	}

	// 读取并进行词频统计
	public static void myRead() {
		ArrayList myArr = new ArrayList(40);
		try (Reader in = new FileReader("G:\蓝鸥\0704(000天 )\笔记\课堂笔记.md")) {
			int tmp = 0;
			while ((tmp = in.read()) > 0) {
				if (tmp == 'n' || tmp == 'r' || tmp == 't') {
					tmp = ' ';
				}

				myArr.add((char) tmp);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		myArr.sorted();
		myArr.show();
	}
}

class MyChar {
	private char myChar;
	private int count;

	public MyChar(char myChar) {
		this.myChar = myChar;
		this.count = 1;
	}

	// 频次加一
	public void plusOne() {
		count++;
	}

	@Override
	public String toString() {
		return myChar + "(" + count + ")";
	}
	/

	public char getMyChar() {
		return myChar;
	}

	public int getCount() {
		return count;
	}
}

class ArrayList {
	private MyChar[] arr;
	private int len;

	public ArrayList() {
		this(10);
	}

	public ArrayList(int lenght) {
		arr = new MyChar[lenght];
		len = 0;
	}

	// 按照出现频率进行排序
	public void sorted() {
		for (int i = 1; i < len; i++) {
			for (int j = 0; j < len - i; j++) {
				if (big(j, j + 1)) {
					MyChar tmp = arr[j];
					arr[j] = arr[j + 1];
					arr[j + 1] = tmp;
				}

			}
		}
	}

	// 判定是否需要交换
	public boolean big(int i, int j) {
		boolean res = false;
		if (arr[i].getCount() < arr[j].getCount()) {
			res = true;
		} else if (arr[i].getCount() == arr[j].getCount()) {
			res = arr[i].getMyChar() > arr[j].getMyChar();
		}
		return res;
	}

	// 展示词频统计结果
	public void show() {
		for (int i = 0; i < len; i++) {
			System.out.print(arr[i]);
		}
	}

	// 传入一个字符,实现词频追加统计
	public void add(char c) {
		MyChar myChar = select(c);
		if (myChar != null) {
			myChar.plusOne();
		} else {
			if (len == arr.length) {
				swell();
			}
			arr[len] = new MyChar(c);
			len++;
		}
	}

	// 数组扩容
	public void swell() {
		MyChar[] newArr = new MyChar[len * 3 / 2];
		for (int i = 0; i < len; i++) {
			newArr[i] = arr[i];
		}
		arr = newArr;
	}

	// 字符查询
	public MyChar select(char c) {
		MyChar res = null;
		for (int i = 0; i < len; i++) {
			if (arr[i].getMyChar() == c) {
				res = arr[i];
				break;
			}
		}
		return res;
	}
}

节点流的分类

类型字符流字节流
File文件FileReader、FileWriterFileInputStream、FileOutputStream
内存数组CharArrayReader、 CharArrayWriterByteArrayInputStream、 ByteArrayOutputStream
内存字串StringReader、 StringWriter
管道PipedReader、 PipedWriterPipedInputStream、 PipedOutputStream
1. 文件节点流

FileInputStream和FileOutputStream是文件字节流,是一种节点流

1.1 构造方法

输入流

  • FileInputStream(“文件名称”),如果文件不存在则报错FileNotFoundException

  • FileInputStream(File)

输出流

  • FileOutputStream(“文件名称”) 如果文件不存在则新建文件,如果文件存在则覆盖文件内容
  • FileOutputStream(String name文件名称, boolean append是否采用追加方式)
1.2 基本方法

输入read

  • read():读取并返回整形数据
  • read(byte[]):将数据读取之字节数组中,返回值为int,有用数据的最后索引

输出write

  • write(int):将(char)int 写入到输出流中
  • write(byte[]):将字节数组中的数据写入到输出流中
2. 内存流 2.1 可变长数组

用于适配不同已经封装好的方法中参数的类型;

这个工具方法要的是输入流,另一个工具方法又要的是输出流(方法内部无法重写)

可以用一个内存输入流先充当这个输入流,在获取到这个输入流的字节数组,在把他封装到一个输出流,传入到另一个工具方法中使用。

使用中间流来进行数据格式的转换

CharArrayReader(char[] buf);
CharArrayRead(char[] buf, int offset, int length);

CharArrayWriter用于实现向一个字符数组中写入数据,这个数组可以自动调整大小

ByteArrayInputStream、ByteArrayOutputStream和CharArrayReader以及CharArrayWriter类似,支 持操作的内容不同而已,操作byte[]与char[]

案例:读取输入字符流,将其转存至变长数组中,在变长数组末尾追加指定字符串,将其转换为输出流,在终端输出输出流存储的数据

public class Test2 {
	public static void main(String[] args) throws Exception {
		String str="abc中国人民解放军123";
		char[] arr=str.toCharArray();
		Reader r=new CharArrayReader(arr);
		while(true) {
			int kk=r.read();
			if(kk==-1)
				break;
			System.out.println((char)kk);
		}
		System.out.println("键盘录入数据");
		Scanner sc=new Scanner(System.in);
		Writer w=new CharArrayWriter();
		while(true) {
			String ss=sc.nextLine();
			if("quit".equals(ss)) break;
			w.write(ss);
		}
		//需要使用CharArrayWriter中定义的特殊方法,获取输出的目标数组
		if(w instanceof CharArrayWriter) {
			CharArrayWriter caw=(CharArrayWriter)w;
			caw.append("asdfasd");//向输出的数组末尾添加内容  StringBuilder
			//获取输出的目标数组
			char[] target=caw.toCharArray();
			System.out.println(new String(target));
		}
	}
}
2.2 内存字符串流(来源和去处都是字符串)
  • StringReader(可读)
    • in.read():int 获取一个整型值(字符)
  • StringWriter(可写)
    • out.write(int):将整型值代表的字符写入调用者中
    • out.getBuffer():StringBuffer,返回当前对象中所存储的字符串
package com.yang4;

import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;

public class T01 {

	public static void main(String[] args) throws IOException {
		String ss = "中华家test";
		Reader in = new StringReader(ss);
		while (true) {
			int i = in.read();
			if (i == -1) {
				break;
			}
			System.out.println((char) i);
		}
		Writer out = new StringWriter();
		for (int i = 0; i < 27; i++) {
			out.write('a' + i);
		}
		if (out instanceof StringWriter) {
			StringWriter sw = (StringWriter) out;
			StringBuffer sb = sw.getBuffer();
			System.out.println(sb);
		}
	}

}
2.3 缓冲区

部分文件需要进行临时存储,但是文件级别的转存,是要经过硬盘的,也就是外存,效率较低;

这时可以使用内存流来维护缓冲区,这就可以大大的提升数据处理的效率


过滤流类型

过滤流就是在节点流的基础上附加功能,这边使用的就是装饰模式来进行实现。

装饰模式的4个角色:通用接口、被装饰对象、抽象装饰、装饰器

处理类型字符流字节流
缓存BufferedReader、BufferedWriterBufferedInputStream、 BufferedOutputStream
过滤处理FilterReader、FilterWriterFilterInputStream、 FilterOutputStream
桥接处理InputStreamReader、 OutputStreamWriter
对象序列化 处理ObjectInputStream、 ObjectOutputStream
数据转换DataInputStream、 DataOutputStream
行数统计LineNumberReaderLineNumberInputStream
回滚处理PushbackReaderPushbackInputStream
打印功能PrintWriterPrintWriter
1. 过滤流的实现

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

FilterInputStream/FilterOutputStream和FilterReader/FilterWriter

2.1 装饰模式复习

4个角色:通用接口、被装饰对象、抽象装饰、装饰器

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

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

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

2.2 案例:自定义流实现循环13加密:

读取数据不变:FileReader—BufferedReader

写出数据自定义过滤流SecurityWriter(FilterWriter)

package com.yang4;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FilterReader;
import java.io.IOException;
import java.io.Reader;

public class T02 {

	public static void main(String[] args) throws FileNotFoundException, IOException {
		try (SecurityWriter in = new SecurityWriter(new FileReader("data/Test01.java"))) {
			while (true) {
				int i = in.read();
				if (i < 0) {
					break;
				}
				System.out.print((char) i);
			}
		}

	}

}

class SecurityWriter extends FilterReader {

	public SecurityWriter(Reader in) {
		super(in);
	}

	public int read() throws IOException {
		int k = super.read();
		if (k >= 'A' && k <= 'Z') {
			k = (k - 'A' + 13) % 26 + 'A';
		} else if (k >= 'a' && k <= 'z') {
			k = (k - 'a' + 13) % 26 + 'a';
		}
		return k;
	}
}

2. 读取中文处理乱码 2.1 FileReader

使用字符流进行操作

2.2 new String(btye[])

读取字节流,使用String给的方法进行字符拼接

package com.lianxiti;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class Test03 {

	public static void main(String[] args) throws FileNotFoundException, IOException {
		try (InputStream in = new FileInputStream("data/output.txt")) {
			byte[] arr = new byte[1024];
			int len = in.read(arr);
			System.out.println(new String(arr, 0, len)); // 种花家
		}
	}

}

2.3 桥接流

InputStreamReader和OutputStreamWriter是java.io包中用于处理字符流的最基本的类,

用来在字节流和字符流之间作为中介:从字节输入流读入字节,并按编码规范转换为字符;往字节输出流写字符时先将字符按编码规范转换为字节。使用这两者进行字符处理时,在构造方法中应指定一定的平台规范,以便把以字节方式表示的流转换为特定平台上的字符表示。转换流可以在构造时指定其编码字符集

InputStreamReader用于将一个InputStream类型的输入流自动转换为Reader字符流

OutputStreamWriter用于将一个Writer字符输出流转换为OutputStream字节输出流

package com.yang4;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;

public class T03 {

	public static void main(String[] args) throws Exception {
		// 桥接流
		// 输入字节流 转 输入字符流
		InputStream in = new FileInputStream("data/Test01.java");
		Reader r = new InputStreamReader(in);
		while (true) {
			int k = r.read();
			if (k == -1) {
				break;
			}
			System.out.print((char) k);
		}
		// 输出字节流 转 输出字符流
		OutputStream out = new FileOutputStream("data/output.txt");
		Writer w = new OutputStreamWriter(out);
		w.write("种花家");
		w.flush();
		w.close();
	}

}

3. 缓冲流

只要能想办法减少对硬盘的操作,就一定可以提高执行效率

3.1 缓冲流

缓冲流是套接在响应的节点流之上,对续写的数据提供缓冲的功能,提高读写的效率,同时增加了一些新方法

以介质是硬盘为例,字节流和字符流的弊端:在每一次读写的时候,都会访问硬盘。

如果读写的频率比较高的时候,其性能表现不佳。为了解决以上弊端,采用缓存流。

缓存流在读取的时候,会一次性读较多的数据到缓存中,以后每一次的读取,都是在缓存中访问,直到缓存中的数据读取完毕,再到硬盘中读取。

3.2 构造方法

缓冲字符流

  • BufferedReader(Reader)不定义缓存大小,默认8192
  • BufferedReader(Reader in, int size)size为自定义缓冲区的大小
  • BufferedWriter(Writer)
  • BufferedWriter(Writer out, int size)size为自定义缓冲区的大小

缓冲字节流

  • BufferedInputStream(InputStream)
  • BufferedInputStream(InputStream in, int size)size为自定义缓冲区的大小
  • BufferedOutputStream(OutputStream)
  • BufferedOutputStream(OuputStream out, int size)size为自定义缓冲区的大小
3.2 缓冲输入流

对数据流进行整行读取

readLine():String 获取输入流的单行数据,会吃掉行未的换行符

键盘录入
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int age = 0;
while (true) {
    String ss = br.readLine();
    try {
        age = Integer.parseInt(ss);
        if (age < 18 || age > 150) {
            System.out.println("您输入的年龄不合法");
        } else {
            break;
        }
    } catch (Exception e) {
        System.out.println("您输入了非法字符");
    }

}
System.out.println("年龄为" + age);
为文本文件打上行标签
package com.yang4;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class T05 {

	public static void main(String[] args) throws FileNotFoundException, IOException {
		try (BufferedReader rb = new BufferedReader(new FileReader("data/Test01.java"));
				BufferedWriter bw = new BufferedWriter(new FileWriter("data/output01.txt"))) {
			int hang = 0;
			while (true) {
				String ss = rb.readLine();
				if (ss == null) {
					break;
				}
				bw.write((++hang + "t"));
				bw.write(ss);
				bw.newLine();

			}
		}
	}

}

4. 数据流

只有字节流,没有对应的字符流

DataInputStream和DataOutputStream两个类创建的对象分别被称为数据输入流和数据输出流。所以比较适合于网络上的数据传 输。这两个流也是过滤器流,常以其它流如InputStream或OutputStream作为它们的输入或输出 DataInputStram和DataOutputStream分别继承自InputStream和OuputStream,属于过滤流,需要分别套接在InputStream和OutputStream类型的节点流上

DataInputStream和DataOutputStream提供了可以存取与机器无关的Java原始类型数据的方法

4.1 一些方法

数据存取方法

  • 有各种针对java中的基本数据类型的读写操纵

构造方法

  • DataInputStream(InputStream)
  • DataOutputStream(OutputStream)

size():int 获取当前操作的位置

4.2 操作字符串

就用这俩,其他的反正就是不合适

readUTF

writeUTF


public class Test83 {
	public static void main(String[] args) throws Exception {
		DataOutputStream dos = new DataOutputStream(new FileOutputStream("data/out3.dat"));
		System.out.println(dos.size());//可以获取当前的输出位置
		dos.writeInt(123);//写出一个整型数
		System.out.println(dos.size());
		dos.writeDouble(12.34);
		System.out.println(dos.size());
		String ss="abcdef";
//		dos.writeBytes(ss);
		dos.writeUTF(ss);  //操作字符串的方法
//		dos.writeChars(ss);
		dos.close();
		
		DataInputStream dis=new DataInputStream(new FileInputStream("data/out3.dat"));
//		dis.skip(4);//跳过4个字节开始读取数据
//		double dd=dis.readDouble();
//		System.out.println(dd);
		dis.skip(12);
//		byte[] data=dis.readAllBytes(); // 读取效果如下图所示存在乱码
		String s1=dis.readUTF();
		System.out.println(s1);
	}
}

6. 打印流

PrintStream和PrintWriter都属于输出流,分别针对字节和字符 PrintWriter和

PrintStream都提供了重载的print和println方法用于输出多种类型数据

print(Object):void

public void println(Object x) {
    String s = String.valueOf(x); //调用String类中的静态方法将object类型的数据转换为字符串
    synchronized (this) {
            print(s);
            newLine(); //print('n')
        }
    }
    //String中的valueOf方法的定义
    public static String valueOf(Object obj) {
    	return (obj == null) ? "null" : obj.toString(); //如果输出对象非空,则调用对象的toString方法
}

println表示输出后自动换行

  • PrintWriter和PrintStream的输出操作不会抛出异常,用户通过检测错误状态获取错误信息
  • PrintWriter和PrintStream有自动的flush功能 textOut.flushBuffer();

PrintWriter(Writer)

PrintWriter(Writer out, boolean autoFlush)自动刷新----println

PrintWriter(OutputStream out) //参数是一个字节流,但是不需要通过桥接处理
PrintWriter(OutputStream out, boolean autoFlush)
PrintStream(OutputStream)
PrintStream(OutputStream out, boolean autoFlush)
扩展小芝士
  • 图片文件格式
    • png
    • gif
    • jpg:控制文件大小
转载请注明:文章转载自 www.wk8.com.cn
本文地址:https://www.wk8.com.cn/it/1036733.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 wk8.com.cn

ICP备案号:晋ICP备2021003244-6号