状态还要再好好调整一下,才能跟上李兴华老师的教学进度

本文详细介绍了Java中的多种IO流操作,包括内存流、管道流、回退流等,并讲解了System类对IO的支持,以及如何使用缓冲区读取和Scanner类进行高效的数据处理。
今天所讲的知识点
A 内存流
B 管道流
C 回退流
D System类对IO的支持
E 缓冲区读取
F Scanner类
G 字符编码问题

我对知识点的分析
A 内存流

计算机中对于数据的输入输出其实都是相对于内存来说的:Out是指从内存中输出,In是指读取数据到内存。
只不过之前的各种IO流是以程序为终端的,而内存流是以内存为终端的。

一、内存输入流:ByteArrayInputStream
构造方法:public ByteArrayInputStream(byte[] buf)
它是InputStream的直接子类。


二、内存输出流:ByteArrayOutputStream
构造方法:public ByteArrayOutputStream()
它是OutputStream的直接子类。


三、操作方法
这两个类使用的方法基本都是从父类继承下来的。
ByteArrayInputStream的操作方法:
No. 方法名称 描述
1 public void close() throws IOException 关闭
2 public int read() 读取一个字节,如果为-1,表示读到尾了
3 public int read(byte[] b,int off,int len) 读取len个到b(从内存输入流指定的读取目标的off处开始读)
ByteArrayOutputStream的操作方法:
No. 方法名称 描述
1 public String toString() 将此缓冲的输出流的内容以字符串返回
2 public void write(int b)throws IOException 将b的内容写入此缓冲的输出流
3 public void write(byte[] b,int off,int len)throws IOException 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此缓冲的输出流。
4 public void flush()throws IOException 刷新此缓冲的输出流

四、操作实例
package mldn.lin.Test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

public class Test{
public static void main(String[] args){
String info="MLDNJAVA-LINYAN";

//实例化内存的输入流对象,并指定从哪里读取内容到内存
ByteArrayInputStream byInput=new ByteArrayInputStream(info.getBytes());

//实例化内存的输出流对象
ByteArrayOutputStream byOutput=new ByteArrayOutputStream();

int temp=0;
while((temp=byInput.read())!=-1){
// 将刚才读取的内容其大写字母变为小写字母
char c = Character.toLowerCase((char) temp);
//将指定的内容写入内存的输出流
byOutput.write(c);
}
try {
byInput.close();
byOutput.close();
} catch (IOException e) {
e.printStackTrace();
}
//输出以检验内存输出流的内容是否是转换后的小写字母
System.out.println(byOutput);//打印byOutput,会调用其toString()
}
}


B 管道流
在程序中进行两个线程对象间的通讯操作,称为管道流。
一、管道输出流:PipedOutputStream
它是OutputStream的直接子类。

构造方法:public PipedOutputStream()

二、管道输入流:PipedInputStream
它是InputStream的直接子类。

构造方法:public PipedInputStream()

三、操作方法
PipedInputStream类的操作方法:
public void connect(PipedOutputStream src)throws IOException:连接管道输出流
protected void receive(int b)throws IOException:接收数据
public int read()throws IOException:读取到管道输入流中
public int read(byte[] b,int off,int len)throws IOException:读取到管道输入流中
public void close()throws IOException

PipedOutputStream类的操作方法:
public void connect(PipedInputStream snk)throws IOException:连接管道输入流
public void write(int b)throws IOException
public void write(byte[] b,int off,int len)throws IOException
public void flush()throws IOException:刷新
public void close()throws IOException

四、示例代码:实现线程的双向通信


C 回退流
有选择的收取输入流中的内容,当从输入流中读取的内容不是自己需要的内容,可以将其回退回去,重新选择。

一、字节回退流:PushbackInputStream

构造方法:public PushbackInputStream(InputStream in)

二、字符回退流:PushbackReader

构造方法:public PushbackReader(Reader in)

三、操作方法
字节回退流和字符回退流的操作方法极其类似,都有如下方法:
1、public void unread(char/byte[] b) throws IOException 回退一组流
2、public void unread(char/byte[] b,int off,int len) throws IOException 回退一组的部分流
3、public void unread(int b) throws IOException 回退一个流
4、public int read()throws IOException
5、public int read(char/byte[] cbuf,int off,int len)throws IOException
6、public void close()throws IOException

