Java-流和IO

news/2023/6/7 1:08:38

文章目录

      • InputStream
        • FileInputStream
          • 常用方法详情
          • 代码示例
        • BufferInputStream
          • 常用方法详情
          • 代码示例
      • OutputStream
        • FileOutputStream
          • 常用方法详情
          • 代码示例
        • BufferedOutputStream
          • 常用方法详情
          • 代码示例
      • Read
      • Write

Java的java.io库提供了IO接口,IO是以流为基础进行输入输出的。

流又可以分为:输入流、输出流、字节流、字符流等。流相互结合使用,有字节输入流、字节输出流、字符输入流、字符输出流等。

输入流表示从一个源读取数据,输出流表示向一个目标写数据。

字节流操作的数据单元是字节(byte),字符流操作的数据单元是字符(char)。

在这里插入图片描述
输入流的基类:InputStream、Reader 主要用于读数据

输出流的基类:OutputStream、Writer 主要用于写数据

字节流的基类:InputStream、OutputStream

字符流的基类:Reader、Writer

InputStream

主要方法:
在这里插入图片描述
常用方法详情:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
相应接口文档可查看:java文档中文

FileInputStream

FileInputStream 继承了InputStream ,主要方法:
在这里插入图片描述
在这里插入图片描述

常用方法详情

构造方法,常用于连接实际文件创建一个FileInputStream 对象,使用该对象完成上述流的操作
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码示例

从一个文件中读取字节数据,先创建一个data.txt ,输入:北国风光,千里冰封,万里雪飘。望长城内外,惟余莽莽;大河上下,顿失滔滔。
以UTF-8编码保存。

