FileChannel詳解

一、FileChannel的優勢

FileChannel是Java NIO庫中的一個重要類,作為Java中File I/O讀寫的另一種方式,相較於傳統的IO方式,FileChannel具有以下優勢:

1. 更快的I/O操作,只適用於間隔地讀或寫一個大容量的數據塊;

2. 可以直接操作直接內存映射文件,使用堆外內存讀寫操作;

3. 支持非阻塞I/O,可以使用單獨的線程讀寫文件,FileChannel中的data與NIO庫的selector結合可以實現同步非阻塞IO;

4. 支持多個並發訪問;

5. 可以鎖定文件的某個區域以進行獨佔訪問;

6. 可以將兩個或多個FileChannel中的數據直接傳輸,實現零拷貝,加快文件的讀取和寫入速度。

二、FileChannel讀取文件

FileChannel的read()方法提供了多種方式讀取文件。最常用的是使用ByteBuffer緩衝區進行讀取:

    try(RandomAccessFile file = new RandomAccessFile("test.txt", "rw");
        FileChannel channel = file.getChannel()){
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        while (channel.read(buffer) != -1){
            buffer.flip();
            while (buffer.hasRemaining()){
                System.out.print((char) buffer.get());
            }
            buffer.clear();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

三、FileChannel寫文件

FileChannel的write()方法提供了多種方式寫入數據到文件。最常用的是使用ByteBuffer緩衝區進行寫入:

    try(RandomAccessFile file = new RandomAccessFile("test.txt", "rw");
        FileChannel channel = file.getChannel()){
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        buffer.put("Test String".getBytes());
        buffer.flip();
        while (buffer.hasRemaining()){
            channel.write(buffer);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

四、FileChannel寫入文件

FileChannel提供了map()方法將一個文件區域直接映射到內存中,讀寫操作直接在內存中進行:

    try(RandomAccessFile file = new RandomAccessFile("test.txt", "rw");
        FileChannel channel = file.getChannel()){
        MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, 1024);
        buffer.put("Test String".getBytes());
    } catch (IOException e) {
        e.printStackTrace();
    }

五、FileChannel線程安全

FileChannel是線程安全的,因為FileChannel實例方法中的狀態是由操作系統中的文件對象來維護的。即使有多個線程同時對同一個FileChannel操作,操作系統也會協作來保證正確的順序和正確的結果。

六、FileChannel可以實現數據零拷貝

FileChannel提供的transferTo()方法和transferFrom()方法可以非常高效地傳輸數據,實現數據的零拷貝。

    try(RandomAccessFile file = new RandomAccessFile("src.txt", "rw");
        FileChannel srcChannel = file.getChannel();

        RandomAccessFile outputFile = new RandomAccessFile("dest.txt", "rw");
        FileChannel outputChannel = outputFile.getChannel()
    ) {
        long position = 0;
        long count = srcChannel.size();
        srcChannel.transferTo(position, count, outputChannel);
    } catch (IOException e) {
        e.printStackTrace();
    }

七、FileChannel.write的寫入速度

FileChannel通過ByteBuffer進行寫入操作的性能非常高,一般會比傳統的IO方式的性能快很多。下面我們來比較一下FileChannel和傳統的IO流的寫入速度:

    try(FileOutputStream fos = new FileOutputStream("test.txt")){
        FileChannel fileChannel = fos.getChannel();
        long start = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            ByteBuffer buffer = ByteBuffer.allocate(64);
            buffer.put("123456789012345678901234567890123456789012345678901234567890123\n".getBytes());
            buffer.flip();
            fileChannel.write(buffer);
        }
        System.out.println("FileChannel Time:" + (System.currentTimeMillis() - start) + " ms");
    } catch (IOException e) {
        e.printStackTrace();
    }
    try(FileOutputStream fos = new FileOutputStream("test.txt")){
        long start = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            fos.write("123456789012345678901234567890123456789012345678901234567890123\n".getBytes());
        }
        System.out.println("FileOutputStream Time:" + (System.currentTimeMillis() - start) + " ms");
    } catch (IOException e) {
        e.printStackTrace();
    }

八、FileChannel.map

FileChannel提供的map方法可以將文件映射為一個ByteBuffer。通過修改ByteBuffer中的數據會修改文件的內容:

    try(RandomAccessFile file = new RandomAccessFile("test.txt", "rw");
        FileChannel channel = file.getChannel()){
        MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, channel.size());
        buffer.put(0, (byte) 'H');
        buffer.put(1, (byte) 'e');
        buffer.put(2, (byte) 'l');
        buffer.put(3, (byte) 'l');
        buffer.put(4, (byte) 'o');
    } catch (IOException e) {
        e.printStackTrace();
    }