四、操作实例
package mldn.lin.Test;

import java.io.ByteArrayInputStream;
import java.io.PushbackInputStream;
public class Test {
public static void main(String[] args) throws Exception {
String info = "123sbg456..78"; //一会儿从中读取数字

ByteArrayInputStream bis = new ByteArrayInputStream(info.getBytes());// 表示内存输入流
PushbackInputStream push = new PushbackInputStream(bis); // 实例化回退流对象

int temp = 0;
while ((temp = push.read()) != -1) { // 读取内容
if (!(temp>='0' && temp<='9')) { // 不需要字符,回推
push.unread(temp); // 回退到缓冲区之中
push.read();// 读取出不要的
} else {
System.out.print((char) temp);
}
}
push.close();
bis.close();
}
}

D System类对IO的支持
一、System类中和输入输出有关的常量
1、public static final PrintStream out 对应标准输出,显示器
2、public static final PrintStream err 对应错误输出,显示器
3、public static final InputStream in 对应标准输入,键盘

二、System.out
1、示例:
System.out.print(“chailinyan”);
out是全局常量,所以可以通过类名访问,同时out是PrintStream对象,所以具有PrintStream类的操作方法(print、println等),所以上述语句是指向屏幕输出字符串“chailinyan”;

2、System.out向上转型至OutputStream
OutputStream ops = System.out; // 使用System.out实例化OutputStream对象
ops.write("hello".getBytes());
ops.close();
运行结果也是向屏幕打印,所以用哪个子类对象实例化OutputStream,OutputStream就具有谁输出的能力

三、System.err
和System.out的使用语法一样,区别在于System.err用于错误信息的输出
• System.out是希望用户看到的信息
• System.err是不希望用户看到的信息

四、System.in
因为System.in是InputStream类型的,该类具有InputStream类的操作方法。
示例代码:
方法一:
byte b[] = new byte[1024];// 接收键盘输入
System.out.print("请输入内容:");
int len = System.in.read(b); // 所有内容输入到byte数组之中
System.out.println("输入的内容是:" + new String(b, 0, len));

方法二:
InputStream input = System.in; // 此时表示从键盘输入
byte b[] = new byte[1024];// 接收键盘输入
System.out.print("请输入内容:");
int len = input.read(b); // 所有内容输入到byte数组之中
System.out.println("输入的内容是:" + new String(b, 0, len));

问题:如果输入的内容太长,则b数组不够

方法三:(可以输入随意长度的内容)
InputStream input = System.in; // 此时表示从键盘输入
int temp = 0;
StringBuffer buf = new StringBuffer();
System.out.print("请输入内容:");
while ((temp = input.read()) != -1) {
if (temp == '\n') {//按回车表示输入结束
break;// 退出循环
}
buf.append((char) temp);
}
System.out.println("输入的内容是:" + buf);

局限:无输入长度限制,但是如果输入汉字,则会出现乱码,因为按一个一个字节读取的,而一个汉字是两个字节
解决方案:见缓冲区读取部分

四、输入、输出重定向
对于System.in、System.out、System.err来讲本身可以对输入和输出进行重定向的操作,即可以改变其输入输出的位置
使用System的方法如下:
No. 方法名称 描述
1 public static void setOut(PrintStream out) 修改输出的位置
2 public static void setErr(PrintStream err) 修改错误输出的位置,但是,一般不更改
3 public static void setIn(InputStream in) 修改输入的位置

package mldn.lin.Test;

import java.io.FileInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.PrintStream;

public class Test{
public static void main(String[] args) throws Exception {
InputStream input =new FileInputStream(new File("D:" + File.separator+"test.txt"));
System.setIn(input);//重定向输入来源为文件test.txt而不是键盘
byte b[] = new byte[1024];
int len = System.in.read(b); // 读取内容

PrintStream ps = new PrintStream(new FileOutputStream(new File("D:"+ File.separator + "test1.txt")));
System.setOut(ps);// 重定向输出位置为文件test1.txt而不是显示器
System.out.println(new String(b, 0, len));
}
}

