加入收藏 | 设为首页 | 会员中心 | 我要投稿 北几岛 (https://www.beijidao.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

小师妹学JavaIO之:文件写入那些事

发布时间:2021-05-21 08:22:43 所属栏目:大数据 来源: https://www.jb51.cc
导读:@H_502_0@ 目录 简介 字符输出和字节输出 格式化输出 输出其他对象 在特定的位置写入 给文件加锁 总结 @H_502_0@ 简介 @H_502_0@小师妹又对F师兄提了一大堆奇奇怪怪的需求,要格式化输出,要特定的编码输出,要自己定位输出,什么?还要阅后即焚?大家看F师兄
@H_502_0@

目录
  • 简介
  • 字符输出和字节输出
  • 格式化输出
  • 输出其他对象
  • 在特定的位置写入
  • 给文件加锁
  • 总结
@H_502_0@

简介

@H_502_0@小师妹又对F师兄提了一大堆奇奇怪怪的需求,要格式化输出,要特定的编码输出,要自己定位输出,什么?还要阅后即焚?大家看F师兄怎么一一接招吧。

字符输出和字节输出

@H_502_0@小师妹:F师兄,上次你的IO讲到了一半,文件读取是基本上讲完了,但是文件的写入还没有讲,什么时候给小师妹我再科普科普?

@H_502_0@小师妹:F师兄,你知道我这个人一直以来都是勤奋好学的典范,是老师们眼中的好学生,同学们心中的好榜样,父母身边乖巧的好孩子。在我永攀科学高峰的时候,居然发现还有一半的知识没有获取,真是让我扼腕叹息,F师兄,快快把知识传给我吧。

@H_502_0@小师妹你的请求,师兄我自当尽力办到,但是我怎么记得上次讲IO文件读取已经过了好几天了,怎么今天你才来找我。

@H_502_0@小师妹红着脸:F师兄,这不是使用的时候遇到了点问题,才想找你把知识再复习一遍。

@H_502_0@更多精彩内容且看:

  • 区块链从入门到放弃系列教程-涵盖密码学,超级账本,以太坊,Libra,比特币等持续更新
  • Spring Boot 2.X系列教程:七天从无到有掌握Spring Boot-持续更新
  • Spring 5.X系列教程:满足你对Spring5的一切想象-持续更新
  • java程序员从小工到专家成神之路(2020版)-持续更新中,附详细文章教程
@H_502_0@那先把输出类的结构再过一遍:

@H_502_0@

@H_502_0@

@H_502_0@上面就是输出的两大系统了:Writer和OutputStream。

@H_502_0@Writer主要针对于字符,而Stream主要针对Bytes。

@H_502_0@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);
        }
    }
@H_502_0@BufferedWriter是对FileWriter的封装,它提供了一定的buffer机制,可以提高写入的效率。

@H_502_0@其实BufferedWriter提供了三种写入的方式:

public void write(int c)
public void write(char cbuf[],int off,int len)
public void write(String s,int len)
@H_502_0@第一个方法传入一个int,第二个方法传入字符数组和开始读取的位置和长度,第三个方法传入字符串和开始读取的位置和长度。是不是很简单,完全可以理解?

@H_502_0@小师妹:不对呀,F师兄,后面两个方法的参数,不管是char和String都是字符我可以理解,第一个方法传入int是什么鬼?

@H_502_0@小师妹,之前跟你讲的道理是不是都忘记的差不多了,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;
        }
    }
@H_502_0@还记得int需要占用多少个字节吗?4个,char需要占用2个字节。这样强制从int转换到char会有精度丢失的问题,只会保留低位的2个字节的数据,高位的两个字节的数据会被丢弃,这个需要在使用中注意。

@H_502_0@看完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);
        }
    }
@H_502_0@跟Writer一样,BufferedOutputStream也是对FileOutputStream的封装,我们看下BufferedOutputStream中提供的write方法:

public synchronized void write(int b)
public synchronized void write(byte b[],int len)
@H_502_0@比较一下和Writer的区别,BufferedOutputStream的方法是synchronized的,并且BufferedOutputStream是直接对byte进行操作的。

@H_502_0@第一个write方法传入int参数也是需要进行截取的,不过这次是从int转换成byte。

格式化输出

@H_502_0@小师妹:F师兄,我们经常用的System.out.println可以直接向标准输出中输出格式化过后的字符串,文件的写入是不是也有类似的功能呢?

@H_502_0@肯定有,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 ","非常棒");
        }
    }

输出其他对象

@H_502_0@小师妹:F师兄,我们看到可以输出String,char还有Byte,那可不可以输出Integer,Long等基础类型呢?

@H_502_0@可以的,使用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);
        }
    }
@H_502_0@DataOutputStream提供了writeLong,writeDouble,writeFloat等等方法,还可以writeUTF!

在特定的位置写入

@H_502_0@小师妹:F师兄,有时候我们不需要每次都从头开始写入到文件,能不能自定义在什么位置写入呢?

@H_502_0@使用RandomAccessFile就可以了:

public void useRandomAccess() throws IOException {
        try(RandomAccessFile writer = new RandomAccessFile("src/main/resources/www.flydean.com","rw")){
            writer.seek(100);
            writer.writeInt(50);
        }
    }
@H_502_0@RandomAccessFile可以通过seek来定位,然后通过write方法从指定的位置写入。

给文件加锁

@H_502_0@小师妹:F师兄,最后还有一个问题,怎么保证我在进行文件写的时候别人不会覆盖我写的内容,不会产生冲突呢?

@H_502_0@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();
        }
    }

总结

@H_502_0@今天给小师妹讲了好多种文件的写的方法,够她学习一阵子了。

@H_502_0@本文的例子https://github.com/ddean2009/learn-java-io-nio

@H_502_0@本文作者:flydean程序那些事

@H_502_0@本文链接:http://www.flydean.com/io-file-writer/

@H_502_0@本文来源:flydean的博客

@H_502_0@欢迎关注我的公众号:程序那些事,更多精彩等着您!

(编辑:北几岛)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读