九、FileChannel.transferTo

FileChannel提供的transferTo方法將數據從源通道傳輸到目標通道,實現了零拷貝,速度比傳統的IO流快很多:

    try(RandomAccessFile file = new RandomAccessFile("src.txt", "rw");
        FileChannel srcChannel = file.getChannel();

        RandomAccessFile outputFile = new RandomAccessFile("dest.txt", "rw");
        FileChannel outputChannel = outputFile.getChannel()
    ) {
        long position = 0;
        long count = srcChannel.size();
        srcChannel.transferTo(position, count, outputChannel);
    } catch (IOException e) {
        e.printStackTrace();
    }

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/243387.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-12 12:55
下一篇 2024-12-12 12:55

相關推薦

  • 神經網絡代碼詳解

    神經網絡作為一種人工智能技術,被廣泛應用於語音識別、圖像識別、自然語言處理等領域。而神經網絡的模型編寫,離不開代碼。本文將從多個方面詳細闡述神經網絡模型編寫的代碼技術。 一、神經網…

    編程 2025-04-25
  • Linux sync詳解

    一、sync概述 sync是Linux中一個非常重要的命令,它可以將文件系統緩存中的內容,強制寫入磁盤中。在執行sync之前,所有的文件系統更新將不會立即寫入磁盤,而是先緩存在內存…

    編程 2025-04-25
  • Python安裝OS庫詳解

    一、OS簡介 OS庫是Python標準庫的一部分,它提供了跨平台的操作系統功能,使得Python可以進行文件操作、進程管理、環境變量讀取等系統級操作。 OS庫中包含了大量的文件和目…

    編程 2025-04-25
  • Python輸入輸出詳解

    一、文件讀寫 Python中文件的讀寫操作是必不可少的基本技能之一。讀寫文件分別使用open()函數中的’r’和’w’參數,讀取文件…

    編程 2025-04-25
  • 詳解eclipse設置

    一、安裝與基礎設置 1、下載eclipse並進行安裝。 2、打開eclipse,選擇對應的工作空間路徑。 File -> Switch Workspace -> [選擇…

    編程 2025-04-25
  • Linux修改文件名命令詳解

    在Linux系統中,修改文件名是一個很常見的操作。Linux提供了多種方式來修改文件名,這篇文章將介紹Linux修改文件名的詳細操作。 一、mv命令 mv命令是Linux下的常用命…

    編程 2025-04-25
  • Java BigDecimal 精度詳解

    一、基礎概念 Java BigDecimal 是一個用於高精度計算的類。普通的 double 或 float 類型只能精確表示有限的數字,而對於需要高精度計算的場景,BigDeci…

    編程 2025-04-25
  • git config user.name的詳解

    一、為什麼要使用git config user.name? git是一個非常流行的分布式版本控制系統,很多程序員都會用到它。在使用git commit提交代碼時,需要記錄commi…

    編程 2025-04-25
  • MPU6050工作原理詳解

    一、什麼是MPU6050 MPU6050是一種六軸慣性傳感器,能夠同時測量加速度和角速度。它由三個傳感器組成:一個三軸加速度計和一個三軸陀螺儀。這個組合提供了非常精細的姿態解算,其…

    編程 2025-04-25
  • nginx與apache應用開發詳解

    一、概述 nginx和apache都是常見的web服務器。nginx是一個高性能的反向代理web服務器,將負載均衡和緩存集成在了一起,可以動靜分離。apache是一個可擴展的web…

    編程 2025-04-25

發表回復

登錄後才能評論