亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java怎么使用NIO優化IO實現文件上傳下載功能

發布時間:2022-07-28 14:56:12 來源:億速云 閱讀:148 作者:iii 欄目:開發技術

本篇內容主要講解“Java怎么使用NIO優化IO實現文件上傳下載功能”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Java怎么使用NIO優化IO實現文件上傳下載功能”吧!

1 NIO的一些基礎預備知識

Java中IO流類的體系中BIO與NIO:https://blog.csdn.net/ZGL_cyy/article/details/104326458
Java IO體系與NIO和BIO體系面試題 :https://blog.csdn.net/ZGL_cyy/article/details/122836368
為什么使用NIO:因為傳統IO文件傳輸速率低,所以選擇了NIO進行文件的下載操作。NIO還有一個好處就是其中零拷貝可以實現減少內存中數據的重復,減少CPU操作的效果。所以相對于傳統IO,NIO有著效率高點的優勢。

2 NIO為何較傳統的io速度較快

就拿單個io過程來看,首先時間主要花在了用戶態和內核態的轉換上,其次,考慮將多個io的“合并”為一個io,這不就節省時間了嗎

相應的NIO主要做了兩方面的提升

1.避免了用戶態和內核態的交換,直接操作內存,用戶態和內核態的轉換是很費時的,傳統的io寫入磁盤時,用戶態的接口不能直接操作內存,而是通過操作系統調用內核態接口來進行io。

2.利用buffer減少io的次數,buffer化零為整”的寫入方式因為大大減小了尋址/寫入次數,所以就降低了硬盤的負荷。

3.IO 是基于流來讀取的,而NIO則是基于塊讀取,面向流 的 I/O 系統一次一個字節地處理數據。一個輸入流產生一個字節的數據,一個輸出流消費一個字節的數據。為流式數據創建過濾器非常容易。鏈接幾個過濾器,以便每個過濾器只負責單個復雜處理機制的一部分,這樣也是相對簡單的。不利的一面是,面向流的 I/O 通常相當慢。
一個 面向塊 的 I/O 系統以塊的形式處理數據。每一個操作都在一步中產生或者消費一個數據塊。按塊處理數據比按(流式的)字節處理數據要快得多。但是面向塊的 I/O 缺少一些面向流的 I/O 所具有的優雅性和簡單性。

4.非阻塞IO 和 異步IO的支持, 減少線程占有的棧空間,以及上下文切換

5.IO 多路復用的支持

6.Buffer 支持,所有讀寫操作都是基于 緩沖 來實現

7.NIO 支持 Direct Memory, 可以減少一次數據拷貝

8.Netty 零拷貝的支持

3 NIO實戰上傳下載

3.1 url下載文件

java NIO包提供了無緩沖情況下在兩個通道之間直接傳輸字節的可能。

為了讀來自URL的文件,需從URL流創建ReadableByteChannel :

ReadableByteChannel readableByteChannel = Channels.newChannel(url.openStream());

從ReadableByteChannel 讀取字節將被傳輸至FileChannel:

FileOutputStream fileOutputStream = new FileOutputStream(FILE_NAME);
FileChannel fileChannel = fileOutputStream.getChannel();

然后使用transferFrom方法,從ReadableByteChannel 類下載來自URL的字節傳輸到FileChannel:

fileOutputStream.getChannel().transferFrom(readableByteChannel, 0, Long.MAX_VALUE);

transferTo() 和 transferFrom() 方法比簡單使用緩存從流中讀更有效。依據不同的底層操作系統,數據可以直接從文件系統緩存傳輸到我們的文件,而不必將任何字節復制到應用程序內存中。

在Linux和UNIX系統上,這些方法使用零拷貝技術,減少了內核模式和用戶模式之間的上下文切換次數。

工具類:

/**NIO文件下載工具類
 * @author olalu
 */
public class NioDownloadUtils {

    /**
     * @description:
     * @param file: 要下在文件
     * @return: void
     */
    public static void downloadDoc(File file,HttpServletResponse response) throws IOException {
        OutputStream outputStream = response.getOutputStream();
        String contentType = Files.probeContentType(Paths.get(file.getAbsolutePath()));
        //設置響應頭
        response.setHeader("Content-Type", contentType);
        response.setHeader("Content-Disposition", "attachment;filename="+ new String(file.getName().getBytes("utf-8"),"ISO8859-1"));
        response.setContentLength((int) file.length());
        //獲取文件輸入流
        FileInputStream fileInputStream = new FileInputStream(file);
        //獲取輸出流通道
        WritableByteChannel writableByteChannel = Channels.newChannel(outputStream);
        FileChannel fileChannel = fileInputStream.getChannel();
        //采用零拷貝的方式實現文件的下載
        fileChannel.transferTo(0,fileChannel.size(),writableByteChannel);
        //關閉對應的資源
        fileChannel.close();
        outputStream.flush();
        writableByteChannel.close();
    }

    public static void downloadDoc(String path,HttpServletResponse response) throws IOException {
        File file = new File(path);
        if (!file.exists()){
            throw new RuntimeException("文件不存在");
        }
        downloadDoc(file,response);
    }

}

3.2 通過NIO上傳文件

/**
     * 文件上傳方法
     */
    public static Result uploading(MultipartFile file) {
        //獲取文件名
        String realName = file.getOriginalFilename();
        String newName = null;
        if(realName != null && realName != ""){
            //獲取文件后綴
            String suffixName = realName.substring(realName.lastIndexOf("."));
            //生成新名字
            newName = UUID.randomUUID().toString().replaceAll("-", "")+suffixName;
        }else {
            return Result.fail("文件名不可為空");
        }
        //創建流
        FileInputStream fis = null;
        FileOutputStream fos = null;
        //創建通道
        FileChannel inChannel = null;
        FileChannel outChannel = null;
        try {
            fis = (FileInputStream)file.getInputStream();
            //開始上傳
            fos = new FileOutputStream(UPLOAD_URL+"\\"+newName);
            //通道間傳輸
            inChannel = fis.getChannel();
            outChannel = fos.getChannel();
            //上傳
            inChannel.transferTo(0,inChannel.size(),outChannel);

        }catch (IOException e){
            return Result.fail("文件上傳路徑錯誤");
        }finally {
            //關閉資源
            try {
                if (fis != null) {
                    fis.close();
                }
                if (fos != null) {
                    fos.close();
                }
                if (inChannel != null) {
                    inChannel.close();
                }
                if (outChannel != null) {
                    outChannel.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return Result.ok(newName);

    }

到此,相信大家對“Java怎么使用NIO優化IO實現文件上傳下載功能”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

瓮安县| 斗六市| 太和县| 石柱| 南昌县| 天水市| 辽源市| 抚远县| 嘉义县| 西林县| 昔阳县| 彭山县| 安平县| 谷城县| 三都| 平阴县| 扎赉特旗| 壤塘县| 奇台县| 化德县| 金湖县| 大田县| 中江县| 广汉市| 彝良县| 盐边县| 桐梓县| 建宁县| 清丰县| 浮梁县| 涞水县| 太白县| 定陶县| 樟树市| 库尔勒市| 黎城县| 黄大仙区| 新田县| 绥化市| 舞阳县| 离岛区|