Hadoop學習(2)Eclipse配置Hadoop開發環境+HDFS Java API測試+Bug解決記錄

目錄

參考:

1. 添加插件

2. 在Windows上安裝Hadoop2.9.1

(1)在本地安裝Hadoop

(2)配置Hadoop的環境變量

(3)修改hadoop-env.cmd文件中的JAVA_HOME

(4)添加Windows支持文件(winutils.exe,hadoop.dll)

(5)重啓Eclipse(File->Restart)

3. Eclipse中的配置

4. 創建HDFS測試項目(Maven工程)

測試代碼1:

(1)錯誤1:

(2)錯誤2:

(3)錯誤3:

(4)錯誤4:

問題總結:

測試代碼2:

測試代碼3:

測試代碼4:

測試代碼5:

copyToLocalFile方法報錯:


參考:

https://www.cnblogs.com/qingyunzong/p/8528134.html

1. 添加插件

下載在Windows Eclipse上需要的一些額外的文件:hadoop-eclipse=plugin-2.7.3.jar、winutils.exe,hadoop.dll,下載地址爲鏈接:https://pan.baidu.com/s/1XpQ4qXGN4XzgwLNsraDKpQ 密碼:obej,然後將hadoop-eclipse=plugin-2.7.3.jar包,並放入到eclipse的plugins文件夾中。

2. 在Windows上安裝Hadoop2.9.1

(1)在本地安裝Hadoop

我的Hadoop集羣版本也是2.9.1(本地與集羣版本最好一致)。將之前搭建集羣所用的hadoop-2.9.1.tar.gz解壓到Windows某目錄下,我的是:E:\softwares\hadoop\hadoop-2.9.1,如下:

(2)配置Hadoop的環境變量

HADOOP_HOME=E:\softwares\hadoop\hadoop-2.9.1

Path=E:\softwares\hadoop\hadoop-2.9.1\bin

(3)修改hadoop-env.cmd文件中的JAVA_HOME

hadoop-env.cmd文件在hadoop的安裝目錄E:\softwares\hadoop\hadoop-2.9.1\下的etc\hadoop\下,我的JAVA_HOME是:C:\Program Files\Java\jdk1.8.0_144。修改完hadoop-env.cmd文件中的JAVA_HOME測試,查看hadoop版本:

經查證,是在hadoop-env.cmd中寫JAVA_HOME的路徑中出現了問題,本來路徑確實是C:\Program Files\Java\jdk1.8.0_144,但路徑名稱“Program Files”中有空格導致了出錯,解決方法如下:

解決參考:

發現原來是路徑上包含了一個空格,所以有以下2個解決辦法:

1.用路徑替代符 C:\Progra~1\Java\jdk1.8.0_144,Progra~1是 C:\Program Files目錄的dos文件名模式下的縮寫,長於8個字符的文件名和文件夾名,都被簡化成前面6個有效字符,後面~1,有重名的就 ~2,~3。

2.用引號括起來 "C:\Program Files"\Java\jdk1.8.0_144

參考:https://blog.csdn.net/wen3011/article/details/54907731

根據上面的思路,將hadoop-env.cmd中的JAVA_HOME的路徑設置成C:\Progra~1\Java\jdk1.8.0_144,如下:

然後運行hadoop version,成功顯示版本信息:

(4)添加Windows支持文件(winutils.exe,hadoop.dll)

  • 1)winutils.exe 放在windows平臺中你安裝的hadoop的bin目錄下

  • 2)  hadoop.dll 放在windows操作系統的 c:/windows/system32目錄下

(5)重啓Eclipse(File->Restart)

出現問題:點擊如下田字格圖標,並沒有出現“小象”Map/Reduce的圖標

點擊Windows-->Preferences查看,也未出現Hadoop Map/Reduce。

解決參考:

這種現象一般由於安裝在eclipse\plugins下的插件沒有導入的問題。解決方法:把 eclipse\configuration\org.eclipse.update 刪除掉。出現這種情況的原因是在你安裝新的插件以前你啓動過 eclipse ,在 org.eclipse.update 文件夾下記錄了插件的歷史更新情況,它只記憶了以前的插件更新情況,而你新安裝的插件它並不記錄。

參考:https://blog.csdn.net/qq_30879741/article/details/72934480

根據上面的思路,我將E:\Eclipse\java-photon\eclipse\configuration\org.eclipse.update\下原先的文件platform.xml刪掉,然後重啓Eclipse(File->Restart),這次小象的圖標就出現了,而且在Window-->Preferences下也出現了Hadoop Map/Reduce。

