javaSE学习笔记(七)IO流

目录

六、IO流

1.IO流概述

概念

分类

IO体系

简单介绍

最重要,最常用,最常见的两个流

2.File类

路径分隔符

绝对路径和相对路径

构造方法

方法

重命名注意事项

删除注意事项

3.FileInputStream&FileOutputStream

FileInputStream

获取文件输入流

方法

read()方法返回值为什么是int,而不是byte

FileOutputStream

获取文件输出流

方法

4.BufferedInputStream&BufferedOutputStream

小数组的读写和带Buffered的读取哪个更好

BufferedInputStream

获取缓冲输入流

BufferedOutputStream

获取缓冲输出流

方法

5.MultipartFile(springmvc会用到)

6.零拷贝(拓展了解,可以不掌握)


六、IO流

1.IO流概述

概念

作用:IO流用来处理数据传输,java操作数据是通过流的方式,java提供了IO包来进行流操作,使用后需要关闭流

分类

按流向分:输入流,输出流

按操作类型分:

字节流 : 字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的

字符流 : 字符流只能操作纯字符数据

IO体系

简单介绍

字节流的抽象父类:InputStream,OutputStream

字符流的抽象父类:Reader,Writer

其他子类

最重要,最常用,最常见的两个流

FileInputStream&&FileOutputStream 字节流

BufferedInputStream&&BufferOutputStream 缓冲字节流

可能会用到,但很少见,实际开发中几乎用不到

ServletInputstream 读取客户端的请求信息的输入流

ServletOutputStream 用这个输出流可以将数据返回到客户端

SequenceInputStream 序列流,可以把多个InputStream整合成一个SequenceInputStream

不重要,实际开发不用

FileReader&&FileWriter 字符流,与字节流几乎一样,只是读写的单位是字符

BufferedReader&&BufferedReader 缓冲字符流,与字节流几乎一样,只是读写的单位是字符

LineNumberReader BufferedReader的子类,具有相同的功能,并且可以统计行号

InputStreamReader&OutputStreamWriter 转换流,字节流读入,转为字符流,再转为字节流写出

ByteArrayOutputStream 内存输出流,可以向内存中写数据,把内存当作一个缓冲区(字节数组),写出之后可以一次性获取出所有数据

ObjecOutputStream&&ObjectInputStream 对象操作流,针对对象进行读写,简单理解为序列化和反序列化操作

DataInputStream&&DataOutputStream 数据输入输出流,可以按照基本数据类型大小读写数据

PrintStream 打印流,将对象的toString()结果输出, 并且自动加上换行, 而且可以使用自动刷出的模式

2.File类

定义:文件和目录路径名的抽象表示形式,File类中涉及文件或文件目录的创建、删除、重命名、修改时间、文件大小等

路径分隔符

windows和DOS系统默认使用"\"来表示;

UNIX和URL使用"/"来表示

JAVA提供了一个自适应的常量File.separator

绝对路径和相对路径

绝对路径是一个固定的路径,从盘符开始

相对路径相对于某个位置

构造方法

File(String pathname),根据一个路径得到File对象

File(String parent, String child),根据一个目录和一个子文件/目录得到File对象,通过这种方式可以分别得到某个父目录下不同的子目录文件

File(File parent, String child),根据一个父File对象和一个子文件/目录得到File对象,也可以将父目录封装成File对象,这样比String更强大(有很多属性和方法可以调用)

方法

实际开发中更关注的是流的操作,对File通常不会进行复杂操作,java提供了FileUtils工具类

public boolean createNewFile() 创建文件,如果存在这样的文件,就不创建了

public boolean mkdir() 创建文件夹,如果存在这样的文件夹,就不创建了

public boolean mkdirs() 创建文件夹,如果父文件夹不存在,会自动创建出来

public boolean renameTo(File dest)重命名为指定的文件路径(改名+剪切)

public boolean delete() 删除文件或者文件夹

重命名注意事项

