1. 程式人生 > >Hadoop雲盤系統(轉載)

Hadoop雲盤系統(轉載)

總體概況

    專案名稱:  《Hadoop雲盤系統》                

Ø專案開發環境:Linux下Hadoop分散式系統

Ø專案開發環境:Ubuntu11.04+Hadoop0.20.2+JDK1.6+Eclipse3.3.2。

Ø使用技術:Hadoop + Java

Ø作品描述:1、個人獨立完成,課餘興趣作品。包含全部設計、分析、編碼、優化。

2、功能實現,檔案上傳、下載、刪除、維護、資料夾的新建、檔案路徑跟蹤、以及個人檔案搜尋功能實現和檔案分類展現等。

3、基於Hadoop開發的分散式雲平臺的檔案管理系統。

  一、 概況:     1、這是個人的業餘愛好專案,自己進行了全部的設計、分析、編碼、和優化。
    2、 根據現場需求進行流程分析與編寫。     3、 根據所需求的業務進行開發,程式碼編寫,實現功能。     4、 對程式業務邏輯進行優化,使其達到更高的效能。     專案難點:1、搜尋的實現利用了回溯法進行所有檔案的搜尋,利用字元是否包含來判斷是否進入結果容器中              2、目錄跟蹤顯示的實現 這是本人仿照《百度網盤》,利用Hadoop技術進行開發的《Hadoop雲盤系統》        如下圖所示,《百度網盤》和自己做的《Hadoop雲盤系統》進行了對比。

                 

                  再看個人的《雲盤》

                  

                        總結:介面設計簡潔,整齊,操作方面,使用者體驗良好。

三、Hadoop叢集主要配置和啟動操作操作過程

    1、檢視叢集的主節點配置。先在Linux中啟動Hadoop,如下:檢視現在JPS執行的程序,檢查系統是否正常啟動

                  

      2、檢視 core-site.xml檔案檢視主節點的配置。

                

            無誤後,可以利用Eclipse 啟動程式執行程式了。

四、系統部分測試和主要程式碼解析

            1、上傳檔案

,是從本地檔案系統中上傳到HDFS中,上傳到當前進入的目錄當中

                              

        主要程式碼分析:

