前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >关于NIO与Socket编程技术指南 “验证 write(ByteBuffer src, long position)方法中的 position 不变性”的不严谨问题

关于NIO与Socket编程技术指南 “验证 write(ByteBuffer src, long position)方法中的 position 不变性”的不严谨问题

作者头像
johnhuster的分享
发布2022-03-29 14:53:40
2860
发布2022-03-29 14:53:40
举报
文章被收录于专栏:johnhuster

NIO与Socket编程技术指南2018.7版中第 2 章通道和 FileChannel 类的使用(第130页)

关于“验证 write(ByteBuffer src, long position)方法中的 position 不变性的”不够严谨,首先贴出该书中的示例代码,file.txt中笔者存了123。

代码语言:javascript
复制
@Test
	public void writeAtPos()throws  IOException{
		FileOutputStream fos = new FileOutputStream("d:/tmp/file.txt");
		FileChannel fc = fos.getChannel();
		println(fc.position());
		fc.position(3);
		println(fc.position());
		ByteBuffer buffer = ByteBuffer.wrap("hahhahah哈哈".getBytes("utf-8"));
		fc.write(buffer,0);
		println(fc.position());
	}

上面代码输出结果如下:

代码语言:javascript
复制
0
 3
 3

从上面这个例子来看确实如“NIO与Socket编程技术指南”这本书说的一样,完全没有问题,接下来看下面这个例子:

代码语言:javascript
复制
	@Test
	public void writeAtPos2()throws  IOException{
		FileOutputStream fos = new FileOutputStream("d:/tmp/file.txt",true);
		FileChannel fc = fos.getChannel();
		println(fc.position());
		fc.position(3);
		println(fc.position());
		ByteBuffer buffer = ByteBuffer.wrap("hahhahah哈哈".getBytes("utf-8"));
		fc.write(buffer,0);
		println(fc.position());
	}

上面代码输出结果如下:

代码语言:javascript
复制
6
 6
 14

之所以说“NIO与Socket编程技术指南”这本书关于这部分的说法不严谨,在于FileOutputStream 是否以追加模式创建,将会影响

position()方法返回结果,更准确来说应该是write(ByteBuffer src, long position)方法不影响底层文件游标位置,但是FileChannel的position返回值却不一定了!!!

关于FileChannel的position方法可以参考FileChannelImpl的position实现:

代码语言:javascript
复制
public long position() throws IOException {
        this.ensureOpen();
        synchronized(this.positionLock) {
            long var2 = -1L;
            int var4 = -1;

            long var5;
            try {
                this.begin();
                var4 = this.threads.add();
                if (this.isOpen()) {
                    do {
                        //要注意的是针对追加模式打开的文件,position返回的是文件的整体大小而不是FileChannel的当前位置!!!!
                        var2 = this.append ? this.nd.size(this.fd) : this.nd.seek(this.fd, -1L);
                    } while(var2 == -3L && this.isOpen());

                    var5 = IOStatus.normalize(var2);
                    return var5;
                }

                var5 = 0L;
            } finally {
                this.threads.remove(var4);
                this.end(var2 > -1L);

                assert IOStatus.check(var2);

            }

            return var5;
        }
    }

PS:

为了加深这个知识点,建议参考下笔者的另一篇文章:https://blog.csdn.net/john1337/article/details/105114551

position方法会有影响底层文件游标位置,但是却不一定影响文件实际写入位置(也是区分追加模式)。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/03/28 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档