java IO流总结

                                java IO

字节流和字符流

InputStream(字节流)和Reader(字符流)是所有输入流的基类,本身不能创建实例来实现,但是是所有输入流的模板它们提供的方法所有的流都可以使用

OutPutStream(字节流) 与write (字符流)分别是按字节,与字符操作流中的数据。

java IO流执行输出时,不要忘记关闭关闭,关闭输出流除了可以保证流的物理资源被回收之外,可能还可以将文件缓冲区中的数据flush到物理结点(因为在执行clos ()后, 自动输出流的flush ()方法)。

如果希直接输出字符串的内容,则使用Write会有更好的效果

public class PrintStreamTest {

public static void main(String[] args) {

try {

FileOutputStream ps = new FileOutputStream("b.txt");

PrintWriter pw = new PrintWriter(ps);// printWrite对文件输出流进行包装

pw.print("hello b.txt");

pw.close();

} catch (FileNotFoundException e) {

// TODO 自动生成的 catch 

e.printStackTrace();

}

}

 

}

处理流的使用:

使用处理流的思路:使用处理流包装节点流,程序通过处理流来执行输入输出功能,让结点流与底层I/O设备文件交互。

只要流的构造器参数不是一个物理节点,而是已经存在的流,那么这种流就是一定是处理流,而所有节点流都是直接以物理IO节点作为构造参数的。

一个节点流作为构造器的参数即可,这样创建的处理流就是包装该结点的处理流。

在使用处理流包装底层节点流之后,关闭输入输出流资源时,只要关闭最上层的处理流即可,关闭最上层的处理时,系统会自己关闭该处理流包装了该节点流的处理流。

通常使用中如果要处理的内容是文本内容,则使用字符流,如果进行输入输出的内容是二进制则应使用字节流。

转换流:

转换流用于字符与字节之间的转换,其中InputStreamReadr (将字节流转换为字符流),OutputStreamWrite (将字符流转换为字节流)。

BufferReader BufferedReader 流具有缓冲功能,其可以一次读取一行文本(ReadLine ()方法),以换行符为标志,如果没有读到换行符,程序阻塞,直到读到换行符位置。

RandomAcessFile 

RandomAcessFile :是java输入输出流体系中功能最丰富的文件内容访问类,它既可以读取文件内容,也可以向文件输出数据,与普通的输入输出流不同的是其支持随机访问的方式,程序可以直接跳转到文件任意地方读写文件。

setFilePointer ()返回文件记录指针当前的位置

seek () 将文件记录指针定位到pos位置。

public class RandomAceesFileTest {

public static void main(String[] args) {

try {

System.out.println(System.getProperties());

RandomAccessFile raf = new RandomAccessFile("G:\\a.txt", "r");

System.out.println("文件指针的初始位置"+raf.getFilePointer());

raf.seek(3000); // 将文件指针定位到指定位置(300字节出开始读数据)

byte [] buffer =new byte [1024];

int hasRead = 0 ;

while ((hasRead=raf.read(buffer))!=-1) {  // read返回读取字节的个数

System.out.println(new String (buffer, 0 , hasRead));

System.out.println("已读取字节数"+hasRead);

}

raf.close();

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

// TODO 自动生成的 catch 

e.printStackTrace();

}

}

 

}

当向文件中追加数据时,首先应将记录指针移动到文件最后。

RandomAcessFile依然不能向文件

NIO:前面介绍的输入流输出流都是都是阻塞式的输入输出,不仅如此传统的输入输出都是通过字节的移动来处理的(即使不直接处理字节但底层的实现还是还是依赖于字节的处理)因此一次只能处理一个字节,因此效率不高。

Jdk1.4后增加了提供了一系列改进的输入输出处理的新功能,被称为nio, 这些类都放在java.nio包以及子包下。

javaIO的概述:

 新IO使用了不同的方式来处理输入输出,新IO采用内存映射文件的方式来处理输入输出, 新IO将文件或文件的一端区域映射到内存中,这样就可以向访问内存一样访问文件了,这比传统的处理速度快的多。

ChannelBuffer 是新IO的核心概念,Channle (通道)在新IO中所有的数据都需要通过通道传输,Channel提供了一个map()方法,通过该方法可以可以直接将“一块数据”映射到内存中,传统的输入输出系统是面向流的,则新IO则是面向块的。

Buffer可以被理解为容器,其本质是一个数组,发送到Channel中的所有对象必须首先放到Buffer中,而从Channel中读取的数据也必须放在Bufffer中。

使用Buffer

Buffer就像一个数组,可以保存多个类型相同的数据,可以保存多个类型相同的数据,Buffer是一个抽象类,最常用的是ByteBuffer,可以在底层字节数组上进行get/set除了ByteBuffer

之外对应的还有其类CharBufferShortBuffer , INtBuffer LongBuffer , 。。。

Buffer中有三个参数:

容量:表示Buffer的最大容量

界限:第一个不应该被读出或写入的缓冲区位置索引。位于limt后的数据即不可写也不可被读入

位置:用于指明下一个可以被读出或者写入位置的索引。

