目錄
(3)修改hadoop-env.cmd文件中的JAVA_HOME
(4)添加Windows支持文件(winutils.exe,hadoop.dll)
參考:
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種:
- 第1種是參考http://www.codeweblog.com/hdfs-java-api-%E8%AF%A6%E8%A7%A3/,說如果這個值爲真,就會調用一個getRawFileSystem()方法,API上說這個方法將會返回一個本地文件系統。默認是使用HDFS的文件系統,如果是windows系統,需要使用原生的本地文件系統。
- 第2種是參考https://blog.csdn.net/u014432433/article/details/51479720,原文如下:
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();