如果路径名相同,就是改名

如果路径名不同,就是改名并剪切

删除注意事项

Java中的删除不走回收站

要删除一个文件夹,请注意该文件夹内不能包含文件或者文件夹

public boolean isDirectory() 判断是否是目录

public boolean isFile() 判断是否是文件

public boolean exists() 判断是否存在

public boolean canRead() 判断是否可读,通过setReadable(true);

public boolean canWrite() 判断是否可写,通过setWriteable(false);

public boolean isHidden() 判断是否隐藏

public String getAbsolutePath() 获取绝对路径

public String getPath() 获取路径(构造方法中传入的路径)

public String getName() 获取名称

public long length() 获取长度(字节数)

public long lastModified() 获取最后一次的修改时间(距1970的毫秒值)

public String[] list() 获取指定目录下的所有文件或者文件夹的名称数组

public File[] listFiles() 获取指定目录下的所有文件或者文件夹的File对象数组

3.FileInputStream&FileOutputStream

文件字节输入/输出流,对文件数据以字节的形式进行读写

FileInputStream

获取文件输入流

File file = new File("xxxxxxxx");

FileInputStream fileInputStream=new FileInputStream(file); //若File类对象的所代表的文件不能打开(不存在、不是文件是目录等原因),则会抛出FileNotFoundException

FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Coolway26\\Desktop\\ceshi.txt"); //直接传入文件路径也可以获取文件流,底层仍然是先生成File对象,路径需要使用转义字符

方法

public int read() throws IOException //从输入流中读取一个字节的数据,返回读取的数据,是int型变量,若到达文件末尾,则返回-1

public int read(byte[] b) throws IOException //一次读取一个字节显然效率太低了,因此IO流提供了另外一种读取的方式,从输入流中一次性读取b.length个字节到字节数组b中,返回读入数组缓冲区的总字节数,若到达文件末尾,则返回-1

public int read(byte[] b, int off, int len) throws IOException

public void close() throws IOException //关闭流,释放资源

public int available() throws IOException //获取流中字节个数

read()方法返回值为什么是int,而不是byte

目的:为了准确的判断是否到了末尾(末尾是int型的-1)

因为字节输入流可以操作任意类型的文件,比如图片音频等,文件都是以二进制形式存储,如果每次读取都返回byte,有可能在读到中间的时候遇到111111111,那么这11111111是byte类型的-1,流遇到-1就认为到达文件末尾,不会再继续读取后续内容,读取的时候用int类型接收,如果11111111会在其前面补上24个0凑足4个字节,那么byte类型的-1就变成int类型的255,这样可以保证整个数据读完,而结束标记的-1就是int类型

FileOutputStream

获取文件输出流

FileOutputStream fos = new FileOutputStream(file);

FileOutputStream fos = new FileOutputStream("C:\\Users\\Coolway26\\Desktop\\ceshi.txt"); //文件如果不存在,会自动创建,文件存在会清空该文件

FileOutputStream fos = new FileOutputStream("C:\\Users\\Coolway26\\Desktop\\ceshiOut.txt", true); //追加写入,不清空文件

方法

public void write(int b) throws IOException //通过流向文件末尾写入一个字节,虽然入参是int,但实际写入时会默认去掉前面的0

public void write(byte b[]) throws IOException

public void write(byte b[], int off, int len) throws IOException

//桌面上创建一个txt文件,保存 123ceshi测试,然后操作这个文件看看效果
FileInputStream fis = new FileInputStream("C:\\Users\\Coolway26\\Desktop\\ceshi.txt");
int n=0;
StringBuffer sb = new StringBuffer();
while (n != -1)     //当n不等于-1,则代表未到末尾
{
    n = fis.read(); //读取文件的一个字节(8个二进制位),并将其由二进制转成十进制的整数返回
    char by = (char) n;    //转成字符,中文会乱码,因为中文不是单个字节存储
    sb.append(by);
}
System.out.println(sb.toString());