E 缓冲区读取
在使用System.in进行键盘输入时,如果使用读取到字节数组,则要实现定义足够大的容量,如果使用循环读取字节,则对于中文这种双字节字符又会出现乱码,由此需要采用缓冲区读取方式,即先将内容一次性读取到缓冲区,然后再从缓冲区读取。要想实现这样的功能就要使用BufferedReader类完成。

一、BufferedReader类的构造方法
构造方法:public BufferedReader(Reader in)
参数说明:参数要求是Reader类型,而System.in是InputStream类型的,则此时如果要想使用,则必须将字节输入流变为字符输入流,使用InputStreamReader类。

二、BufferedReader类的操作方法
最常用的:public String readLine() throws IOException 读取一行

三、示例代码
BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
System.out.print("请输入内容:");
String str = null;
try {
str = buf.readLine();// 输入数据
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("输入的内容是:" + str);

F Scanner类
如果想要在读取的同时能够进行验证操作,或者说按照自己的格式从输入流中筛选处自己要的信息,那么就需要用到java.util包中的Scanner类。此类虽然不是java.io包中的,但也是也io操作有关的。
一、构造方法
1、public Scanner(File source) throws FileNotFoundException
2、public Scanner(InputStream source)
二、操作方法
1、public boolean hasNext() //判断是否有下一个输入内容
2、public String next() //取出内容
3、public boolean hasNext(Pattern pattern) //设置输入的正则验证,是在取之前使用
4、public String next(Pattern pattern) //对输入的内容进行验证,是在取的时候使用
5、public Scanner useDelimiter(String pattern) //设置读取的分隔符
6、public boolean hasNextInt() //判断下一个内容是否是整数,可以把Int换成其他数据类型
7、public int nextInt() //读取下一个整数内容(一般之前都使用了hasNextInt()进行判断过了)
Scanner类提供了判断和读取各种数据类型的方法,但是对于日期,复杂字符串等内容的判断需要手工编写正则表达式。

三、示例代码
1、判断日期
Scanner scan = new Scanner(System.in); // 表示键盘输入
System.out.print("请输入内容:");
if (scan.hasNext("\\d{4}-\\d{2}-\\d{2}")) { // 判断输入的是否是日期类型
String str = scan.next("\\d{4}-\\d{2}-\\d{2}");
Date date = null;
try {
date = new SimpleDateFormat("yyyy-MM-dd").parse(str);
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println("输入的是数字,x = " + date);
} else {
System.out.println("输入的不是日期!");
}

2、设置读取内容的分隔符
Scanner scan = new Scanner(new FileInputStream(new File("D:"+ File.separator + "mldn.txt"))); // 表示从文件中读取
scan.useDelimiter("\n"); // 换行作为分隔符,即一行一行读取
while (scan.hasNext()) {
System.out.println(scan.next());
}

G 字符编码问题
不同的文字在计算机中采用的编码方式不同,那么不同的开发语言支持的编码方式也不同。
一、编码
编码,也即通常所说的字符集,或称字集,是某种文字的集合;将固定数目的文字编序,以方便作通讯、教育、资讯处理等用途。我们常见的有:ASCII、Unicode、GB 2312、Big5、CNS 11643、GBK、ISO 8859-1、UTF-8等。
在Java程序开发中最常见的是:ISO 8859-1、GBK/ GB 2312、Unicode、 UTF。


二、示例代码
1、获得本机编码方式
System.getProperties().getProperty("file.encoding")

2、转换编码方式
OutputStream out = new FileOutputStream(new File("D:" + File.separator+ "temp.txt"));
out.write("中国,你好!".getBytes("ISO8859-1"));// 转变编码
out.close();


今天一天还算是相对轻松一些,毕竟李兴华老师已经把IO操作的基本要领都讲解清楚了,只是多了解了几个操作类而已,清明后的第一天上课,感觉歇散了一样,很没有精神,过了今天我想就会好了吧。嘿嘿,好捆,晚上坚持复习完,之后就赶紧去睡觉了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值