首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Hadoop HDFS 檔案操作實戰:上傳、下載、刪除完整範例

     編輯:Java 程式設計入門

Hadoop 分散式檔案系統(HDFS)是大數據生態系統的核心儲存層。本文提供使用 Java API 對 HDFS 執行上傳、下載、刪除檔案的完整可執行程式碼,適用於 Hadoop 2.x/3.x 環境。

核心依賴

<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-client</artifactId>
    <version>3.3.4</version> <!-- 對應叢集版本 -->
</dependency>

完整工具類實作

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import java.io.IOException;
import java.io.File;

public class HadoopFile {
    private Configuration conf;

    public HadoopFile() {
        this.conf = new Configuration();
        // 載入核心站點配置(含 fs.defaultFS 等)
        conf.addResource(new Path("/etc/hadoop/core-site.xml"));
    }

    public HadoopFile(Configuration conf) {
        this.conf = conf;
    }

    /** 上傳本地檔案到 HDFS */
    public boolean uploadFile(String hdfsPath, String localFilePath) {
        File localFile = new File(localFilePath);
        if (!localFile.isFile()) {
            System.err.println("本地檔案不存在: " + localFilePath);
            return false;
        }

        try (FileSystem localFS = FileSystem.getLocal(conf);
             FileSystem hdfsFS = FileSystem.get(conf)) {
            
            Path hdfsDir = new Path(hdfsPath);
            Path hdfsFile = new Path(hdfsDir, localFile.getName());
            
            // 確保目標目錄存在
            if (!hdfsFS.exists(hdfsDir)) {
                hdfsFS.mkdirs(hdfsDir);
            }
            
            try (FSDataInputStream in = localFS.open(new Path(localFilePath));
                 FSDataOutputStream out = hdfsFS.create(hdfsFile)) {
                
                byte[] buffer = new byte[8192];  // 8KB 緩衝區
                int bytesRead;
                while ((bytesRead = in.read(buffer)) > 0) {
                    out.write(buffer, 0, bytesRead);
                }
            }
            
            // 列印上傳後目錄內容確認
            FileStatus[] files = hdfsFS.listStatus(hdfsDir);
            for (FileStatus fs : files) {
                System.out.println(fs.getPath() + " [" + fs.getLen() + " bytes]");
            }
            return true;
            
        } catch (IOException e) {
            System.err.println("上傳失敗: " + e.getMessage());
            e.printStackTrace();
            return false;
        }
    }

    /** 刪除 HDFS 上的檔案或目錄 */
    public boolean deleteFile(String hdfsPath) {
        try (FileSystem hdfsFS = FileSystem.get(conf)) {
            Path path = new Path(hdfsPath);
            boolean deleted = hdfsFS.delete(path, true);  // true = 遞迴刪除
            
            if (deleted) {
                System.out.println("刪除成功: " + hdfsPath);
            } else {
                System.out.println("刪除失敗或路徑不存在: " + hdfsPath);
            }
            
            // 列印父目錄內容確認
            FileStatus[] files = hdfsFS.listStatus(path.getParent());
            for (FileStatus fs : files) {
                System.out.println(fs.getPath());
            }
            return deleted;
            
        } catch (IOException e) {
            System.err.println("刪除異常: " + e.getMessage());
            e.printStackTrace();
            return false;
        }
    }

    /** 從 HDFS 下載檔案到本地 */
    public boolean downloadFile(String hdfsFilePath, String localDirPath) {
        try (FileSystem localFS = FileSystem.getLocal(conf);
             FileSystem hdfsFS = FileSystem.get(conf)) {
            
            Path hdfsPath = new Path(hdfsFilePath);
            Path localPath = new Path(localDirPath, hdfsPath.getName());
            
            try (FSDataInputStream in = hdfsFS.open(hdfsPath);
                 FSDataOutputStream out = localFS.create(localPath)) {
                
                byte[] buffer = new byte[8192];
                int bytesRead;
                while ((bytesRead = in.read(buffer)) > 0) {
                    out.write(buffer, 0, bytesRead);
                }
            }
            System.out.println("下載完成: " + localPath);
            return true;
            
        } catch (IOException e) {
            System.err.println("下載失敗: " + e.getMessage());
            e.printStackTrace();
            return false;
        }
    }
    
    public static void main(String[] args) {
        HadoopFile hdfs = new HadoopFile();
        
        // 上傳測試
        hdfs.uploadFile("/user/hadoop/input", "/local/path/data.txt");
        
        // 下載測試
        hdfs.downloadFile("/user/hadoop/output/part-r-00000", "/local/download");
        
        // 刪除測試
        hdfs.deleteFile("/user/hadoop/temp");
    }
}

關鍵 API 對照

操作核心類別/方法說明
取得 FileSystemFileSystem.get(Configuration)需正確配置 core-site.xml 中的 fs.defaultFS
建立輸出流FSDataOutputStream create(Path)覆寫模式,支援 append 需用 append(Path)
建立輸入流FSDataInputStream open(Path)支援 seek 定位讀取
刪除boolean delete(Path, boolean recursive)recursive=true 遞迴刪除目錄
列出目錄FileStatus[] listStatus(Path)取得檔案中繼資料
建立目錄mkdirs(Path)遞迴建立多層目錄

進階用法與最佳實務

大檔案上傳優化

  • 增加緩衝區大小(64KB-256KB)
  • 啟用壓縮:conf.set("mapreduce.output.fileoutputformat.compress", "true")
  • 使用 DistCp (Distributed Copy) 進行叢集間大量資料遷移

Kerberos 安全叢集認證

Configuration conf = new Configuration();
conf.set("hadoop.security.authentication", "kerberos");
UserGroupInformation.setConfiguration(conf);
UserGroupInformation.loginUserFromKeytab("user@REALM", "/path/to/keytab");
FileSystem fs = FileSystem.get(conf);

HDFS HA (High Availability) 配置

conf.set("fs.defaultFS", "hdfs://nameservice1");
conf.set("dfs.nameservices", "nameservice1");
conf.set("dfs.ha.namenodes.nameservice1", "nn1,nn2");
conf.set("dfs.namenode.rpc-address.nameservice1.nn1", "host1:8020");
conf.set("dfs.namenode.rpc-address.nameservice1.nn2", "host2:8020");
conf.set("dfs.client.failover.proxy.provider.nameservice1", 
         "org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider");

常見錯誤排查

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
錯誤現象可能原因解決方向
Connection refusedNameNode 地址/埠錯誤、防火牆阻擋檢查 core-site.xml、telnet 測試連通性
AccessControlException權限不足、Kerberos 未認證檢查 HDFS 權限、keytab 設定
FileAlreadyExistsException上傳目標檔案已存在先刪除或使用 append 模式
LeaseExpiredException寫入過程中租約過期增加 dfs.lease.soft/hard.limit 參數