Buffer的主要作用是装入数据,然后输出数据,当Buffer装入数据后,调用flip()方法该方法将limit设置为position位置,并将position位置设置为0,这就使得Buffer读写指针又移到了开始的位置,即Buffer调用了filp()方法后为输出数据做好了准备 当Bufffer调用clear()方法后,不是清空buffer的数据,仅是将position位置置为0,将limit置为capacity

这样就为再次向Buffer中输入数据做好了准备。 

public class BufferTest {

public static void main(String[] args) {

CharBuffer  buffer = CharBuffer.allocate(8);//创建一个容量为8字节的charBuffer

System.out.println("capacity:" + buffer.capacity());

System.out.println("limit:"+buffer.limit());

System.out.println("posution:"+buffer.position());

buffer.put('a');

buffer.put('b');

buffer.put('c');

System.out.println("插入元素后position="+buffer.position());

buffer.flip();//position置为0,并将limit置于position位置处。

System.out.println("调用fliplimit=:"+buffer.limit());

System.out.println("调用flipposition=:"+buffer.position());

System.out.println("第一个元素(position=0"+buffer.get());

System.out.println("输出一个元素后position: "+buffer.position());

buffer.clear(); //position置为,将limit置为capacity(该方法并不会将缓冲区置为空)

System.out.println("调用clearposition"+buffer.position());

        System.out.println("调用clearlimit="+buffer.limit());

        System.out.println("第三个元素为:"+buffer.get(2));// 使用绝对方式来访问Buffer里的数据时不会影响position的值

        System.out.println("执行绝对读取后position:"+buffer.position());

}

}

Channel的使用:

1Channel 可以直接将指定的文件的部分或全部直接映射成Buffer

2:程序不能直接访问Channel中的数据,包括读取与写入,Channel只能与Buffer进行交互。如果从Channel中取得数据,必须先用BufferChannel中取出一些数据,让程序从Buffer中取出这些数据,写入也一样,javaChannel接口提供DatagramChannel(基于UDP通信的Channel),FileChannelSelectableChannel,(ServerSocketChannelSocketChannel(用于Tcp通信的Channel))。

所有的Channel都不是通过构造方法来获取的,而是通过传统的节点流(InputStreamOutPutStream,)的getChannel获取的,不同类型的节点流获得的Channel不一样。

public class FileChannelTest {

public static void main(String[] args) {

File file = new File("G:\\a.txt");

try {

FileChannel  inchannel = new FileInputStream(file).getChannel();

FileChannel outchannel = new FileOutputStream("G:\\c.txt").getChannel();

//inchannel里的全部数据映射成ByteBuffer

MappedByteBuffer buffer = inchannel.map(FileChannel.MapMode.READ_ONLY, 0, file.length());

//使用GBK的字符集来创建解码器

Charset  charset = Charset.forName("GBK");

//直接将Buffer里的数据全部输出

outchannel.write(buffer);

// position置为0,将limit置为capacity,为再次读入做准备。

buffer.clear();

// 创建解码器对象

CharsetDecoder  decoder = charset.newDecoder();

//使用解码器将ByteBuffer转化为charBufffer

CharBuffer charbuffer = decoder.decode(buffer);

System.out.println(charbuffer);

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

 

}

字符集合CharSet

在计算机中所有的文件在底层都是二进制文件,全不都是字节码,对于文本文件可以看到哟个个字符,这是因为系统将底层的二进制序列转换为字符的缘故,这个过程涉及编码(Encode)解码(Decoder),通常而言把明文的字符转换为计算机理解的二进制序列,称为编码,把二进制序列转换为人能够看懂的称为解码。

一旦知道字符集的别名之后,程序就可以调用CharSetforName()方法来创建对应的CharSet对象,forName()方法的参数就是对应的字符集的别名。

获得CharSet对象之后就可以通过该对象的newDecoder()或newEncoder()分别返回CharSetDecode,和CharSetEncoder代表该charSet的解码编码器,调用CharSetDecoderdecode方法将ByteBuffer(字节序列)转换为CharBuffer(字符序列)调用charSetEncoderencoder()方法可将CharBufferSring装换为ByteBuffer(字节序列)。

String类里提供了一个getBytes String charSets)该方法返回byte[];将指定的字符集转换成字节序列。

public class CharSetTransform {

public static void main(String[] args) throws CharacterCodingException {

Charset cn = Charset.forName("GBK");// 创建中文简体对应的CharSet对象

 // 获取cn对象的编码器解码器

CharsetEncoder  charsetEncoder = cn.newEncoder();

CharsetDecoder charsetDecoder = cn.newDecoder();

       //创建一个CharBuffer

CharBuffer buffer = CharBuffer.allocate(8);

buffer.put('');

buffer.put ('');

buffer.put('');

buffer.flip();

ByteBuffer byteBuffer = charsetEncoder.encode(buffer);//CharBuffer中的字符序列编码为字节序列。

System.out.println(byteBuffer);

System.out.println(charsetDecoder.decode(byteBuffer));//将字节序列解码为字符序列

}

}

文件锁:

如果多个程序需要并发修改同一个文件时,程序之间需要某种机制进行通信,使用文件锁可以有效地阻止一个多个进程并发的修改同一个文件 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值