小师妹学JavaIO之:文件写入那些事
简介
小师妹又对F师兄提了一大堆奇奇怪怪的需求,要格式化输出,要特定的编码输出,要自己定位输出,什么?还要阅后即焚?大家看F师兄怎么一一接招吧。
字符输出和字节输出
小师妹:F师兄,上次你的IO讲到了一半,文件读取是基本上讲完了,但是文件的写入还没有讲,什么时候给小师妹我再科普科普?
小师妹:F师兄,你知道我这个人一直以来都是勤奋好学的典范,是老师们眼中的好学生,同学们心中的好榜样,父母身边乖巧的好孩子。在我永攀科学高峰的时候,居然发现还有一半的知识没有获取,真是让我扼腕叹息,F师兄,快快把知识传给我吧。
小师妹你的请求,师兄我自当尽力办到,但是我怎么记得上次讲IO文件读取已经过了好几天了,怎么今天你才来找我。
小师妹红着脸:F师兄,这不是使用的时候遇到了点问题,才想找你把知识再复习一遍。
更多精彩内容且看:
- 区块链从入门到放弃系列教程-涵盖密码学,超级账本,以太坊,Libra,比特币等持续更新
- Spring Boot 2.X系列教程:七天从无到有掌握Spring Boot-持续更新
- Spring 5.X系列教程:满足你对Spring5的一切想象-持续更新
- java程序员从小工到专家成神之路(2020版)-持续更新中,附详细文章教程
那先把输出类的结构再过一遍:
上面就是输出的两大系统了:Writer和OutputStream。
Writer主要针对于字符,而Stream主要针对Bytes。
Writer中最最常用的就是FileWriter和BufferedWriter,我们看下一个最基本写入的例子:
public void useBufferedWriter() throws IOException {
String content = "www.flydean.com";
File file = new File("src/main/resources/www.flydean.com");
FileWriter fw = new FileWriter(file);
try(BufferedWriter bw = new BufferedWriter(fw)){
bw.write(content);
}
}
BufferedWriter是对FileWriter的封装,它提供了一定的buffer机制,可以提高写入的效率。
其实BufferedWriter提供了三种写入的方式:
public void write(int c)
public void write(char cbuf[], int off, int len)
public void write(String s, int off, int len)
第一个方法传入一个int,第二个方法传入字符数组和开始读取的位置和长度,第三个方法传入字符串和开始读取的位置和长度。是不是很简单,完全可以理解?
小师妹:不对呀,F师兄,后面两个方法的参数,不管是char和String都是字符我可以理解,第一个方法传入int是什么鬼?
小师妹,之前跟你讲的道理是不是都忘记的差不多了,int的底层存储是bytes,char和String的底层存储也是bytes,我们把int和char做个强制转换就行了。我们看下是怎么转换的:
public void write(int c) throws IOException {
synchronized (lock) {
ensureOpen();
if (nextChar >= nChars)
flushBuffer();
cb[nextChar++] = (char) c;
}
}
还记得int需要占用多少个字节吗?4个,char需要占用2个字节。这样强制从int转换到char会有精度丢失的问题,只会保留低位的2个字节的数据,高位的两个字节的数据会被丢弃,这个需要在使用中注意。
看完Writer,我们再来看看Stream:
public void useFileOutputStream() throws IOException {
String str = "www.flydean.com";
try(FileOutputStream outputStream = new FileOutputStream("src/main/resources/www.flydean.com");
BufferedOutputStream bufferedOutputStream= new BufferedOutputStream(outputStream)){
byte[] strToBytes = str.getBytes();
bufferedOutputStream.write(strToBytes);
}
}
跟Writer一样,BufferedOutputStream也是对FileOutputStream的封装,我们看下BufferedOutputStream中提供的write方法:
public synchronized void write(int b)
public synchronized void write(byte b[], int off, int len)
比较一下和Writer的区别,BufferedOutputStream的方法是synchronized的,并且BufferedOutputStream是直接对byte进行操作的。
第一个write方法传入int参数也是需要进行截取的,不过这次是从int转换成byte。
格式化输出
小师妹:F师兄,我们经常用的System.out.println可以直接向标准输出中输出格式化过后的字符串,文件的写入是不是也有类似的功能呢?
肯定有,PrintWriter就是做格式化输出用的:
public void usePrintWriter() throws IOException {
FileWriter fileWriter = new FileWriter("src/main/resources/www.flydean.com");
try(PrintWriter printWriter = new PrintWriter(fileWriter)){
printWriter.print("www.flydean.com");
printWriter.printf("程序那些事 %s ", "非常棒");
}
}
输出其他对象
小师妹:F师兄,我们看到可以输出String,char还有Byte,那可不可以输出Integer,Long等基础类型呢?
可以的,使用DataOutputStream就可以做到:
public void useDataOutPutStream()
throws IOException {
String value = "www.flydean.com";
try(FileOutputStream fos = new FileOutputStream("src/main/resources/www.flydean.com")){
DataOutputStream outStream = new DataOutputStream(new BufferedOutputStream(fos));
outStream.writeUTF(value);
}
}
DataOutputStream提供了writeLong,writeDouble,writeFloat等等方法,还可以writeUTF!
在特定的位置写入
小师妹:F师兄,有时候我们不需要每次都从头开始写入到文件,能不能自定义在什么位置写入呢?
使用RandomAccessFile就可以了:
public void useRandomAccess() throws IOException {
try(RandomAccessFile writer = new RandomAccessFile("src/main/resources/www.flydean.com", "rw")){
writer.seek(100);
writer.writeInt(50);
}
}
RandomAccessFile可以通过seek来定位,然后通过write方法从指定的位置写入。
给文件加锁
小师妹:F师兄,最后还有一个问题,怎么保证我在进行文件写的时候别人不会覆盖我写的内容,不会产生冲突呢?
FileChannel可以调用tryLock方法来获得一个FileLock锁,通过这个锁,我们可以控制文件的访问。
public void useFileLock()
throws IOException {
try(RandomAccessFile stream = new RandomAccessFile("src/main/resources/www.flydean.com", "rw");
FileChannel channel = stream.getChannel()){
FileLock lock = null;
try {
lock = channel.tryLock();
} catch (final OverlappingFileLockException e) {
stream.close();
channel.close();
}
stream.writeChars("www.flydean.com");
lock.release();
}
}
总结
今天给小师妹讲了好多种文件的写的方法,够她学习一阵子了。
本文的例子https://github.com/ddean2009/learn-java-io-nio
本文作者:flydean程序那些事
本文链接:http://www.flydean.com/io-file-writer/
本文来源:flydean的博客
欢迎关注我的公众号:程序那些事,更多精彩等着您!
小师妹学JavaIO之:文件写入那些事的更多相关文章
- 小师妹学JavaIO之:文件系统和WatchService
目录 简介 监控的痛点 WatchService和文件系统 WatchSerice的使用和实现本质 总结 简介 小师妹这次遇到了监控文件变化的问题,F师兄给小师妹介绍了JDK7 nio中引入的Watc ...
- 小师妹学JavaIO之:文件File和路径Path
简介 文件和路径有什么关系?文件和路径又隐藏了什么秘密?在文件系统的管理下,创建路径的方式又有哪些?今天F师兄带小师妹再给大家来一场精彩的表演. 文件和路径 小师妹:F师兄我有一个问题,java中的文 ...
- 小师妹学JavaIO之:MappedByteBuffer多大的文件我都装得下
目录 简介 虚拟地址空间 详解MappedByteBuffer MapMode MappedByteBuffer的最大值 MappedByteBuffer的使用 MappedByteBuffer要注意 ...
- 小师妹学JavaIO之:目录还是文件
目录 简介 linux中的文件和目录 目录的基本操作 目录的进阶操作 目录的腰疼操作 总结 简介 目录和文件傻傻分不清楚,目录和文件的本质到底是什么?在java中怎么操纵目录,怎么遍历目录.本文F师兄 ...
- 小师妹学JavaIO之:用Selector来发好人卡
目录 简介 Selector介绍 创建Selector 注册Selector到Channel中 SelectionKey selector 和 SelectionKey 总的例子 总结 简介 NIO有 ...
- 小师妹学JavaIO之:NIO中Channel的妙用
目录 简介 Channel的分类 FileChannel Selector和Channel DatagramChannel SocketChannel ServerSocketChannel Asyn ...
- 小师妹学JavaIO之:Buffer和Buff
目录 简介 Buffer是什么 Buffer进阶 创建Buffer Direct VS non-Direct Buffer的日常操作 向Buffer写数据 从Buffer读数据 rewind Buff ...
- 小师妹学JavaIO之:NIO中那些奇怪的Buffer
目录 简介 Buffer的分类 Big Endian 和 Little Endian aligned内存对齐 总结 简介 妖魔鬼怪快快显形,今天F师兄帮助小师妹来斩妖除魔啦,什么BufferB,Buf ...
- 小师妹学IO系列文章集合-附PDF下载
目录 第一章 IO的本质 IO的本质 DMA和虚拟地址空间 IO的分类 IO和NIO的区别 总结 第二章 try with和它的底层原理 简介 IO关闭的问题 使用try with resource ...
- 小师妹学JVM之:JVM的架构和执行过程
目录 简介 JVM是一种标准 java程序的执行顺序 JVM的架构 类加载系统 运行时数据区域 执行引擎 总结 简介 JVM也叫Java Virtual Machine,它是java程序运行的基础,负 ...
随机推荐
- defaultdict高级用法
说明 defaultdict数据结构允许调用者提供一个函数,用来在键名缺失的情况下,创建与这个 键对应的值.只要字典发现调用者想要访问的键不存在,就会触发这个函数,以返回应该 与键相关联的默认值 下面 ...
- ContentType组件表使用
https://www.shuzhiduo.com/A/qVdepN2r5P/
- 【C++ OOP 01】封装
封装 封装的意义 封装是C++面向对象三大特性之一 封装的意义: 将属性和行为作为一个整体,表现生活中的事物 将属性和行为加以权限控制 封装意义一 在设计类的时候,属性和行为写在一起,表现事物 语 ...
- 【Azure 应用服务】App Service中抓取 Web Job 的 DUMP 办法
问题描述 使用Azure App Service,也可以部署一个Java程序作为Web Job运行.运行一个 .Jar 文件只需要以下4步: 1)把Java应用打包成一个 .jar 文件 2)创建一个 ...
- 【Azure 微服务】Azure Service Fabric 因证书问题而使得 Node 一直处于 Down 状态
问题描述 Service Fabric 集群更新证书后,重启Node后就变为Down的状态,反复 Restart 结果反复Down 问题分析 根据Service Fabric的文档表示,修改证书时一定 ...
- opencv库图像基础4绘图-python
opencv库图像基础4绘图-python 1.绘画线条和简单图形 创建颜色字典和一个画布 import cv2 import numpy as np import matplotlib.pyplot ...
- 四: Mysql用户管理
# 用户与权限管理 MySQL用户可以分为普通用户和root用户, root用户是超级管理员,拥有所有权限,包括创建用户.删除用户和修改用户的密码等管理权限:普通用户只拥有被授予的各种权限. MySQ ...
- java项目-尚硅谷项目三员工调度系统
导入工具类和数据 创建TeamSchedule项目,com.atguigu.team. view,com.atguigu.team.service,com.atguigu.team.domain包 , ...
- [学习笔记].Net5项目打包到Linux系统服务时遇到的坑
如果按照官方文档的步骤手动安装.Net5 会有一个坑: 在 Linux 上手动安装 .NET - .NET | Microsoft Docs 在使用systemd打包.Net5服务的时候,无法运行, ...
- java服务OOM和CPU飙升排查
一.JVM参数 -D 可以是系统默认有的参数,也可以是自己定义的参数 -Dfile.encoding=UTF-8 -Dmaven.test.skip=true -Dspring.profiles.ac ...