public class InputStreamDemo {public static void main(String[] args) {// data.txt 路径String fileName = "D:\\work\\workspace\\java-learn\\io\\data.txt";readMsg(fileName);}public static void readMsg(String fileName) {byte[] data = null;try {// 创建输入流FileInputStream fis = new FileInputStream(fileName);// 在读写操作前获取数据流的字节大小int readSize = fis.available();data = new byte[readSize];// 从输入流fis中读取data.length字节数据到字节数组data// 这里的读数据,还可以根据fis.read())!=-1,一个个字节读取。fis.read(data);// 释放资源fis.close();System.out.println("size = " + readSize);// 遍历字节数组for (int i = 0; i < data.length; i++) {System.out.print(data[i] + "、");}} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}
}

在这里插入图片描述
在这里插入图片描述
这样,就完成了使用FileInputStream 读取文件数据。可以使用data.txt 内容直接转换成字节数组,看看与FileInputStream 读取文件数据内容是否一致。

public static void main(String[] args) {// data.txt 路径
//        String fileName = "D:\\work\\workspace\\java-learn\\io\\data.txt";
//        readMsg(fileName);String s = "北国风光,千里冰封,万里雪飘。望长城内外,惟余莽莽;大河上下,顿失滔滔。";try {byte[] data = s.getBytes("UTF-8");System.out.println("字节数组大小: " + data.length);// 遍历字节数组for (int i = 0; i < data.length; i++) {System.out.print(data[i] + "、");}} catch (UnsupportedEncodingException e) {e.printStackTrace();}}

在这里插入图片描述
对比一致。这样就可以在已经有文件的时候,使用FileInputStream 读取相应文件内容。
在接口文档中,read有三种读取方式:
1、read()

public static void readMsg2(String fileName) {try {// 创建输入流FileInputStream fis = new FileInputStream(fileName);int b;while ((b = fis.read()) != -1) {// 因为fis.read() 返回值是一个个字节的整形,这里需要转换一下System.out.print((byte)b + "、");}// 释放资源fis.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}

这个方法要注意的是read()返回值是整形,至于为什么,可以参考:https://blog.csdn.net/music0ant/article/details/60337974

2、read(byte[] bytes)

这个方法就是上面的例子使用的

** 3、read(byte[] b, int off, int len) **

public static void readMsg3(String fileName) {byte[] data = null;try {// 创建输入流FileInputStream fis = new FileInputStream(fileName);// 这里设置的大小一般为1024的倍数data = new byte[1024];int len;while ((len = fis.read(data, 0, data.length)) != -1) {// 字节转换成字符System.out.println(new String(data, 0, len));}// 释放资源fis.close();// 遍历字节数组for (int i = 0; i < data.length; i++) {System.out.print(data[i] + "、");}} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}

BufferInputStream

BufferedInputStream 是FilterInputStream 的子类,而FilterInputStream 又是InputStream 的子类
FileInputStream 的read() 方法,是直接从磁盘中读取数据至内存;而BufferedInputStream 底层是维护了一块大小为
DEFAULT_BUFFER_SIZE = 8192 的缓存区,它read()方法会使用到fill() 方法,该方法完成将数据存放到缓冲区中,但该方法内,底层会调用FileInputStream 的read() 方法,将数据从磁盘取出。

  1. 使用BufferedInputStream 需要传入一个InputStream
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\work\\workspace\\java-learn\\io\\data.txt"));

这时,BufferedInputStream 获取到了相应的FileputStream 流及设置了默认的缓存区大小

public BufferedInputStream(InputStream in) {this(in, DEFAULT_BUFFER_SIZE);
}

in 代表了流

  1. 然后在使用BufferedInputStream 的read()方法时(包括有参及无参的方法),都会存三两个方法的调用:fill()和getInIfOpen()及getBufIfOpen()
public synchronized int read() throws IOException {if (pos >= count) {fill();if (pos >= count)return -1;}return getBufIfOpen()[pos++] & 0xff;}
public synchronized int read(byte b[], int off, int len)throws IOException{getBufIfOpen(); .....省略int nread = read1(b, off + n, len - n);// 调用read1() 中含有fill() 方法.....省略}private int read1(byte[] b, int off, int len) throws IOException {.....省略if (len >= getBufIfOpen().length && markpos < 0) {return getInIfOpen().read(b, off, len);}fill();.....省略System.arraycopy(getBufIfOpen(), pos, b, off, cnt);pos += cnt;return cnt;}
private void fill() throws IOException {byte[] buffer = getBufIfOpen();if (markpos < 0)pos = 0;            /* no mark: throw away the buffer */else if (pos >= buffer.length)  /* no room left in buffer */if (markpos > 0) {  /* can throw away early part of the buffer */int sz = pos - markpos;System.arraycopy(buffer, markpos, buffer, 0, sz);pos = sz;markpos = 0;} else if (buffer.length >= marklimit) {markpos = -1;   /* buffer got too big, invalidate mark */pos = 0;        /* drop buffer contents */} else if (buffer.length >= MAX_BUFFER_SIZE) {throw new OutOfMemoryError("Required array size too large");} else {            /* grow buffer */int nsz = (pos <= MAX_BUFFER_SIZE - pos) ?pos * 2 : MAX_BUFFER_SIZE;if (nsz > marklimit)nsz = marklimit;byte nbuf[] = new byte[nsz];System.arraycopy(buffer, 0, nbuf, 0, pos);if (!bufUpdater.compareAndSet(this, buffer, nbuf)) {// Can't replace buf if there was an async close.// Note: This would need to be changed if fill()// is ever made accessible to multiple threads.// But for now, the only way CAS can fail is via close.// assert buf == null;throw new IOException("Stream closed");}buffer = nbuf;}count = pos;int n = getInIfOpen().read(buffer, pos, buffer.length - pos);if (n > 0)count = n + pos;}
  1. getInIfOpen() 获取到了in流,getBufIfOpen() 获取到了缓存区,使用read() 方法就获取到了缓存区内的数据。
private InputStream getInIfOpen() throws IOException {InputStream input = in;if (input == null)throw new IOException("Stream closed");return input;}
private byte[] getBufIfOpen() throws IOException {byte[] buffer = buf;if (buffer == null)throw new IOException("Stream closed");return buffer;}

BufferedInputStream
当创建BufferedInputStream时,将创建一个内部缓冲区数组。 当从流中读取或跳过字节时,内部缓冲区将根据需要从所包含的输入流中重新填充,一次有多个字节。 mark操作会记住输入流中的一点,并且reset操作会导致从最近的mark操作之后读取的所有字节在从包含的输入流中取出新的字节之前重新读取。
主要方法:
在这里插入图片描述
在这里插入图片描述

常用方法详情

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码示例

1、read()
直接使用read() 方法逐步读取

public static void read(String file) {try {// 获取文件的输入流FileInputStream fis = new FileInputStream(file);// 使用构造方法获取缓冲流对象BufferedInputStream bis = new BufferedInputStream(fis);// 记录数据的下一个字节,如果到达了流的末尾,为 -1int len;// 计算有多少的字节// 判断是否到达流的末尾,退出循环while ((len = bis.read()) != -1) {// read() 返回的是字节的整形,需要转换System.out.print((byte)len + "、");}// 释放资源bis.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}

2、通过read(byte[] b)读取

public static void read2(String file) {try {FileInputStream fis = new FileInputStream(file);BufferedInputStream bis = new BufferedInputStream(fis);// 设置读取数据的缓冲区,这里设置读取字节最多为b的长度1024byte[] b = new byte[1024];// 读取到缓冲区的总字节数,或者如果没有更多的数据,因为已经到达流的末尾,则是 -1// 也就是上面的缓冲区设置的b长度,就是通过bis.read(b)一步步获取,直到最后的 -1int len;// 如果new byte[16],则len 会为:16、16、16、16、16、16、14// 如果new byte[32],则len 会为:32、32、32、14// 如果new byte[64],则len 会为:64、46while ((len = bis.read(b)) != -1) {// 根据读取到的字节长度为len 的b 数组进行解码打印// 注意如果分配的缓冲区长度不够放置完整字符,将会产生乱码,// 比如new byte[16],这里将会出现乱码,因为读取的句子有字符被“切割开”了。无法解析相应字节System.out.printf(new String(b, 0, len));}} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}

3、通过read(byte[] b,int off,int len)读取

public static void read3(String file) {FileInputStream fis = null;byte[] data = null;try {fis = new FileInputStream(file);BufferedInputStream bis = new BufferedInputStream(fis);data = new byte[1024];int len;while ((len = bis.read(data, 0, data.length)) != -1) {System.out.println(new String(data, 0, len));}// 释放资源fis.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}

结果:
在这里插入图片描述

OutputStream

FileOutputStream

文件输出流是用于将数据写入到输出流File或一个FileDescriptor 。
File 都好理解,FileDescriptor 是文件描述符,可以看作是系统为了管理已经打开的文件,而创建的文件索引。一个文件描述符对应一个文件,不同的文件描述符可以对应同一个文件。执行IO操作需要通过文件描述符。

常用方法详情

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
具体使用:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
该方法可以获取到文件描述符
在这里插入图片描述

代码示例

1、write(byte[] b):

public class FileOutputStreamDemo {public static void main(String[] args) {String fileName = "D:\\work\\workspace\\java-learn\\io\\out.txt";String date = "惜秦皇汉武,略输文采。唐宗宋祖,稍逊风骚。一代天骄,成吉思汗。数风流人物,还看今朝。";byte[] bytes = date.getBytes();// 指定编码// byte[] bytes = date.getBytes("UTF-8");saveMsg(fileName, bytes);}public static void saveMsg(String fileName, byte[] data) {FileOutputStream foStream = null;try {foStream = new FileOutputStream(fileName);foStream.write(data);foStream.close();} catch (Exception e) {e.printStackTrace();} finally {if (foStream != null) {try { foStream.close();} catch (Exception ee) {}}}}
}

结果:
在这里插入图片描述
2、write(byte[] b, int off, int len)
根据偏移量写入

public class FileOutputStreamDemo {public static void main(String[] args) {String fileName = "D:\\work\\workspace\\java-learn\\io\\out.txt";String date = "惜秦皇汉武,略输文采。唐宗宋祖,稍逊风骚。一代天骄,成吉思汗。数风流人物,还看今朝。";byte[] bytes = date.getBytes();// 指定编码// byte[] bytes = date.getBytes("UTF-8");
//        saveMsg(fileName, bytes);saveMsg2(fileName, bytes);}public static void saveMsg2(String fileName, byte[] data) {FileOutputStream foStream = null;try {foStream = new FileOutputStream(fileName);// 偏移12个字符,从“武”开始写入foStream.write(data, 12, 21);foStream.close();} catch (Exception e) {e.printStackTrace();} finally {if (foStream != null) {try { foStream.close();} catch (Exception ee) {}}}}public static void saveMsg(String fileName, byte[] data) {FileOutputStream foStream = null;try {foStream = new FileOutputStream(fileName);foStream.write(data);foStream.close();} catch (Exception e) {e.printStackTrace();} finally {if (foStream != null) {try { foStream.close();} catch (Exception ee) {}}}}
}

结果:
在这里插入图片描述

BufferedOutputStream

和BufferedInputStream 一样,为了提高读写速度,使用BufferedOutputStream ,在写数据到文件时,不会直接写,而是先写到缓冲区,缓冲区满了,在通过flush() 方法刷新缓冲流,从缓冲区写数据到文件。BufferedOutputStream 默认使用8192 大小的缓冲区。在默认构造方法中定义。可以调用含有int size 构造方法设定缓冲区大小。

常用方法详情

在这里插入图片描述

public BufferedOutputStream(OutputStream out) {this(out, 8192);
}public BufferedOutputStream(OutputStream out, int size) {super(out);if (size <= 0) {throw new IllegalArgumentException("Buffer size <= 0");}buf = new byte[size];
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码示例
public class BufferedOutputStreamDemo {public static void main(String[] args) {String fileName = "D:\\work\\workspace\\java-learn\\io\\bufferedOut.txt";String date = "Buffered 惜秦皇汉武,略输文采。唐宗宋祖,稍逊风骚。一代天骄,成吉思汗。数风流人物,还看今朝。";byte[] bytes = date.getBytes();
//        saveMsg(fileName, bytes);saveMsg2(fileName, bytes);}public static void saveMsg2(String file, byte[] data) {BufferedOutputStream bos = null;try {bos = new BufferedOutputStream(new FileOutputStream(file));// 从“秦”开始写,写4个字符bos.write(data, 12, 12);// 刷新缓冲输出流bos.flush();bos.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {if (bos != null) {try { bos.close();} catch (Exception ee) {}}}}public static void saveMsg(String file, byte[] data) {BufferedOutputStream bos = null;try {bos = new BufferedOutputStream(new FileOutputStream(file));bos.write(data);// 刷新缓冲输出流bos.flush();bos.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {if (bos != null) {try { bos.close();} catch (Exception ee) {}}}}
}

结果:
全写
在这里插入图片描述
根据偏移量写
在这里插入图片描述

Read

Write

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.exyb.cn/news/show-4561682.html

如若内容造成侵权/违法违规/事实不符,请联系郑州代理记账网进行投诉反馈,一经查实,立即删除!

相关文章

保时捷狂推NFT,高调喊出打造Web3社区,Web2品牌“天生缺陷”终将折戟沉沙?...

图片来源&#xff1a;由无界 AI 绘画工具生成2023年1月&#xff0c;保时捷中国的公关团队“忙疯”了&#xff0c;一连搞了好几个活动。有展览&#xff0c;媒体连线直播&#xff0c;甚至搞起了一场有圆桌&#xff0c;有嘉宾主题演讲的发布会。目的只有一个&#xff0c;告诉中国用…

安全可信 | 安全与高效兼得?天翼云EasyCoding敏捷开发平台来了!

近日&#xff0c;天翼云云上数字研发EasyCoding敏捷开发平台在“可信安全”SaaS安全能力评估中&#xff0c;通过中国信息通信研究院评测&#xff0c;荣获“SaaS安全能力检验证书”。 随着数字经济蓬勃发展&#xff0c;企业上云步伐不断加快&#xff0c;以远程办公、数字化采购…

All In全闪存存储,这家银行干得漂亮

华为构建全闪存数据中心全生命周期服务&#xff0c;全面支持河北银行将所有业务系统迁移到全闪存存储&#xff0c;以单设备全闪存存储承载更多业务。出品 | 常言道作者 | 丁常彦曾几何时&#xff0c;互联网金融的强势崛起&#xff0c;让众多传统金融机构感受到浓浓的危机感&…

从阿里云七代云服务器,谈云计算四大趋势

简介&#xff1a;云计算走了十年有余&#xff0c;期间阿里云共发布了七代云服务器。每一代阿里云ECS产品的性能提升&#xff0c;都指引着云计算的发展趋势。看看第七代ECS产品的发布&#xff0c;又透露了哪些未来趋势。从不知为何物到成为基础设施&#xff0c;云计算走过了 10 …

构建招商、物业、人力、财务、资产、综合管理为一体的数据分析体系

经过二三十年的发展&#xff0c;地产行业增速放缓&#xff0c;进入“狭路相逢勇者胜”的存量时代&#xff0c;传统的标准化复制产品和服务难以应对市场需求和行业的激烈竞争&#xff0c;加速房企向多元化经营和精细化运营转型。对于商业地产来说&#xff0c;已经由开发竞争阶段…

基于IoT全链路实时质量 - 魔洛哥

1 背景 伴随着物联网(IoT)的快速发展&#xff0c;软硬件交互场景越来越普及&#xff0c;在自用和商用的空间场域中&#xff0c;我们智慧园区、未来酒店的智能化场景也得到了极大的丰富&#xff0c;打造出多款智能有科技感的产品&#xff0c;如人脸门禁、云前台、入住自助机、无…

阿里云第七代云服务器,引领IaaS市场四大趋势

从不知为何物到成为基础设施,云计算走过了10年有余。 像许多社会变迁一样,这是一个自上而下的过程,无论是国内外,最早用云计算的,都是中小站长或者初创企业。因为他们无法像中大型企业一样,支付高昂的数据中心建设和服务器维护费用。 因此,最受他们关注的,也是最早的云计算产…

“数盈”未来 | 中台的SaaS进化

点击蓝字关注 了解更多2015年&#xff0c;“中台”概念诞生。从那时开始&#xff0c;IT界对中台的讨论就从未停止。提到中台&#xff0c;很多从业者依然无法具象地说清它到底是什么。从企业信息化、数字化、智能化进程的角度来说&#xff0c;国内企业也仅仅可以说刚刚迈过信息化…