刪掉,然後重啓Eclipse,點擊右上角“田字格"圖標,出現“小象”Map/Reduce的圖標,如下(網上有很多說eclipse版本的問題,很多刪除eclipse重裝的,我覺得此方法太暴力,可能不是版本問題,就是這個org.eclipse.update的問題,它沒有及時更新eclipse的變化。我的eclipse版本:Photon Release (4.8.0)):

點擊Window-->Preferences查看,出現Hadoop Map/Reduce:

3. Eclipse中的配置

(1)點擊Window->Preferences->Hadoop Map/Reduce,設置Hadoop的安裝目錄:E:\softwares\hadoop\hadoop-2.9.1

(2)打開Hadoop開發視圖:Window->Perspective->Open Perspective->Other...,在出現的如下對話框中選擇小象Map/Reduce

然後右上角會出現小象圖標,以表示是Hadoop開發的視圖(Perspective)(以後可直接點擊這裏的小象圖標切換到Hadoop開發視圖中):

(3)打開Map/Reduce Locations,Window->Show view->Other...,出現如下彈窗,然後選擇MapReduce Tools下的Map/Reduce Locations:

選擇後eclipse左側的Project Explorer會出現左側的DFS Locations,同時也會出現Map/Reduce Locations的view,如下:

新建Hadoop連接:在上圖說顯示的Map/Reduce Locations的view中右鍵,選擇New Hadoop Location...,出現如下彈框,然後填寫相關配置信息:

配置成功後左側的DFS Locations顯示如下:

而這正與我的Hadoop HDFS的目錄結構一致:

4. 創建HDFS測試項目(Maven工程)

測試代碼1:

package demo.MavenTest;
import java.net.URI;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;

public class HdfsClientTest {

	public static void main(String[] args) throws Exception{
		// TODO Auto-generated method stub
		Configuration conf = new Configuration();
		FileSystem fs = FileSystem.get(new URI("hdfs://10.10.129.200:9000"), conf, "hadoop");

        //測試查看HDFS根目錄
		FileStatus[] listStatus = fs.listStatus(new Path("/"));
		for (FileStatus fileStatus : listStatus) {
			System.out.println(fileStatus);
		}//end for
  fs.close();
	}//end main

}//end class

對應的pom依賴如下:

<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-common -->
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-common</artifactId>
    <version>2.9.1</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-hdfs -->
    <dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-hdfs</artifactId>
    <version>2.9.1</version>
</dependency>

運行程序:(Run as->Run on hadoop)

(1)錯誤1:

Exception in thread "main" java.lang.NoClassDefFoundError: com/ctc/wstx/io/InputBootstrapper

