精华内容
下载资源
问答
  • java使用nio读写文件

    千次阅读 2019-11-16 15:49:45
    最近在研究 JAVA NIO 的相关知识,学习NIO,就不能提到IO的原理和事项,必经NIO是基于IO进化而来 IO涉及到的底层的概念大致如下: 缓冲区操作。2) 内核空间与用户空间。3) 虚拟内存。4) 分页技术 一,虚拟存储器 ...

    IO原理

    最近在研究 JAVA NIO 的相关知识,学习NIO,就不能提到IO的原理和事项,必经NIO是基于IO进化而来

    IO涉及到的底层的概念大致如下:

    1. 缓冲区操作。2) 内核空间与用户空间。3) 虚拟内存。4) 分页技术

    一,虚拟存储器
    虚拟存储器是硬件异常(缺页异常)、硬件地址翻译、主存、磁盘文件和内核软件的完美交互,它为每个进程提供了一个大的、一致的和私有的地址空间。

    虚拟存储器的三大能力:

    ①将主存看成是一个存储在磁盘上的地址空间的高速缓存。
    ②为每个进程提供了一个一致的地址空间。
    ③保护每个进程的地址空间不被其他进程破坏。

    虚拟内存的两大好处:
    ① 一个以上的虚拟地址可指向同一个物理内存地址。
    ② 虚拟内存空间可大于实际可用的硬件内存。

    二,用户空间与内核空间
    设虚拟地址为32位,那么虚拟地址空间的范围为0~4G。操作系统将这4G分为二部分,将最高的1G字节(虚拟地址范围为:0xC0000000-0xFFFFFFFF)供内核使用,称为内核空间。而将较低的3G字节供各个进程使用,称为用户空间。
    每个进程可以通过系统调用进入内核,因为内核是由所有的进程共享的。对于每一个具体的进程,它看到的都是4G大小的虚拟地址空间,即相当于每个进程都拥有一个4G大小的虚拟地址空间。

    三,IO操作

    一般IO缓冲区操作:

    1. 用户进程使用read()系统调用,要求其用户空间的缓冲区被填满。
    2. 内核向磁盘控制器硬件发命令,要求从磁盘读入数据。
    3. 磁盘控制器以DMA方式(数据不经过CPU)把数据复制到内核缓冲区。
    4. 内核将数据从内核缓冲区复制到用户进程发起read()调用时指定的用户缓冲区。

    在这里插入图片描述

    从上图可以看出:磁盘中的数据是先读取到内核的缓冲区中。然后再从内核的缓冲区复制到用户的缓冲区。为什么会这样呢?

    因为用户空间的进程是不能直接硬件的(操作磁盘控制器)。磁盘是基于块存储的硬件设备,它一次操作固定大小的块,而用户请求请求的可能是任意大小的数据块。因此,将数据从磁盘传递到用户空间,由内核负责数据的分解、再组合。

    内存映射IO:就是复用一个以上的虚拟地址可以指向同一个物理内存地址。将内核空间的缓冲区地址(内核地址空间)映射到物理内存地址区域,将用户空间的缓冲区地址(用户地址空间)也映射到相同的物理内存地址区域。从而数据不需要从内核缓冲区映射的物理内存地址移动到用户缓冲区映射的物理内存地址了。从链路上看,这样的方式明显比上述的IO操作方式要短了,节省出来的路程,就是NIO操作的优势所在

    要求:①用户缓冲区与内核缓冲区必须使用相同的页大小对齐。
    ②缓冲区的大小必须是磁盘控制器块大小(512字节磁盘扇区)的倍数—因为磁盘是基于块存储的硬件设备,一次只能操作固定大小的数据块。

    用户缓冲区按页对齐,会提高IO的效率—这也是为什么在JAVA中new 一个字节数组时,指定的大小为2的倍数(4096)的原因吧。

    在这里插入图片描述

    四,JAVA中的IO,本质上是把数据移进或者移出缓冲区。

    read()和write()系统调用完成的作用是:把内核缓冲区映射的物理内存空间中的数据 拷贝到 用户缓冲区映射的物理内存空间中。

    因此,当使用内存映射IO时,可视为:用户进程直接把文件数据当作内存,也就不需要使用read()或write()系统调用了。

    当发起一个read()系统调用时,根据待读取的数据的位置生成一个虚拟地址(用户进程使用的是虚拟地址),由MMU转换成物理地址,若内核中没有相应的数据,产生一个缺页请求,内核负责页面调入从而将数据从磁盘读取到内核缓冲区映射的物理内存中。对用户程序而言,这一切都是在不知不觉中进行。

    总之,从根本上讲数据从磁盘装入内存是以页为单位通过分页技术装入内存的。

    五,JAVA NIO中的直接缓存和非直接缓存

    直接缓存:不是分配于堆上的存储,位于JVM之外,它不受JAVA的GC管理,相当于内核缓冲区。非直接缓存:建立在JAVA堆上的缓存,受JVM管理,相当于用户缓冲区。

    根据上面第三点,将直接缓存中的数据写入通道的速度要快于非直接缓存。因为,连接到通道的另一端是文件(磁盘,FileChannel)或者网络(Socket通道),这些都是某种形式上的硬件。那么,对于非直接缓存而言,数据从缓冲区传递到硬件,要经过内核缓冲区中转。而对于直接缓存而言,就不需要了,因为直接缓存已经直接映射到内核缓冲区了。

    了解了上述的基本概念后,下面我们分别使用传统的IO方式和NIO方式实现一个文件拷贝的功能,简单对比一下

    IO方式实现文件拷贝:

    	//IO方法实现文件k拷贝
        private static void traditionalCopy(String sourcePath, String destPath) throws Exception {
            File source = new File(sourcePath);
            File dest = new File(destPath);
            if (!dest.exists()) {
                dest.createNewFile();
            }
            FileInputStream fis = new FileInputStream(source);
            FileOutputStream fos = new FileOutputStream(dest);
            byte[] buf = new byte[1024];
            int len = 0;
            while ((len = fis.read(buf)) != -1) {
                fos.write(buf, 0, len);
            }
            fis.close();
            fos.close();
        }
    

    然后我们来测试一下一个比较大的文件拷贝,看看性能如何

    public static void main(String[] args) throws Exception{
            long start = System.currentTimeMillis();
            traditionalCopy("D:\\常用软件\\JDK1.8\\jdk-8u181-linux-x64.tar.gz", "D:\\常用软件\\JDK1.8\\IO.tar.gz");
            long end = System.currentTimeMillis();
            System.out.println("用时为:" + (end-start));
        }
    

    在这里插入图片描述

    在这里插入图片描述

    180M的文件,这个速度也还不算太差,下面我们再尝试使用NIO的方式试一下,提供两种方式的拷贝,

    public void nioCpoy(String source, String target, int allocate) throws IOException{
            ByteBuffer byteBuffer = ByteBuffer.allocate(allocate);
            FileInputStream inputStream = new FileInputStream(source);
            FileChannel inChannel = inputStream.getChannel();
    
            FileOutputStream outputStream = new FileOutputStream(target);
            FileChannel outChannel = outputStream.getChannel();
    
            int length = inChannel.read(byteBuffer);
            while(length != -1){
                byteBuffer.flip();//读取模式转换写入模式
                outChannel.write(byteBuffer);
                byteBuffer.clear(); //清空缓存,等待下次写入
                // 再次读取文本内容
                length = inChannel.read(byteBuffer);
            }
            outputStream.close();
            outChannel.close();
            inputStream.close();
            inChannel.close();
        }
    
    public static void fileChannelCopy(String sfPath, String tfPath) {
    
            File sf = new File(sfPath);
            File tf = new File(tfPath);
            FileInputStream fi = null;
            FileOutputStream fo = null;
            FileChannel in = null;
            FileChannel out = null;
            try{
                fi = new FileInputStream(sf);
                fo = new FileOutputStream(tf);
                in = fi.getChannel();//得到对应的文件通道
                out = fo.getChannel();//得到对应的文件通道
                in.transferTo(0, in.size(), out);//连接两个通道,并且从in通道读取,然后写入out通道
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                try{
                    fi.close();
                    in.close();
                    fo.close();
                    out.close();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    

    测试一下性能如何,运行一下下面的代码,

    public static void main(String[] args) {
            long start = System.currentTimeMillis();
            String sPath = "D:\\常用软件\\JDK1.8\\jdk-8u181-linux-x64.tar.gz";
            String tPath = "D:\\常用软件\\JDK1.8\\NIO.tar.gz";
            fileChannelCopy(sPath,tPath);
            long end = System.currentTimeMillis();
            System.out.println("用时为:" + (end-start));
        }
    

    在这里插入图片描述
    在这里插入图片描述

    这个效率通过简单的对比可以说明问题了,NIO在操作大文件读写时,性能优势就体现出来了,下面附上通过NIO操作文件读写的几个方法,后面做参考使用

    /**
     * NIO读写文件工具类
     */
    public class NIOFileUtil {
    
        private String file;
    
        public String getFile() {
            return file;
        }
    
        public void setFile(String file) {
            this.file = file;
        }
    
        public NIOFileUtil(String file) throws IOException {
            super();
            this.file = file;
        }
    
        /**
         * NIO读取文件
         * @param allocate
         * @throws IOException
         */
        public void read(int allocate) throws IOException {
    
            RandomAccessFile access = new RandomAccessFile(this.file, "r");
    
            //FileInputStream inputStream = new FileInputStream(this.file);
            FileChannel channel = access.getChannel();
            ByteBuffer byteBuffer = ByteBuffer.allocate(allocate);
    
            CharBuffer charBuffer = CharBuffer.allocate(allocate);
            Charset charset = Charset.forName("GBK");
            CharsetDecoder decoder = charset.newDecoder();
            int length = channel.read(byteBuffer);
            while (length != -1) {
                byteBuffer.flip();
                decoder.decode(byteBuffer, charBuffer, true);
                charBuffer.flip();
                System.out.println(charBuffer.toString());
                // 清空缓存
                byteBuffer.clear();
                charBuffer.clear();
                // 再次读取文本内容
                length = channel.read(byteBuffer);
            }
            channel.close();
            if (access != null) {
                access.close();
            }
        }
    
        /**
         * NIO写文件
         * @param context
         * @param allocate
         * @param chartName
         * @throws IOException
         */
        public void write(String context, int allocate, String chartName) throws IOException{
            // FileOutputStream outputStream = new FileOutputStream(this.file); //文件内容覆盖模式 --不推荐
            FileOutputStream outputStream = new FileOutputStream(this.file, true); //文件内容追加模式--推荐
            FileChannel channel = outputStream.getChannel();
            ByteBuffer byteBuffer = ByteBuffer.allocate(allocate);
            byteBuffer.put(context.getBytes(chartName));
            byteBuffer.flip();//读取模式转换为写入模式
            channel.write(byteBuffer);
            channel.close();
            if(outputStream != null){
                outputStream.close();
            }
        }
    
        /**
         * nio事实现文件拷贝
         * @param source
         * @param target
         * @param allocate
         * @throws IOException
         */
        public static void nioCpoy(String source, String target, int allocate) throws IOException{
            ByteBuffer byteBuffer = ByteBuffer.allocate(allocate);
            FileInputStream inputStream = new FileInputStream(source);
            FileChannel inChannel = inputStream.getChannel();
    
            FileOutputStream outputStream = new FileOutputStream(target);
            FileChannel outChannel = outputStream.getChannel();
    
            int length = inChannel.read(byteBuffer);
            while(length != -1){
                byteBuffer.flip();//读取模式转换写入模式
                outChannel.write(byteBuffer);
                byteBuffer.clear(); //清空缓存,等待下次写入
                // 再次读取文本内容
                length = inChannel.read(byteBuffer);
            }
            outputStream.close();
            outChannel.close();
            inputStream.close();
            inChannel.close();
        }
    
        //IO方法实现文件k拷贝
        private static void traditionalCopy(String sourcePath, String destPath) throws Exception {
            File source = new File(sourcePath);
            File dest = new File(destPath);
            if (!dest.exists()) {
                dest.createNewFile();
            }
            FileInputStream fis = new FileInputStream(source);
            FileOutputStream fos = new FileOutputStream(dest);
            byte[] buf = new byte[1024];
            int len = 0;
            while ((len = fis.read(buf)) != -1) {
                fos.write(buf, 0, len);
            }
            fis.close();
            fos.close();
        }
    
        public static void main(String[] args) throws Exception{
            /*long start = System.currentTimeMillis();
            traditionalCopy("D:\\常用软件\\JDK1.8\\jdk-8u181-linux-x64.tar.gz", "D:\\常用软件\\JDK1.8\\IO.tar.gz");
            long end = System.currentTimeMillis();
            System.out.println("用时为:" + (end-start));*/
    
            long start = System.currentTimeMillis();
            nioCpoy("D:\\常用软件\\JDK1.8\\jdk-8u181-linux-x64.tar.gz", "D:\\常用软件\\JDK1.8\\NIO.tar.gz",1024);
            long end = System.currentTimeMillis();
            System.out.println("用时为:" + (end-start));
        }
    
    }
    

    NIO在读写文件上体现出来的性能优势得益于其自身的结构设计,最重要的还是本文开头所讲的关于操作链路上的结构优化设计,掌握这一点原理基本就理解了NIO的实质,本篇到这里就结束了,最后感谢观看!

    展开全文
  • NIO使用FileChannel 用于文件数据的读写 FileChannel方法 public int read(ByteBuffer dst) 从通道读取数据并放到缓冲区中,此操作也会移动 Buffer 中的position指针,不断往position中放数据,read完成后...

    前言

    在NIO中使用FileChannel 用于文件数据的读写

    FileChannel方法

    public int read(ByteBuffer dst)
    从通道读取数据并放到缓冲区中,此操作也会移动 Buffer 中的position指针,不断往position中放数据,read完成后position指向limit。
    public int write(ByteBuffer src)
    把缓冲区的数据写到通道中,此操作也会不断移动Buffer中的position位置直到limit,读取到的数据就是position到limit这两个指针之间的数据。
    public long transferFrom(ReadableByteChannel src, long position, long count)
    从目标通道中复制数据到当前通道
    public long transferTo(long position, long count, WritableByteChannel target)
    把数据从当前通道复制给目标通道
    该方法拷贝数据使用了零拷贝,通常用来在网络IO传输中,将FileChannel里面的文件数据直接拷贝到与客户端或者服务端连接的Channel里面从而达到文件传输。
    

    将数据写入文件中

    package com.boshrong.nio;
    
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.nio.ByteBuffer;
    import java.nio.channels.FileChannel;
    
    public class FileChannelTest {
        public static void main(String[] args) throws IOException {
            // 将数据写入到文件中
            String name="bosh_rong 快乐每一天";
            //创建一个输出流
            File file = new File("d:/test.txt");
            FileOutputStream fileOutputStream=new FileOutputStream(file);
            // 获取相应的channel
            FileChannel channel = fileOutputStream.getChannel();
            // 将字符串放入缓存区
            ByteBuffer byteBuffer =ByteBuffer.allocate(1024);
            //将字符串以字节形式放入buffer中
            byteBuffer.put(name.getBytes());
            //开始读取
            byteBuffer.flip();
            //从buffer中读取到文件
            channel.write(byteBuffer);
            fileOutputStream.close();
        }
    }
    

    从文件中读取数据

    package com.boshrong.nio;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.nio.ByteBuffer;
    import java.nio.channels.FileChannel;
    
    public class FileChannelRead {
        public static void main(String[] args) throws IOException {
            // 使用nio从本地读取一个文件
            //File file = new File();
            FileInputStream fileInputStream = new FileInputStream("d:/test.txt");
            // 获取文件相应的channel,channel中会有相关数据
            FileChannel channel = fileInputStream.getChannel();
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            // 将channel的数据读取到buffer
            channel.read(buffer);
            //System.out.println(buffer);
            System.out.println("读取的数据为"+new String(buffer.array()));
            fileInputStream.close();
    
        }
    }
    

    总结

    java 输入输出流对象被 NIO FileChannel 所包裹,使用流对象.getChannel() 获取文件对应的channel。channel.write(buffer); 读取buffer的内容到channel,到了channel 也就到了file . channel.read(buffer) 从通道读取数据放入buffer ,从channel读取数据就相当从对应的流对象读取数据。

    在这里插入图片描述

    展开全文
  • 在软件系统中,由于IO的速度要比内存慢...使用java.nio.charset.Charset作为字符集编码解码解决方案;增加通道(channel)对象,作为新的原始I/O抽象;支持锁和内存映射文件的文件访问接口;提供了基于Selector的异步网
  • 主要介绍了Java文件读写IO/NIO及性能比较详细代码及总结,具有一定借鉴价值,需要的朋友可以参考下。
  • package cn.ac.yangge.service; import cn.ac.yangge.unity.AnalysisData; import cn.ac.yangge.unity.ByteBufferPrint; import org.springframework.stereotype.Service; import java.io.*;...import java.net.Inet
    package cn.ac.yangge.service;
    
    import cn.ac.yangge.unity.AnalysisData;
    import cn.ac.yangge.unity.ByteBufferPrint;
    import org.springframework.stereotype.Service;
    
    import java.io.*;
    import java.net.InetSocketAddress;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.nio.ByteBuffer;
    import java.nio.channels.SelectionKey;
    import java.nio.channels.Selector;
    import java.nio.channels.ServerSocketChannel;
    import java.nio.channels.SocketChannel;
    import java.util.*;
    import java.util.concurrent.Callable;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ThreadPoolExecutor;
    
    /**
     * Created by yangge on 2017/5/26 0026.
     */
    @Service("tcpService")
    public class TcpService {
        // 主入口
        public static void main() throws IOException {
            sockectChannelSever();
        }
    
    
        //使用serversocketchannel 非程阻塞
        public static void sockectChannelSever() {
            int port = 8888;//端口
    
            ServerSocketChannel serverSocketChannel;
            Selector selector;
            try {
                serverSocketChannel = ServerSocketChannel.open();
                ServerSocket ss = serverSocketChannel.socket();
                InetSocketAddress address = new InetSocketAddress(port);
                ss.bind(address);
                serverSocketChannel.configureBlocking(false);
                selector = Selector.open();
                serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
            } catch (IOException e) {
                e.printStackTrace();
                return;
            }
    
            while (true) {
                try {
                    selector.select();
                } catch (IOException e) {
                    e.printStackTrace();
                    break;
                }
                Set<SelectionKey> readyKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = readyKeys.iterator();
                while (iterator.hasNext()) {
    
                    SelectionKey key = iterator.next();
                    iterator.remove();
                    try {
                        if (key.isAcceptable()) {
                            ServerSocketChannel server = (ServerSocketChannel) key.channel();
                            SocketChannel client = server.accept();
                            System.out.println("Accepted connection from " + client);
                            client.configureBlocking(false);
                            SelectionKey clientKey = client.register(selector, SelectionKey.OP_READ);
                            ByteBuffer buffer = ByteBuffer.allocate(100);
                            clientKey.attach(buffer);
                        }
                        if (key.isReadable()) {
                            SocketChannel client = (SocketChannel) key.channel();
                            ByteBuffer output = (ByteBuffer) key.attachment();
                            client.read(output);
                            output.flip();
                            byte[] byteArray=output.array();
                            for(byte b:byteArray){
                                System.out.println(b);
                            }
                            System.out.println(ByteBufferPrint.getString(output));
    
                        }
                    } catch (IOException ex) {
                        key.cancel();
                        try {
                            key.channel().close();
                        } catch (IOException e) {
                        }
                    }
                }
            }
    
        }
    
    }
    
    

    Java NIO中的SocketChannel是一个连接到TCP网络套接字的通道。可以通过以下2种方式创建SocketChannel:

    1. 打开一个SocketChannel并连接到互联网上的某台服务器。
    2. 一个新连接到达ServerSocketChannel时,会创建一个SocketChannel。

    打开 SocketChannel

    下面是SocketChannel的打开方式:

    1 SocketChannel socketChannel = SocketChannel.open();
    2 socketChannel.connect(new InetSocketAddress("http://jenkov.com"80));

    关闭 SocketChannel

    当用完SocketChannel之后调用SocketChannel.close()关闭SocketChannel:

    1 socketChannel.close();

    从 SocketChannel 读取数据

    要从SocketChannel中读取数据,调用一个read()的方法之一。以下是例子:

    1 ByteBuffer buf = ByteBuffer.allocate(48);
    2 int bytesRead = socketChannel.read(buf);

    首先,分配一个Buffer。从SocketChannel读取到的数据将会放到这个Buffer中。

    然后,调用SocketChannel.read()。该方法将数据从SocketChannel 读到Buffer中。read()方法返回的int值表示读了多少字节进Buffer里。如果返回的是-1,表示已经读到了流的末尾(连接关闭了)。

    写入 SocketChannel

    写数据到SocketChannel用的是SocketChannel.write()方法,该方法以一个Buffer作为参数。示例如下:

    01 String newData = "New String to write to file..." + System.currentTimeMillis();
    02  
    03 ByteBuffer buf = ByteBuffer.allocate(48);
    04 buf.clear();
    05 buf.put(newData.getBytes());
    06  
    07 buf.flip();
    08  
    09 while(buf.hasRemaining()) {
    10     channel.write(buf);
    11 }

    注意SocketChannel.write()方法的调用是在一个while循环中的。Write()方法无法保证能写多少字节到SocketChannel。所以,我们重复调用write()直到Buffer没有要写的字节为止。

    非阻塞模式

    可以设置 SocketChannel 为非阻塞模式(non-blocking mode).设置之后,就可以在异步模式下调用connect(), read() 和write()了。

    connect()

    如果SocketChannel在非阻塞模式下,此时调用connect(),该方法可能在连接建立之前就返回了。为了确定连接是否建立,可以调用finishConnect()的方法。像这样:

    1 socketChannel.configureBlocking(false);
    2 socketChannel.connect(new InetSocketAddress("http://jenkov.com"80));
    3  
    4 while(! socketChannel.finishConnect() ){
    5     //wait, or do something else...
    6 }

    write()

    非阻塞模式下,write()方法在尚未写出任何内容时可能就返回了。所以需要在循环中调用write()。前面已经有例子了,这里就不赘述了。

    read()

    非阻塞模式下,read()方法在尚未读取到任何数据时可能就返回了。所以需要关注它的int返回值,它会告诉你读取了多少字节。

    调试的时候想要转化byteBuffer?

    提供给你两个方法

    String 转换 ByteBuffer:

      

    public static ByteBuffer getByteBuffer(String str) {

    return ByteBuffer.wrap(str.getBytes());

    }


    ByteBuffer 转换 String:

    public static String getString(ByteBuffer buffer) {

    Charset charset = null;

    CharsetDecoder decoder = null;

    CharBuffer charBuffer = null;

    try {

    charset = Charset.forName("UTF-8");

    decoder = charset.newDecoder();

                           //用这个的话,只能输出来一次结果,第二次显示为空

    // charBuffer = decoder.decode(buffer);

    charBuffer = decoder.decode(buffer.asReadOnlyBuffer());

    return charBuffer.toString();

    } catch (Exception ex) {

    ex.printStackTrace();

    return "error";

    }

    }


    想要直接转化为byte[] ?

    可以直接使用byteBuffer.array();


    遇到的坑:

    SelectionKey clientKey = client.register(selector, SelectionKey.OP_READ);
    在配置selectionKey的时候,之前是用了Selection.OP_WRITE的,这导致keys的事件集合中一直存在一个isWritable事件,原因是:
    key.isWritable()是表示Socket可写,网络不出现阻塞情况下,一直是可以写的,所认一直为true.一般我们不注册OP_WRITE事件.


    展开全文
  • java NIO方式读写文件

    2020-02-13 20:16:18
    Java NIO(new/inputstream outputstream)使用通道、缓冲来操作流,所以要深刻理解这些概念,尤其是,缓冲中的数据结构(当前位置(position)、限制(limit)、容量(capacity))。 Channel(通道)、Buffer(缓冲区)、...

    Java NIO(new/inputstream outputstream)使用通道、缓冲来操作流,所以要深刻理解这些概念,尤其是,缓冲中的数据结构(当前位置(position)、限制(limit)、容量(capacity))。

    Channel(通道)、Buffer(缓冲区)、Selector(选择器)

    /**
     * @author sy
     * @date 2020/2/13 19:31
     */
    public class FileUtil implements Serializable {
    
    
      private static Logger log = LoggerFactory.getLogger(FileUtil.class);
    
      /**
       * 通过NIO获取byte[]
       * @param filename
       * @description 一般作用于从本地读取文件,通过httpServletResponse返回页面。
       * @return
       */
      public static byte[] toByteArray(String filename) {
    
        File f = new File(filename);
        if (!f.exists()) {
          log.error("文件未找到!" + filename);
          throw new RuntimeException("文件未找到");
        }
        FileChannel channel = null;
        FileInputStream fs = null;
        try {
          fs = new FileInputStream(f);
          channel = fs.getChannel();
          ByteBuffer byteBuffer = ByteBuffer.allocate((int) channel.size());
          while ((channel.read(byteBuffer)) > 0) {
            // 读取中....
          }
          return byteBuffer.array();
        } catch (IOException e) {
          //实际上应该自定义异常,统一异常处理
          throw new RuntimeException("文件發生錯誤");
        } finally {
          try {
            channel.close();
          } catch (IOException e) {
            throw new RuntimeException("文件發生錯誤");
          }
          try {
            fs.close();
          } catch (IOException e) {
            throw new RuntimeException("文件發生錯誤");
          }
        }
      }
    
    
      /**
       * copy文件
       * @param src
       * @param dst
       * @description 一般作用于拷贝文件
       * @throws IOException
       */
      public static void copyFileUseNIO(String src,String dst) throws IOException{
        //声明源文件和目标文件
        FileInputStream fi = null;
        FileOutputStream fo = null;
        //获得传输通道channel
        FileChannel inChannel = null;
        FileChannel outChannel = null;
        try {
          //声明源文件和目标文件
          fi = new FileInputStream(new File(src));
          fo = new FileOutputStream(new File(dst));
          //获得传输通道channel
          inChannel = fi.getChannel();
          outChannel = fo.getChannel();
          //获得容器buffer
          ByteBuffer buffer = ByteBuffer.allocate(1024);
          while (true) {
            //判断是否读完文件
            int eof = inChannel.read(buffer);
            if (eof == -1) {
              break;
            }
            //重设一下buffer的position=0,limit=position
            buffer.flip();
            //开始写
            outChannel.write(buffer);
            //写完要重置buffer,重设position=0,limit=capacity
            buffer.clear();
          }
        }catch (Exception e){
          throw new RuntimeException("文件發生錯誤");
        }finally {
          try {
            inChannel.close();
            fi.close();
          } catch (IOException e) {
            throw new RuntimeException("文件發生錯誤");
          }
          try {
            outChannel.close();
            fo.close();
          } catch (IOException e) {
            throw new RuntimeException("文件發生錯誤");
          }
        }
      }
    
    }

    注:资料有从各大网站参考,如有雷同,纯属意外。

    展开全文
  • java 使用 NIO 读写文件

    2018-11-09 13:59:05
    public static void Readnio() { RandomAccessFile randomAccessFile = null; FileChannel fileChannel = null; try { randomAccessFile = new RandomAccessFile(&amp;quot;f:\\a.tx...
  • java NIO方式进行读写文件和内容

    千次阅读 2019-03-13 16:05:33
    java NIO方式进行读写文件和内容 import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio....
  • java.nio新功能的优点

    2020-03-04 11:17:40
    java 1.4中推出的java.nio(新输入/输出)软件包允许像在其他低级语言——如C语言——中一样进行输入/输出。许多开发者认为这些新功能只能进行非阻塞操作;但是,这些新功能提供许多其他新鲜有趣的特性,它们包括:...
  • Java 7中,AsynchronousFileChannel已添加到Java NIO。 AsynchronousFileChannel使异步读写文件成为可能。接下来将说明如何使用AsynchronousFileChannel。 1.创建一个AsynchronousFileChannel 可以通过其静态...
  • 在以往的java的IO操作的过程中都是面向字节流操作,并且读写操作是单向的操作,而在java1.4添加nio包新的io不再像以前的标准的io操作一样面向流操作,而NIO是面向块的操作,并且有通道、缓冲区等重要的部分组成。...
  • 使用 java nio 实现按行读写文件

    千次阅读 2018-03-18 18:41:21
    最近在了解 java nio 相关的一些知识,在网上看到了一篇通过 java nio 来按行读取文件的博客,于是为了练手就自己实现了下,关于 java nio 的基础知识这里就不多说了,具体代码实现如下: import java.io....
  • Java NIO(New IO)是一个可以替代标准Java IO API的IO API(从Java 1.4开始),Java NIO提供了与标准IO不同的IO工作方式。很多小伙伴可能和我一样,对于习惯了IO来操作文件之后,对这个日渐流行的新东西会有不少的...
  • 正在复习Java基础知识,依葫芦画瓢写了个NIO服务的demo,又改进了下,做成了双向读写。分享给需要的朋友 废话少说,代码如下: B_Server package nio_demo_01; import java.io.IOException; import java.net....
  • java:NIO读写文件的示例

    千次阅读 2016-07-04 19:00:54
    Java NIO(New IO)是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的Java IO API。 NIO方式读数据非常简单 创建一个缓冲区(ByteBuffer);通过一个FileChannel (从FileInputStream 创建)完成缓冲区的数据...
  • 我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你它写博客: 全新的界面设计 ,将会带来全新的写作体验; 在创作中心设置你喜爱的代码高亮...
  • 主要介绍了使用java NIO及高速缓冲区写入文件过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 所以用NIO实现按行读取并解决中文乱码。看了一些帖子感觉较为复杂,代码不够清晰。顾将自己写的代码奉上。如有不足请指正。 package NIO; import java.io.File; import java.io.IOException; import java.io....
  • java nio 实现文件读写

    千次阅读 2018-02-27 11:39:27
    package ... import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException;...import java.nio.ByteBuffer; import ja...
  • import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.RandomAccessFile; import j....
  • Java NIO读写TXT文件(FileChannel)

    千次阅读 2019-01-08 23:02:17
    先上代码为敬 代码中编码写成GBK是因为windows默认新建txt的时候是GBK格式,如果你的txt文件为UTF-8则修改为UTF-8 package channel; import java.io.FileInputStream; ...import java.nio.c...
  • Java NIO详解

    千次阅读 2019-10-22 12:02:47
    JAVA NIO 简介 NIO与IO的对比
  • JavaNIO

    2020-12-22 04:10:17
    NIO于原来的IO有相同的功能,但是他们之间的使用方式是完全不同的,NIO是面向缓冲区,面向通道的的IO操作,NIO拥有更加高效的进行文件读写。 另外NIO在网络编程可以是一个无阻塞的IO交互,可以大大提升Socket交互的...
  • 详解JavaNIO

    2021-02-25 02:56:55
    但是传统的IO流还是有很多缺陷的,尤其它的阻塞性加上磁盘读写本来就慢,会导致CPU使用效率大大降低。所以,jdk1.4发布了NIO包,NIO的文件读写设计颠覆了传统IO的设计,采用『通道』+『缓存区』使得新式的IO操作直接...
  • Java NIO 介绍和基本demo

    2020-03-09 13:20:00
    前面说到,java中I/O编程,大致可以分为三种,阻塞IO(BIO)、非阻塞IO(NIO)和异步IO(AIO)。 BIO 传统的同步阻塞模型开发中,ServerSocket负责绑定IP地址,启动监听端口;Socket负责发起连接操作。连接成功后,双方...
  • Java IO NIO NIO2

    千次阅读 2018-07-03 22:56:03
    Java的I/O操作类在包java.io下,可分为如下4组:1、基于字节操作的I/O接口:InputStream和OutputStream;2、基于字符操作的I/O接口:Writer和Reader;3、基于磁盘操作的I/O接口:File;4、基于网络操作的I/O接口:...
  • JAVANIO按行读写大文件,完美解决中文乱码问题

    万次阅读 多人点赞 2016-02-01 20:46:20
    要将百万行级别的txt数据插入到数据库中,由于内存方面的原因,因此不可能一次读取所有内容,后来在网上找到了解决方法,可以使用NIO技术来处理,于是找到了这篇文章http://www.sharejs.com/codes/java/1334,...
  • Java NIO介绍及使用

    千次阅读 2018-05-14 11:08:42
    1.什么是Java NIO 大家都知道Java BIO,其全称是java blocking IO,相对的Java NIO 全称为java non-blocking IO。顾名思义,java nio 是一种非阻塞IO。 下面是百度百科对Java NIO的介绍: java.nio全称java non-...
  • java NIO读写文件

    2017-03-07 16:16:24
    简介: IO 在NIO 中都从一个Channel 开始。Channel 有点象流。 数据可以从Channel读到Buffer中,也可以从...Java NIO和IO之间第一个最大的区别是,IO是面向流的,NIO是面向缓冲区的。 Java IO面向流意味着每次从流

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 47,527
精华内容 19,010
关键字:

java用nio2读写

java 订阅