int m=0;
byte[] b = new byte[1024];
int i = 0;
while (m != -1)             //当n不等于-1,则代表未到末尾
{
    m = fis.read(b);        //返回实际读取到字节数组中的字节数
    System.out.println(m);
    System.out.println(Arrays.toString(b)); //每次读取后的字节数组内容,数组大小是初始化时侯定好的,没有读到数据的元素是默认值0
    System.out.println(new String(b));      //字节数组转为String,这一次不会乱码,因为字节数组完整接收了整个中文汉字
    i++;
}
fis.close();	//关流

FileOutputStream fos = new FileOutputStream("C:\\Users\\Coolway26\\Desktop\\ceshiOut.txt", true);
fos.write(99);

byte[] bytes = "这是一个测试".getBytes();
fos.write(bytes);

fos.close();


//举例:文件通过流进行复制
//方式一:一次性读取和写入,弊端:有可能会内存溢出----所以应该定义较小的数组进行流的操作
FileInputStream fis = new FileInputStream("C:\\Users\\Coolway26\\Desktop\\ceshi.txt");
FileOutputStream fos = new FileOutputStream("C:\\Users\\Coolway26\\Desktop\\ceshiOut.txt");
byte[] arr = new byte[fis.available()];	//根据文件大小做一个字节数组
fis.read(arr);	   //将文件上的所有字节读取到数组中,返回值是读入的有效字节个数
fos.write(arr);    //将数组中的所有字节一次写到了文件上,返回值是读出的有效字节个数
fis.close();
fos.close();
//方式二:通过小数组操作,这种方式很重要,通常开发中需要生成缓存文件,或者向云服务器上传文件,会使用这种方式
FileInputStream fis = new FileInputStream("C:\\Users\\Coolway26\\Desktop\\ceshi.txt");
FileOutputStream fos = new FileOutputStream("C:\\Users\\Coolway26\\Desktop\\ceshiOut.txt");
int len;
byte[] arr = new byte[1024 * 8];	//自定义字节数组,1024的整数倍,这是标准形式
while((len = fis.read(arr)) != -1) {
    //fos.write(arr);
    fos.write(arr, 0, len);	        //写出字节数组,只写出有效个字节个数,如果不限制,即使用fos.write(arr),那么最后一次写的时候,可能会写入无效字节0,即若干个空字符
}
fis.close();
fos.close();

4.BufferedInputStream&BufferedOutputStream

通过操作小数组来读写流数据,显然比一次性读取全部,或者单个字节读写,都要可靠,因为既能保证内存不溢出,又能减少磁盘IO次数提高效率

java提供了自带的缓冲流操作BufferedInputStream&BufferedOutputStream,使用缓冲流,我们将不再需要手动定义小数组

关流时,只需要关闭缓冲流

小数组的读写和带Buffered的读取哪个更好

定义小数组如果是8192个字节大小和Buffered比较的话(1024*8)(这是缓冲区的默认大小),定义小数组会略胜一筹,因为读和写操作的是同一个数组,而Buffered操作的是两个数组

BufferedInputStream

BufferedInputStream内置了一个缓冲区(数组),当使用BufferedInputStream中读取一个字节时,BufferedInputStream会一次性从文件中读取8192个, 存在缓冲区中, 返回给程序一个,程序再次读取时, 就不用找文件了, 直接从缓冲区中获取,直到缓冲区中所有的都被使用过, 才重新从文件中读取8192个

获取缓冲输入流

FileInputStream fis = new FileInputStream("C:\\Users\\Coolway26\\Desktop\\ceshi.txt");

BufferedInputStream bis = new BufferedInputStream(fis);

BufferedOutputStream

BufferedOutputStream也内置了一个缓冲区(数组),程序向流中写出字节时,不会直接写到文件,先写到缓冲区中,直到缓冲区写满,BufferedOutputStream才会把缓冲区中的数据一次性写到文件里

获取缓冲输出流

