Java基础Demo -- NIO读文件

本文介绍了Java NIO的基础知识,包括通道、缓冲区的使用,字符集的概念,以及NIO在处理文件时的工具类如Path、Files和BasicFileAttributes。还探讨了在处理不同系统换行符和中文乱码问题时的注意事项,并强调了在处理大文件时采用分段读取的重要性。
摘要由CSDN通过智能技术生成

NIO:

  • 通道 read write
  • 缓冲区 put get
  • 字符集
  • 选择器
  • Path接口
  • Files工具类
  • BasicFileAttributes文件属性类

/*
* NIO:不是替代IO,是对IO的一种补充,可以更精细的管控流和访问文件系统
*
* 通道 :  读取/写入流的通道类 getChannel()方法 支持通道的类有:FileInputStream
*               FileOutputStream Socket 常用方法有:读read() 写write()
* 缓冲区:依托通道--从流中读出的内容可放置缓冲区,缓冲区内的内容可写入流,常用缓冲区
*               ByteBuffer ...等对应7种基本类型的,以及 MappedByteBuffer用于将文件映射
*               到缓冲区,缓冲区的三大要素:当前位置、界限、容量。常用方法有:
*               容量capacity() 清空clear() 位置position() 重置rewind() 界限limit()  
*               写put() 读get() 分配allocate() 切分slice()
* 字符集:依托字符集,将字节映射成字符 例如:UTF-8 GBK
* 选择器:适用于套接字的通道,使用选择器可以通过多个通道执行IO
*/

/**
* jdk7 增加了Path Files BasicFileAttributes
*
* Path接口:封装了路径,提供了操作路径的大量方法. Path的toFile()<-互转->File的toPath()
*                   获取Path的方法:Paths.get(String pathname,String...parts); Paths.get(URI uri);
*
* Files工具类:更加细腻的管控文件的大量方法.
*              常用方法有:
*              删除delete() 创建目录createDirectory() 创建文件createFile() 是否存在exists()
*              是否目录isDirectory() 是否文件isRegularFile() 文件大小size()
*              文件属性readAttributes() 是否可读isReadable() 是否可写isWritable()
*              是否隐藏的isHidden() 是否可执行的isExecutable() 文件拷贝copy() 文件移动move()
*              文件的流对象newInputStream() newOutputStream() 获取文件通道newByteChannel()
*
*              OpenOption文件打开时的一些选项:枚举值有:APPEND追加写入
*                                                        CREATE_NEW文件不存在时就创建
*                                                        CREATE老文件要有就干掉,创建新的
*
*              jdk8中该类新增4个方法 list() walk() lines() find() 都返回Stream流
*
* 文件属性类:BasicFileAttributes 常用方法有:
*                                 文件创建时间createTime() 是否目录isDirectory()
*                                 文件最后修改时间lastModifiedTime() 是否文件isRegularFile()
*                                 文件最后访问时间lastAccessTime() 文件大小size()                           
*/

/**
* BufferUnderflowException BufferOverflowException 错误原因:读取的长度超出了允许的长度
*
* 例如下面的代码:
* ByteBuffer buf = ByteBuffer.allocate(2); /这里只分配了2个字节
* buf.order(ByteOrder.LITTLE_ENDIAN);
* byte[] tmp = new byte[3]; 
* buf.get(tmp); //这里get了3个字节的数据,java.nio.BufferUnderflowException异常
*
* 如何解决这个问题呢?添加读取长度与 ByteBuffer 中可读取的长度的判断:例如:
* while (buf.remaining() > 0) {    //每次读1个字节,就判断大于0;每次读2个字节,就判断大于1       
*      byte b = buf.get();        
* }
*
* 总结:
* 当 ByteBuffer.remaining() 小于要读取或写入的长度时,再执行读取或写入操作都会产生异常;
*      读取则产生 java.nio.BufferUnderflowException 异常
*      写入则产生 java.nio.BufferOverflowException 异常
* 当 ByteBuffer.remaining()==0 时,不能再执行读取或写入操作
*/

/**
* \r 回车键   十进制表示为13 十六进制0x0D
* \n 换行键  十进制表示为10 十六进制0x0A
* windows系统 文件内容中的换行是\r\n
* unix系统        文件内容中的换行是/n
* mac系统        文件内容中的换行是/r
*/

/**
* 基于通道读文件
* 一般步骤:
* a:封装Path
* b:获取通道getChannel(path)
* c:准备缓冲区Buffer
* d:通过通道读写文件fChannel.read(buf); fChannel.write(buf);
*/

import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.file.*;
import java.util.*;


//测试
public class NIOdemo 
{

    /**
    * 通过缓冲区以及通道,实现读文件(读ISO8859-1格式的文件可以,读UTF/GBK格式保存的文件很麻烦)
    */
    public static void readFileByByteBufferAndChannel(){

	int count=0; //读写缓冲区时,缓冲区内部的游标不停的向前滚动,表示已经读到了多少个字节
	int j=0; //第几次缓冲区已满
		
        try(SeekableByteChannel fchan = Files.newByteChannel(Paths.get("test.txt")) ){ //获取通道
	/*举例: 假定当前测试文件保存20个英文字母,系统默认ASNI编码格式,两行数据保存的. windows下换行时有(回车)(换行)两个字节,所以内容大小22
	System.out.println("test.txt文件的内容:0123456789\\r\\naaaaaaaaaa (文件的大小:"+fchan.size()+") 其中: \\r回车一个字节 \\n换行一个字节"); 
	System.out.println("文件内容windows下分成两行保存的,采用ASNI编码格式,如下:"); 
	System.out.println("0123456789"); 
	System.out.println("aaaaaaaaaa"); 
	*/
			
	long fSize = fchan.size();
	String fileEncoding = judgeFileEncoding();

	ByteBuffer buf = ByteBuffer.allocate(10); //准备缓冲区

	byte[] tmpB = new byte[2]; //临时存放中文字符截断的前序字节(编码不同,有可能前序就1个字节,也有可能前序2个字节)
	int k = 0; //计数器:临时保存上一字节的次数

	/**
	* buf.rewind()方法:为什么使用?因为想游标重置后,从缓冲区头开始干活(对buf的读/写都是时刻往后滚动游标的)
	*/
	do{
	    ++j; //第几次从文件流读至缓冲区

	    buf.rewind(); //buf重置游标,归零处,为了从缓冲区头开始写
	    count = fchan.read(buf);

	    //System.out.println("\r\n当前第("+j+"
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值