实现一:使用nio实现文件复制
- package study.nio;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.FileNotFoundException;
- import java.io.IOException;
- import java.nio.channels.FileChannel;
- import java.nio.ByteBuffer;
- public class TestCopyFile {
- public static void main(String[] args) throws IOException {
-
- FileManager.copyFile(new File("src.txt"), new File("dst.txt"));
- }
- }
- class FileManager {
-
- public static void copyFile(File src, File dst)
- throws FileNotFoundException, IOException {
-
- FileChannel fcin = new FileInputStream(src).getChannel();
-
- FileChannel fcout = new FileOutputStream(dst).getChannel();
-
- ByteBuffer buf = ByteBuffer.allocate(1024);
- while(fcin.read(buf) != -1) {
- buf.flip();
- fcout.write(buf);
- buf.clear();
- }
- }
-
- }
还可以使用下面方式进行操作,在FileChannel中有两个特殊方法可以允许我们直接将两个通道相连:
long transferFrom(ReadableByteChannel src, long position, long count);
long transferTo(long position, long count, WriteableByteChannel targets);
上面while循环可以替换为:
fcin.transferTo(0, fcin.size(), fcout); 或者 fcout.transferFrom(fcin, 0, fcin.size());
实现二:向一个空文件中写入some text,再以只读方式打开该文件,在尾部追加some more,最终将该文件内容输出。
- package study.nio;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.RandomAccessFile;
- import java.nio.ByteBuffer;
- import java.nio.channels.FileChannel;
-
- public class GetChannel {
-
- public static void main(String[] args) throws Exception {
- FileChannel fc = null;
-
- fc = new FileOutputStream(new File("data.txt")).getChannel();
- fc.write(ByteBuffer.wrap("some text".getBytes()));
- fc.close();
-
- fc = new RandomAccessFile("data.txt", "rw").getChannel();
- fc.position(fc.size());
- fc.write(ByteBuffer.wrap("some more".getBytes()));
- fc.close();
-
- fc = new FileInputStream("data.txt").getChannel();
- ByteBuffer buf = ByteBuffer.allocate(1024);
- fc.read(buf);
- buf.flip();
- while(buf.hasRemaining()) {
- System.out.print((char)buf.get());
- }
- }
- }
以上均使用的是字节操作流,与nio相一致。Reader和Writer这些字符模式类不能用于产生通道,但是Java.nio.channels.Channels类中提供了实用方法,可以在通道中产生Reader和Writer。
Channels.newReader();
Channels.newWriter();
实现三:将一个大文件映射到内存并查找指定的文本内容是否在该文件中(曾记得李开复与微软的故事,当然李开复是从邮件中查找信息,并且邮件被截成了图片,⊙﹏⊙b汗)
- public class LargeMappedFiles {
- public static void main(String args[]) {
- try {
- File[] files = new File[] {new File("src1.txt"), new File("src2.txt")};
- ArrayList<String> ls = search(files, "something is wrong");
- for(int i=0; i<ls.size(); i++) {
- System.out.println(ls.get(i));
- }
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- private static ArrayList<String> search(File[] files, String text) throws Exception {
-
- ArrayList<String> result = new ArrayList<String>();
-
- for(File src : files) {
-
- MappedByteBuffer dst = new RandomAccessFile(src, "rw")
- .getChannel()
- .map(FileChannel.MapMode.READ_WRITE, 0, src.length());
-
- String str = Charset.forName("UTF-8").decode(dst).toString();
-
- dst.flip();
- if(str.indexOf(text) != -1) {
- result.add(src.getName());
- }
-
- dst.clear();
- }
- return result;
- }
- }
实现四:在前面的学习中了解到nio为所有原始数据类型提供了Buffer支持,并且在ByteBuffer中实现了asXBuffer()方法直接将一个ByteBuffer转换成其它类型的Buffer。本例实现数据类型的转换。
- import java.nio.IntBuffer;
- import java.nio.FloatBuffer;
- import java.nio.ByteBuffer;
- import java.util.Arrays;
-
- public class CastBuffer {
- static byte[] bytes = new byte[] {0, 1, 2, 3, 4, 5, 'a', 'b', 'c'};
-
- public static void main(String[] args) {
- ByteBuffer bBuf = ByteBuffer.wrap(bytes);
- System.out.println(Arrays.toString(bBuf.array()));
-
- IntBuffer iBuf = ((ByteBuffer)bBuf.rewind()).asIntBuffer();
- while(iBuf.hasRemaining()) {
- System.out.print(iBuf.get()+",");
- }
-
- FloatBuffer fBuf = ((ByteBuffer)bBuf.rewind()).asFloatBuffer();
- while(fBuf.hasRemaining()) {
- System.out.print(fBuf.get()+",");
- }
- }
- }
其它类型转换与上面方法类似,各种方法都相似。