[java] view plaincopyprint?
  1. JFileChooser chooser = new JFileChooser();  
  2. chooser.setVisible(true);  
  3. int returnVal = chooser.showOpenDialog(null);  
  4. if (returnVal == JFileChooser.APPROVE_OPTION) {// 為確定或OK是
  5. String localPath = chooser.getSelectedFile()  
  6. .getPath();  
  7. String filename = chooser.getSelectedFile()  
  8. .getName();  
  9. InputStream in = null;  
  10. try {  
  11. in = new BufferedInputStream(  
  12. new FileInputStream(localPath));//本地檔案輸入流
  13. catch (FileNotFoundException e3) {  
  14. e3.printStackTrace();  
  15. }  
  16. OutputStream out = null;  
  17. try {  
  18. out = hdfs.create(new Path(currentPath  
  19. "/" + filename),  
  20. new Progressable() {  
  21. publicvoid progress() {  
  22. System.out.print(".");  
  23. }  
  24. });//HDFS路徑的輸出流抽象
  25. catch (IOException e2) {  
  26. e2.printStackTrace();  
  27. }  
  28. try {  
  29. IOUtils.copyBytes(in, out, 4096true);//利用IOUtils工具類實現上傳
  30. catch (IOException e1) {  
  31. e1.printStackTrace();  
  32. }  
  33. try {  
  34. showTable(currentPath);//上傳完畢就重新整理當前路徑的檔案表格
  35. catch (IOException e1) {  
  36. e1.printStackTrace();  
  37. }  
  38. }   
JFileChooser chooser = new JFileChooser();
chooser.setVisible(true);
int returnVal = chooser.showOpenDialog(null);
if (returnVal == JFileChooser.APPROVE_OPTION) {// 為確定或OK是
String localPath = chooser.getSelectedFile()
.getPath();
String filename = chooser.getSelectedFile()
.getName();
InputStream in = null;
try {
in = new BufferedInputStream(
new FileInputStream(localPath));//本地檔案輸入流
} catch (FileNotFoundException e3) {
e3.printStackTrace();
}
OutputStream out = null;
try {
out = hdfs.create(new Path(currentPath
+ "/" + filename),
new Progressable() {
public void progress() {
System.out.print(".");
}
});//HDFS路徑的輸出流抽象
} catch (IOException e2) {
e2.printStackTrace();
}
try {
IOUtils.copyBytes(in, out, 4096, true);//利用IOUtils工具類實現上傳
} catch (IOException e1) {
e1.printStackTrace();
}
try {
showTable(currentPath);//上傳完畢就重新整理當前路徑的檔案表格
} catch (IOException e1) {
e1.printStackTrace();
}
} 

              2、檔案下載分析:從在HDFS中下載到本地檔案系統中,                                                                    主要程式碼分析:                     [java] view plaincopyprint?
  1. if (e.getSource() == deleItem) {  
  2. int ensuce = JOptionPane.showConfirmDialog(new MainWindow(),  
  3. "確定刪除所選檔案嗎""確認對話方塊", JOptionPane.YES_NO_OPTION);  
  4. if (ensuce == JOptionPane.NO_OPTION) {  
  5. return;  
  6. }  
  7. if (ensuce == JOptionPane.YES_OPTION) {  
  8. if (fileList.getSelectedRow() >= 0) {  
  9. String temp = currentPath  
  10. "/"
  11. + fileList.getValueAt(  
  12. fileList.getSelectedRow(), 0);//獲取要刪掉檔案的路徑
  13. try {  
  14. hdfs.delete(new Path(temp), true);  
  15. catch (IOException e1) {  
  16. e1.printStackTrace();  
  17. }  
  18. try {  
  19. showTable(currentPath);  
  20. catch (IOException e1) {  
  21. e1.printStackTrace();  
  22. }  
  23. }  
  24. }   
if (e.getSource() == deleItem) {
int ensuce = JOptionPane.showConfirmDialog(new MainWindow(),
"確定刪除所選檔案嗎", "確認對話方塊", JOptionPane.YES_NO_OPTION);
if (ensuce == JOptionPane.NO_OPTION) {
return;
}
if (ensuce == JOptionPane.YES_OPTION) {
if (fileList.getSelectedRow() >= 0) {
String temp = currentPath
+ "/"
+ fileList.getValueAt(
fileList.getSelectedRow(), 0);//獲取要刪掉檔案的路徑
try {
hdfs.delete(new Path(temp), true);
} catch (IOException e1) {
e1.printStackTrace();
}
try {
showTable(currentPath);
} catch (IOException e1) {
e1.printStackTrace();
}
}
} 

                  3、檔案表格展現                                                主要程式碼:                           [java] view plaincopyprint?
  1. /*-------------------------------------把currentPath路徑下的檔案和資料夾屬性全都顯示錶格中----------------------------------------------------------*/
  2. privatevoid showTable(String currentPath) throws IOException {  
  3. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");  
  4. Path inputDir = new Path(currentPath);/* 獲取檔案的路徑*/
  5. /* FileStatue類*/
  6. FileStatus[] status = hdfs.listStatus(inputDir);/* 得到檔案路徑目錄下檔案列表*/
  7. DefaultTableModel model = (DefaultTableModel) fileList.getModel(); // 獲取表格模型
  8. if (fileList.getRowCount() != 0) { // 當表格中有資料
  9. ((DefaultTableModel) fileList.getModel()).setRowCount(0);// 將表格置空
  10. }  
  11. for (int i = 0; i < status.length; i++) {  
  12. String filename = null;  
  13. String lenStr = null;  
  14. String modifDate = null;  
  15. filename = status[i].getPath().getName();  
  16. String length = null// 獲取檔案大小資訊
  17. DecimalFormat df = new DecimalFormat("#.00");  
  18. if (status[i].isDir()) {  
  19. lenStr = "-";  
  20. else {  
  21. if (status[i].getLen() > (1024 * 1024 * 1024)) {  
  22. length = df.format(status[i].getLen()  
  23. / (1024.0 * 1024 * 1024));  
  24. lenStr = " " + length + "G";  
  25. elseif (status[i].getLen() > (1024 * 1024)) {  
  26. length = df.format(status[i].getLen() / (1024.0 * 1024));  
  27. lenStr = " " + length + "M";  
  28. elseif (status[i].getLen() > 1024) {  
  29. length = df.format(status[i].getLen() / 1024.0);  
  30. lenStr = " " + length + "KB";  
  31. else {  
  32. length = df.format(status[i].getLen());  
  33. lenStr = " " + length + "B";  
  34. }  
  35. }  
  36. modifDate = sdf.format(status[i].getModificationTime());  
  37. model.addRow(new Object[] { filename, lenStr, modifDate }); // 將檔名、檔案大小、檔案建立日期新增到表格
  38. }  
  39. }  
/*-------------------------------------把currentPath路徑下的檔案和資料夾屬性全都顯示錶格中----------------------------------------------------------*/
private void showTable(String currentPath) throws IOException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
Path inputDir = new Path(currentPath);/* 獲取檔案的路徑*/
/* FileStatue類*/
FileStatus[] status = hdfs.listStatus(inputDir);/* 得到檔案路徑目錄下檔案列表*/
DefaultTableModel model = (DefaultTableModel) fileList.getModel(); // 獲取表格模型
if (fileList.getRowCount() != 0) { // 當表格中有資料
((DefaultTableModel) fileList.getModel()).setRowCount(0);// 將表格置空
}
for (int i = 0; i < status.length; i++) {
String filename = null;
String lenStr = null;
String modifDate = null;
filename = status[i].getPath().getName();
String length = null; // 獲取檔案大小資訊
DecimalFormat df = new DecimalFormat("#.00");
if (status[i].isDir()) {
lenStr = "-";
} else {
if (status[i].getLen() > (1024 * 1024 * 1024)) {
length = df.format(status[i].getLen()
/ (1024.0 * 1024 * 1024));
lenStr = " " + length + "G";
} else if (status[i].getLen() > (1024 * 1024)) {
length = df.format(status[i].getLen() / (1024.0 * 1024));
lenStr = " " + length + "M";
} else if (status[i].getLen() > 1024) {
length = df.format(status[i].getLen() / 1024.0);
lenStr = " " + length + "KB";
} else {
length = df.format(status[i].getLen());
lenStr = " " + length + "B";
}
}
modifDate = sdf.format(status[i].getModificationTime());
model.addRow(new Object[] { filename, lenStr, modifDate }); // 將檔名、檔案大小、檔案建立日期新增到表格
}
}

                      4、檔案搜尋功能實現(利用回溯演算法+字元匹配來實現)                         先測試一下功能吧!我們輸入“Hadoop”關鍵字搜尋比配的檔案                                            再入:輸入“數學”搜尋一下結果                                                                主要實現程式碼 [java] view plaincopyprint?
  1. showAllResult(target);//具體實現 
  2. /*--------------------獲取所有要搜尋到的檔案路徑---------------------------------*/
  3. private List<String> findAllFile(String target) {  
  4. List<String> result = new ArrayList<String>();  
  5. char[] tar = target.toCharArray();  
  6. int count = 0;  
  7. String findPath = currentPath;//預設搜尋的路徑是目前開啟目錄下為根的目錄樹
  8. getAllFile(tar, result, findPath, count);  
  9. return result;  
  10. }  
  11. /*-----------------------------回溯檢測樹形下的檔案---------------------------------------------------------*/
  12. privatevoid getAllFile(char[] tar, List<String> result, String findPath,  
  13. int count) {  
  14. conf = new Configuration();  
  15. try {  
  16. hdfs = FileSystem.get(URI.create(findPath), conf);  
  17. catch (IOException e) {  
  18. e.printStackTrace();  
  19. }  
  20. try {  
  21. if (hdfs.isFile(new Path(findPath))) {  
  22. String name = hdfs.getFileStatus(new Path(findPath)).getPath()  
  23. .getName();  
  24. if (isFind(tar, name.toCharArray())) {//檢測是否字元匹配,匹配為找到
  25. result.add(findPath);// 搜尋到加入陣列
  26. }  
  27. return;  
  28. }  
  29. catch (IOException e) {  
  30. e.printStackTrace();  
  31. }  
  32. FileStatus[] sta = null;  
  33. try {  
  34. sta = hdfs.listStatus(new Path(findPath));  
  35. catch (IOException e) {  
  36. e.printStackTrace();  
  37. }  
  38. for (int i = 0; i < sta.length; i++) {//回溯法實現迴圈遞迴遍歷
  39. getAllFile(tar, result, sta[i].getPath().toString(), count++);  
  40. }  
  41. }  
  42. /*-----------------------檢視字串是否包含--------------------------------------------*/
  43. privateboolean isFind(char[] tar, char[] sour) {  
  44. int all=0.0for (int i = 0; i < tar.length; i++) {  
  45. int j = 0;  
  46. for (; j < sour.length; ++j) {  
  47. if (tar[i] == sour[j]) {  
  48. all++;break;  
  49. }  
  50. }  
  51. if (j == sour.length&&all/sour.length<0.75) {//概率匹配
  52. returnfalse;  
  53. }  
  54. }  
  55. returntrue;  
  56. }  
showAllResult(target);//具體實現 
/*--------------------獲取所有要搜尋到的檔案路徑---------------------------------*/
private List<String> findAllFile(String target) {
List<String> result = new ArrayList<String>();
char[] tar = target.toCharArray();
int count = 0;
String findPath = currentPath;//預設搜尋的路徑是目前開啟目錄下為根的目錄樹
getAllFile(tar, result, findPath, count);
return result;
}
/*-----------------------------回溯檢測樹形下的檔案---------------------------------------------------------*/
private void getAllFile(char[] tar, List<String> result, String findPath,
int count) {
conf = new Configuration();
try {
hdfs = FileSystem.get(URI.create(findPath), conf);
} catch (IOException e) {
e.printStackTrace();
}
try {
if (hdfs.isFile(new Path(findPath))) {
String name = hdfs.getFileStatus(new Path(findPath)).getPath()
.getName();
if (isFind(tar, name.toCharArray())) {//檢測是否字元匹配,匹配為找到
result.add(findPath);// 搜尋到加入陣列
}
return;
}
} catch (IOException e) {
e.printStackTrace();
}
FileStatus[] sta = null;
try {
sta = hdfs.listStatus(new Path(findPath));
} catch (IOException e) {
e.printStackTrace();
}
for (int i = 0; i < sta.length; i++) {//回溯法實現迴圈遞迴遍歷
getAllFile(tar, result, sta[i].getPath().toString(), count++);
}
}
/*-----------------------檢視字串是否包含--------------------------------------------*/
private boolean isFind(char[] tar, char[] sour) {
int all=0.0;for (int i = 0; i < tar.length; i++) {
int j = 0;
for (; j < sour.length; ++j) {
if (tar[i] == sour[j]) {
all++;break;
}
}
if (j == sour.length&&all/sour.length<0.75) {//概率匹配
return false;
}
}
return true;
}

                5、檔案分類實現查詢                         a、檔案分類管理檢視,檢視“文件”列出系統中所有的文件                                                            b、“圖片”                                                             c、“音樂”                                                                 等等 。。。 。。。                    6、其他的實現,目錄檔案跟蹤、檔案維護等:        *最後說說本系統的資訊處理的實現---MapReduce解決            首先說下其實登陸不只是利用資料庫來實現的,解決方法有如下幾種:            方案一:用另外一臺機器專門用於對資料庫操作的。要是在一個Hadoop中叢集中安裝一個數據庫,我們不應該把資料庫放在namenode中,而是放到另外的一臺機,因                           為namenode的任務已經夠多了,安裝在namenode上,多使用者登陸時對資料庫操作會消耗namenode的記憶體,會影響namenode對datanode的管理和排程等。                           所以我們應該放到指定的一臺機器上。           方案二:利用利用Hadoop中分散式資料庫HBase解決。這個毫無疑問是最好的解決方案,是針對雲技術分散式的資料庫。不過本人對HBase還是處於瞭解階段,所以沒                          有用上它。          最終方案:HBase用不上,不過沒關係,因為現在只是對一個使用者資訊處理實現,業務量很少,我可以仿照Hive那樣,在資料進行的時候轉化為MapReduce進行,利用MapReduce來進行表與表的關聯。                            例如如下表:                                        資訊表:                         登陸表:                                                                                                  有待擴充套件的功能模組我的分享----可以做成分享一個檔案提供所有人下載,也可以做成分享給具體的某個使用者。                              實現方式:做一個分享表,記錄了 分享人,被分享人,檔案獲取的路徑(或者獲取檔案所需的引數引數)                                        如下:                                                總結:本人學習Hadoop至今快半年,熟悉HDFS、MapReduce開發,有對過Hadoop HDFS部分、MapReduce原始碼深入分析過,特別是MapReduce、做過不少的MapReduce計算實現。對Hadoop雲技術很感興趣,渴望從事於相關的開發工作。