解決:添加pom依賴(參考:https://zhuanlan.zhihu.com/p/38630695):

<!-- https://mvnrepository.com/artifact/com.fasterxml.woodstox/woodstox-core -->
<dependency>
    <groupId>com.fasterxml.woodstox</groupId>
    <artifactId>woodstox-core</artifactId>
    <version>5.0.3</version>
</dependency>

保存後重新運行,出現錯誤2:

(2)錯誤2:

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/collections/map/UnmodifiableMap

解決:添加pom依賴:

<!-- https://mvnrepository.com/artifact/commons-collections/commons-collections -->
<dependency>
    <groupId>commons-collections</groupId>
    <artifactId>commons-collections</artifactId>
    <version>3.2.2</version>
</dependency>

保存後重新運行,出現錯誤3:

(3)錯誤3:

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/configuration/Configuration

解決:添加pom依賴:

<!-- https://mvnrepository.com/artifact/commons-configuration/commons-configuration -->
<dependency>
    <groupId>commons-configuration</groupId>
    <artifactId>commons-configuration</artifactId>
    <version>1.6</version>
</dependency>

保存後重新運行,出現錯誤4:

(4)錯誤4:

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/hadoop/util/PlatforName

解決:添加pom依賴(參考:https://blog.csdn.net/Xgx120413/article/details/51889743):

<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-auth -->
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-auth</artifactId>
    <version>2.9.1</version>
</dependency>

保存後重新運行,程序執行成功:

問題總結:

按說添加了hadoop-common和hadoop-hdfs後,其相應的一些依賴都會下載到本地mvn庫,可能在下載時有漏掉一些依賴,每個人這時的錯誤提示可能有所不一樣,但只需要根據錯誤提示,在pom文件中補上程序運行所需要的依賴即可。我所加入的各個依賴的版本號。是依據於我搭建的Hadoop集羣以及Windows本地Hadoop版本來的,查看這些依賴的jar包及版本號,可以在E:\softwares\hadoop\hadoop-2.9.1\share\hadoop\文件夾下的common文件夾和hdfs文件夾查看,例如hdfs文件夾:

這裏hdfs文件夾下的jar包是hdfs核心包,在lib文件夾下是其依賴jar包,這些都會需要。在這裏可以也查看到相應jar包的版本。

測試代碼2:

Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(new URI("hdfs://10.10.129.200:9000"), conf, "hadoop");

//上傳本地文件到HDFS
fs.copyFromLocalFile(new Path("C:/Users/a/Desktop/hadoopTest/hello.txt"), new Path("/test/input/javaApiTest.txt"));

fs.close();

執行成功,在左側的DFS Locations裏可以看到/test/input/下多了一個文件javaApiTest.txt,其中r3表示有3個副本。

測試代碼3:

Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(new URI("hdfs://10.10.129.200:9000"), conf, "hadoop");

//上傳(流式處理,更底層)
InputStream in = new FileInputStream(new File("C:/Users/a/Desktop/hadoopTest/hello.txt"));
FSDataOutputStream out = fs.create(new Path("/test/input/javaApiTest2.txt"));
IOUtils.copyBytes(in, out, 4096, true);

fs.close();

執行成功,在左側的DFS Locations裏可以看到/test/input/下多了一個文件javaApiTest2.txt,其中r3表示有3個副本。

測試代碼4:

Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(new URI("hdfs://10.10.129.200:9000"), conf, "hadoop");

//下載(流式處理,更底層)
FSDataInputStream in2 = fs.open(new Path("/test/input/words.txt"));
OutputStream out2 = new FileOutputStream(new File("C:/Users/a/Desktop/hadoopTest/words2.txt"));
IOUtils.copyBytes(in2, out2, 4096, true);

fs.close();

執行成功,可看到在C:\Users\a\Desktop\hadoopTest\文件夾下,已經下載下來文件words.txt:

測試代碼5:

Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(new URI("hdfs://10.10.129.200:9000"), conf, "hadoop");

//從HDFS上下載文件到本地
fs.copyToLocalFile(new Path("/test/input/words.txt"), new Path("C:/Users/a/Desktop/hadoopTest/words.txt"));

fs.close();

copyToLocalFile方法報錯:

log4j:WARN No appenders could be found for logger (org.apache.hadoop.metrics2.lib.MutableMetricsFactory).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Exception in thread "main" java.lang.UnsatisfiedLinkError: org.apache.hadoop.io.nativeio.NativeIO$Windows.createFileWithMode0(Ljava/lang/String;JJJI)Ljava/io/FileDescriptor;
	at org.apache.hadoop.io.nativeio.NativeIO$Windows.createFileWithMode0(Native Method)
	at org.apache.hadoop.io.nativeio.NativeIO$Windows.createFileOutputStreamWithMode(NativeIO.java:556)
	at org.apache.hadoop.fs.RawLocalFileSystem$LocalFSFileOutputStream.<init>(RawLocalFileSystem.java:229)
	at org.apache.hadoop.fs.RawLocalFileSystem$LocalFSFileOutputStream.<init>(RawLocalFileSystem.java:219)
	at org.apache.hadoop.fs.RawLocalFileSystem.createOutputStreamWithMode(RawLocalFileSystem.java:314)
	at org.apache.hadoop.fs.RawLocalFileSystem.create(RawLocalFileSystem.java:302)
	at org.apache.hadoop.fs.RawLocalFileSystem.create(RawLocalFileSystem.java:334)
	at org.apache.hadoop.fs.ChecksumFileSystem$ChecksumFSOutputSummer.<init>(ChecksumFileSystem.java:399)
	at org.apache.hadoop.fs.ChecksumFileSystem.create(ChecksumFileSystem.java:462)
	at org.apache.hadoop.fs.ChecksumFileSystem.create(ChecksumFileSystem.java:441)
	at org.apache.hadoop.fs.FileSystem.create(FileSystem.java:1067)
	at org.apache.hadoop.fs.FileSystem.create(FileSystem.java:1048)
	at org.apache.hadoop.fs.FileSystem.create(FileSystem.java:937)
	at org.apache.hadoop.fs.FileUtil.copy(FileUtil.java:391)
	at org.apache.hadoop.fs.FileUtil.copy(FileUtil.java:364)
	at org.apache.hadoop.fs.FileUtil.copy(FileUtil.java:314)
	at org.apache.hadoop.fs.FileSystem.copyToLocalFile(FileSystem.java:2375)
	at org.apache.hadoop.fs.FileSystem.copyToLocalFile(FileSystem.java:2344)
	at org.apache.hadoop.fs.FileSystem.copyToLocalFile(FileSystem.java:2320)
	at demo.MavenTest.HdfsClientTest.main(HdfsClientTest.java:52)

查看copyToLocalFile的源碼:

public void copyToLocalFile(Path src, Path dst) throws IOException {
    copyToLocalFile(false, src, dst);
}

繼續跟蹤:

public void copyToLocalFile(boolean delSrc, Path src, Path dst)throws IOException {
    copyToLocalFile(delSrc, src, dst, false);
}

繼續跟蹤:


  /**
   * The src file is under this filesystem, and the dst is on the local disk.
   * Copy it from the remote filesystem to the local dst name.
   * delSrc indicates if the src will be removed
   * or not. useRawLocalFileSystem indicates whether to use RawLocalFileSystem
   * as the local file system or not. RawLocalFileSystem is non checksumming,
   * So, It will not create any crc files at local.
   *
   * @param delSrc
   *          whether to delete the src
   * @param src
   *          path
   * @param dst
   *          path
   * @param useRawLocalFileSystem
   *          whether to use RawLocalFileSystem as local file system or not.
   *
   * @throws IOException for any IO error
   */
  public void copyToLocalFile(boolean delSrc, Path src, Path dst,
      boolean useRawLocalFileSystem) throws IOException {
    Configuration conf = getConf();
    FileSystem local = null;
    if (useRawLocalFileSystem) {
      local = getLocal(conf).getRawFileSystem();
    } else {
      local = getLocal(conf);
    }
    FileUtil.copy(this, src, local, dst, delSrc, conf);
  }

參數1->delSrc表示:是否要深處源文件;

參數2->src表示:要copy的源文件路徑;

參數3->dst表示:copy的目標文件路徑;

參數4->useRawLocalFileSystem表示:註釋上說useRawLocalFileSystem指示是否使用RawLocalFileSystem作爲本地文件系統。

關於參數useRawLocalFileSystem的解釋網上找了主要有2種:

hadoop是一個綜合文件系統,並不等價於hdfs文件系統。hadoop集成了衆多的文件系統, hdfs僅僅是hadoop旗艦級文件系統。Hadoop的這個特點充分體現了hadoop的優良的可擴展性。在hadoop裏,hadoop定義了一個抽象的文件系統的概念,類:org.apache.hadoop.fs.FileSystm,這個抽象類用來定義hadoop中的一個文件系統接口,只要某個文件系統實現了這個接口,就可以作爲hadoop支持的文件系統。

Hadoop LocalFileSystem是客戶端校驗的類。在使用LocalFileSystem寫文件時,會透明的創建一個.filename.crc的文件。 校驗文件大小的字節數由io.bytes.per.checksum屬性設置,默認是512bytes,即每512字節就生成一個CRC-32校驗和。.filename.crc文件會存 io.bytes.per.checksum的信息。在讀取的時候,會根據此文件進行校驗。事實上LocalFileSystem是通過繼承ChecksumFileSystem實現校驗的工作。

文件

系統

URI

方案  

Java實現

(org.apache.hadoop)

定義

Local

file

fs.LocalFileSystem

支持有客戶端校驗和本地文件系統。

帶有校驗和的本地系統文件在fs.RawLocalFileSystem中實現。

從上面內容可知,當設置useRawLocalFileSystem爲true時就是指使用Hadoop LocalFileSystem,即開啓校驗。所以參數useRawLocalFileSystem就是表示是否開啓文件校驗。

解決:將代碼 fs.copyToLocalFile(new Path("/test/input/words.txt"), new Path("C:/Users/a/Desktop/hadoopTest/words.txt"));改爲 fs.copyToLocalFile(false, new Path("/test/input/words.txt"), new Path("C:/Users/a/Desktop/hadoopTest/words.txt"), true);後程序即可執行成功,在C:\Users\a\Desktop\hadoopTest\文件夾下多了文件words.txt。

Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(new URI("hdfs://10.10.129.200:9000"), conf, "hadoop");

//從HDFS上下載文件到本地
//fs.copyToLocalFile(new Path("/test/input/words.txt"), new Path("C:/Users/a/Desktop/hadoopTest/words.txt"));
fs.copyToLocalFile(false, new Path("/test/input/words.txt"), new Path("C:/Users/a/Desktop/hadoopTest/words.txt"), true);

fs.close();

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章