FileOutputStream fos = new FileOutputStream("C:\\Users\\Coolway26\\Desktop\\ceshiOut.txt");

BufferedOutputStream bos = new BufferedOutputStream(fos);

方法

public void flush(); //刷新此缓冲的输出流,这会使所有缓冲的输出字节被写出到底层输出流中,清空了缓冲区,可以继续写入

public void close() throws IOException //关闭缓冲流,关闭前会执行flush()操作

//拷贝文件
FileInputStream fis = new FileInputStream("C:\\Users\\Coolway26\\Desktop\\ceshi.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream("C:\\Users\\Coolway26\\Desktop\\ceshiOut.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
int b;
while ((b = bis.read()) != -1) {
    bos.write(b);
}

bis.close();
bos.close();

//当然,也可以一次性读入多个字节到缓冲流,通常也是这么做的
int len;
byte[] arr = new byte[1024*8];
while ((len = bis.read(arr)) != -1) {
    bos.write(arr, 0, len);
}
bis.close();
bos.close();

5.MultipartFile(springmvc会用到)

WEB接口中接收文件,springmvc提供的简化文件流操作的接口

//如果不使用MultipartFile
public String fileSave(HttpServletRequest request, HttpServletResponse response){
	MultipartHttpServletRequest msr = (MultipartHttpServletRequest) request;
    MultipartFile targetFile = msr.getFile("file");
}
//使用MultipartFile直接接收文件
public String fileSave(MultipartFile file){
    ...
}

//方法
public interface MultipartFile extends InputStreamSource {
	//返回参数的名称
    String getName();
	// 获取源文件的名称
    @Nullable
    String getOriginalFilename();
	// 返回文件的内容类型
    @Nullable
    String getContentType();
	// 判断文件内容是否为空
    boolean isEmpty();
	// 返回文件大小 以字节为单位
    long getSize();
	// 将文件内容转化成一个byte[] 返回
    byte[] getBytes() throws IOException;
	// 返回输入的文件流
    InputStream getInputStream() throws IOException;

    default Resource getResource() {
        return new MultipartFileResource(this);
    }

    void transferTo(File var1) throws IOException, IllegalStateException;
	// 将MultipartFile 转换换成 File 写入到指定路径
    default void transferTo(Path dest) throws IOException, IllegalStateException {
        FileCopyUtils.copy(this.getInputStream(), Files.newOutputStream(dest));
    }
}

//其他
//获取文件名
MultipartFile file = new MultipartFile();
String fileName = file.getOriginalFilename().substring(0,file.getOriginalFilename().lastIndexOf("."))
//获取文件后缀:这个后缀带‘.’如:.zip,如果不想带‘.’这样即可lastIndexOf(".")+1
MultipartFile file = new MultipartFile();
String fileSuffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."))

6.零拷贝(拓展了解,可以不掌握)

传统IO:一共需要拷贝四次,两次CPU拷贝,两次DMA拷贝

read():把数据从磁盘读到内核缓冲区,从内核缓冲区再拷贝到用户缓冲区

write():把数据写入socket缓冲区,最后写入网卡设备

零拷贝:进行数据IO时,数据在用户态下经历了零次CPU拷贝

缺点:零拷贝有一个缺点,不允许进程对文件内容作一些加工再发送,比如数据压缩后再发送

#mmap+write
try {
    FileChannel readChannel = FileChannel.open(Paths.get("./jay.txt"), StandardOpenOption.READ);
    MappedByteBuffer data = readChannel.map(FileChannel.MapMode.READ_ONLY, 0, 1024 * 1024 * 40);
    FileChannel writeChannel = FileChannel.open(Paths.get("./siting.txt"), StandardOpenOption.WRITE, StandardOpenOption.CREATE);
    //数据传输
    writeChannel.write(data);
    readChannel.close();
    writeChannel.close();
}catch (Exception e){
    System.out.println(e.getMessage());
}

#sendfile
try {
    FileChannel readChannel = FileChannel.open(Paths.get("./jay.txt"), StandardOpenOption.READ);
    long len = readChannel.size();
    long position = readChannel.position();
    
    FileChannel writeChannel = FileChannel.open(Paths.get("./siting.txt"), StandardOpenOption.WRITE, StandardOpenOption.CREATE);
    //数据传输
    readChannel.transferTo(position, len, writeChannel);
    readChannel.close();
    writeChannel.close();
} catch (Exception e) {
    System.out.println(e.getMessage());
}
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

哨兵1号回波数据(L0级)产品目录介绍

1 数据包总览 哨兵1号L0级数据产品系列如下图所示,本文针对图中红框中的数据产品进行介绍(定标数据、噪声数据没下载到。。。)。 1.1 数据包名称 示例: S1A_S3_RAW__0SSV_20211230T105851_20211230T105907_041237_04E698_94F0.S…

github私有仓库开发,公开仓库发布版本

文章目录 github私有仓库开发,公开仓库发布版本需求背景实现思路GitHub Releases具体步骤广告 github私有仓库开发,公开仓库发布版本 需求背景 github私有仓库开发,公开仓库发布版本,既可以保护源代码,又可以发布版本给用户使用。许多知名软件项目都采用了这样的开…

Qt 子窗口不设置parent时,如何随主窗口关闭

遇到个情况,new一个子窗口的时候,如果指定了parent,那在最小化这个子窗口时这个子窗口并不是在缩小到任务栏,而是在任务栏的左上角。像这种: 并且,点击主窗口之后,子窗口也始终显示在主窗口之前…

视频批量剪辑:视频嵌套合并实战指南,剪辑高手速成秘籍

随着社交媒体的兴起,视频制作的需求越来越广泛。无论是个人用户还是专业团队,都需要对视频进行剪辑以符合其需求。而在这个过程中,批量剪辑视频的能力就变得至关重要。视频批量剪辑是指在一次操作中处理多个视频文件的剪辑。通过使用专业的视…

《软件工程与计算》期末考试真题范例及答案

今天分享一套针对《软件工程与计算》这本书的真题案例,有关《软件工程与计算》23章内容的重点知识整理,已经总结在了博客专栏中,有需要的自行阅读: 《软件工程与计算》啃书总结https://blog.csdn.net/jsl123x/category_12468792.…

Dubbo快速入门

1.什么是Dubbo? Dubbo是一款高性能分布式服务框架,由阿里巴巴开发并开源发布。它支持多种协议,如dubbo、HTTP、Hessian、Thrift等,可以很好地解决分布式服务中的服务治理问题,提供了服务注册、发现、负载均衡、容错等功…

第26章_事务概述与隔离级别

文章目录 事务事务的特征事务的控制语句事务的生命周期事务的执行过程 ACID特性原子性一致性隔离性持久性 隔离级别不同隔离级别并发异常脏读不可重复读幻读区别 总结 事务 (1)事务的前提:并发连接访问。MySQL的事务就是将多条SQL语句作为整…

伦敦金股票代码是什么?

伦敦金是跟踪实时的现货黄金价格走势的差价合约交易,它的代码一般是LLG、GOLD,但也有一些货币交易平台会显示为XAU。伦敦金不是股票交易,因此没有四位数或六位数的股票代码,但伦敦金交易品种单一,投资者不用在数千支股…

路径规划-车辆分配及导航

1.根据城市之间的连通状态,构建以城市为结点、两个城市间的距离(根据两个城市经纬度计算的欧式距离)作为边权重的无向图。 2.根据起始点,对除了起始点之外的其他点进行聚类,将点划分成几个部分。 3.在每个部分中找出…

SpringBoot Web开发

SpringBoot3-Web开发 SpringBoot的Web开发能力,由SpringMVC提供。 Web开发的三种方式 方式处理过程注意事项实现效果全自动直接编写控制逻辑全部使用自动给配置默认效果手自一体Configuration、 配置WebMvcConfigurer、 配置WebMvcRegistrations不要标注 EnableWeb…

matlab模糊控制文件m代码实现和基础理论

1、内容简介 略 15-可以交流、咨询、答疑 通过m代码来实现生成模糊文件fis文件 2、内容说明 模糊文件m代码实现和基础理论 matlab模糊控制文件m代码实现和基础理论 模糊文件、m代码和模糊基础理论 3、仿真分析 略 4、参考论文 略 链接:https://pan.baidu.co…

【C++】非类型模板参数 | array容器 | 模板特化 | 模板为什么不能分离编译

目录 一、非类型模板参数 二、array容器 三、模板特化 为什么要对模板进行特化 函数模板特化 补充一个问题 类模板特化 全特化与偏特化 全特化 偏特化 四、模板为什么不能分离编译 为什么 怎么办 五、总结模板的优缺点 一、非类型模板参数 模板参数分两类&#x…

【MongoDB】索引 – 文本索引(用权重控制搜索结果)

一、准备工作 这里准备一些数据 db.books.drop();db.books.insert({_id: 1, name: "Java", alias: "java 入门", description: "入门图书" }); db.books.insert({_id: 2, name: "C", alias: "c", description: "C 入…

[护网杯 2018]easy_tornado 1(两种解法!)

题目环境:发现有三个txt文本文件 /flag.txt/welcome.txt/hints.txt 依此点开 flag在/fllllllllllllag文件中 在hints.txt文件中发现md5计算 md5(cookie_secretmd5(filename)) 并且三个文件中都存在filehash(文件名被哈希算法加密32位小写) 猜…

轻量封装WebGPU渲染系统示例<23>- 可渲染对象添加到多个渲染器Pass节点(源码)

渲染和计算混合系统, 可以看做基于算力驱动设计理念的一种实现。 此系统中,可渲染(rendering)/计算(computing)实体可以任意添加到一个渲染器pass节点。若干个这样的节点相关联,就能构成对应的pass node graph,也就实现了整个3D渲…

CS224W6.2——深度学习基础

在本文中,我们回顾了深度学习的概念和技术,这些概念和技术对理解图神经网络至关重要。从将机器学习表述为优化问题开始,介绍了目标函数、梯度下降、非线性和反向传播的概念。 文章目录 1. 大纲2. 优化问题2.1 举例损失函数 3. 如何优化目标函…

【FISCO BCOS】十九、区块链浏览器部署

目录 一、环境依赖 检查环境 1.检查java 二、拉取安装脚本 获取部署安装包 ​编辑 解压安装包 进入目录 三、修改配置 四、部署服务 五、状态检查 检查前后端进程 1.检查后端server进程 2.检查前端的nginx进程 检查进程端口 六、使用区块链浏览器 1.配置群组…

(二)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB

一、七种算法(DBO、LO、SWO、COA、LSO、KOA、GRO)简介 1、蜣螂优化算法DBO 蜣螂优化算法(Dung beetle optimizer,DBO)由Jiankai Xue和Bo Shen于2022年提出,该算法主要受蜣螂的滚球、跳舞、觅食、偷窃和繁…

HarmonyOS 高级特性

引言 本章将探讨 HarmonyOS 的高级特性,包括分布式能力、安全机制和性能优化。这些特性可以帮助你构建更强大、更安全、更高效的应用。 目录 HarmonyOS 的分布式能力HarmonyOS 的安全机制HarmonyOS 的性能优化总结 1. HarmonyOS 的分布式能力 HarmonyOS 的分布…

Zabbix监控SSL证书有效期

一、介绍 由于业务需要,最近通过 Let’s Encrypt 申请了一些 SSL 证书,而证书有效期为 3 个月,需要在证书到期之前 renew。由于域名较多经常忘记 renew,导致证书过期,因此想通过 Zabbix 的方式监控证书的到期时间&…
最新文章