march alex's blog
          hello,I am march alex
          posts - 52,comments - 7,trackbacks - 0
          MyFrame類用于實現數據的增刪改查。
          代碼用JFrame進行了演示,其中的每一個按鍵都添加了事件監聽。
              這里假定mysql數據庫的端口號是3306。
              數據庫是my_database。
              表是user。
              表中包含name和score兩個元素。
          使用前注意引入JDBC的jar包作為外部jar包。

          import java.awt.Container;
          import java.awt.FlowLayout;
          import java.awt.event.ActionEvent;
          import java.awt.event.ActionListener;
          import java.sql.Connection;
          import java.sql.DriverManager;
          import java.sql.ResultSet;
          import java.sql.SQLException;
          import java.sql.Statement;

          import javax.swing.JButton;
          import javax.swing.JFrame;
          import javax.swing.JLabel;
          import javax.swing.JTextField;


          public class MyFrame extends JFrame {
              private static final int Width = 420;
              private static final int Height = 300;
              private static JFrame frame = null;
              //private static Container ctn = null;
              private static FlowLayout flowLayout = null;
              private static JLabel nameLabel = null;
              private static JLabel scoreLabel = null;
              private static JTextField nameText = null;
              private static JTextField scoreText = null;
              private static JButton addButton = null;
              private static JButton deleteButton = null;
              private static JButton modifyButton = null;
              private static JButton searchButton = null;
              private static JLabel resultLabel = null;
              private static JTextField resultText = null;
              private static JButton closeButton = null;
              
              private static String driver = "com.mysql.jdbc.Driver";
              private static String url = "jdbc:mysql://localhost:3306/my_database";
              private static String userName = "root";
              private static String password = "root";
              private static Connection conn = null;
              private static Statement stmt = null;
              
              public MyFrame() {
                  frame = new JFrame("JFrame connect MySQL");
                  flowLayout = new FlowLayout(FlowLayout.LEFT);
                  flowLayout.setHgap(20);
                  flowLayout.setVgap(30);
                  frame.setLayout(flowLayout);
                  nameLabel = new JLabel("name");
                  scoreLabel = new JLabel("score");
                  nameText = new JTextField(10);
                  scoreText = new JTextField(10);
                  addButton = new JButton("ADD");
                  deleteButton = new JButton("DELETE");
                  modifyButton = new JButton("MODIFY");
                  searchButton = new JButton("SEARCH");
                  resultLabel = new JLabel("result");
                  resultText = new JTextField(30);
                  closeButton = new JButton("CLOSE");
                  
                  frame.add(nameLabel);
                  frame.add(nameText);
                  frame.add(scoreLabel);
                  frame.add(scoreText);
                  frame.add(addButton);
                  frame.add(deleteButton);
                  frame.add(modifyButton);
                  frame.add(searchButton);
                  frame.add(resultLabel);
                  frame.add(resultText);
                  frame.add(closeButton);
                  
                  addButton.addActionListener(new ButtonAction());
                  deleteButton.addActionListener(new ButtonAction());
                  modifyButton.addActionListener(new ButtonAction());
                  searchButton.addActionListener(new ButtonAction());
                  closeButton.addActionListener(new ButtonAction());
                  
                  frame.setVisible(true);
                  frame.setSize(Width, Height);
                  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              }
              
              private class ButtonAction implements ActionListener {
                  public void actionPerformed(ActionEvent evt) {
                      Object s = evt.getSource();
                      String name = nameText.getText();
                      String score = scoreText.getText();
                      if(s == addButton) {
                          if(name.length()==0 || score.length()==0) {
                              System.out.println("Please enter the name and score!");
                          }
                          else {
                              String sqlInsert = 
                                  "INSERT INTO my_table (name,score) VALUES (\"" + name + "\"," + score + ");";
                              try {
                                  stmt.executeUpdate(sqlInsert);
                              } catch (SQLException e) {
                                  e.printStackTrace();
                              }
                              System.out.println("Add " + name + " Succeed!");
                          }
                      } else if(s == deleteButton) {
                          if(name.length() == 0) {
                              System.out.println("You must enter the name");
                              return;
                          } else if(score.length() == 0) {
                              String sqlDelete = "DELETE FROM my_table WHERE name=\"" + name + "\";";
                              try {
                                  stmt.executeUpdate(sqlDelete);
                              } catch (SQLException e) {
                                  e.printStackTrace();
                              }
                          } else {
                              String sqlDelete = "DELETE FROM my_table WHERE name=\"" + name 
                                      + "\" and score<=" + score + ";";
                              try {
                                  stmt.executeUpdate(sqlDelete);
                              } catch (SQLException e) {
                                  e.printStackTrace();
                              }
                          }
                          System.out.println("Delete succeed!");
                      } else if(s == modifyButton) {
                          if(name.length() == 0 || score.length() == 0) {
                              System.out.println("Please enter the name and score you want to modify!");
                          } else {
                              String sqlModify = "UPDATE my_table SET name=\"" + name 
                                      + "\" WHERE score=" + score + ";";
                              try {
                                  stmt.executeUpdate(sqlModify);
                              } catch (SQLException e) {
                                  e.printStackTrace();
                              }
                              System.out.println("Modify " + name + " succeed!");
                          }
                      } else if(s == searchButton) {
                          String sqlName = " name=\"" + name + "\"";
                          String sqlScore = " score=" + score;
                          String sqlSelect = "SELECT * FROM my_table";
                          if(name.length() == 0 && score.length() == 0) {
                              ;
                          } else if(score.length() == 0) {
                              sqlSelect += " WHERE" + sqlName + ";";
                          } else if(name.length() == 0) {
                              sqlSelect += " WHERE" + sqlScore + ";";
                          } else {
                              sqlSelect += " WHERE" + sqlName + " and" + sqlScore + ";";  
                          }
                          //System.out.println(sqlSelect);
                          try {
                              ResultSet res = stmt.executeQuery(sqlSelect);
                              while(res.next()) {
                                  String ansName = res.getString(1);
                                  String ansScore = res.getString(2);
                                  System.out.println(ansName + " get score: " + ansScore);
                              }
                          } catch (SQLException e) {
                              e.printStackTrace();
                          }
                      } else if(s == closeButton) {
                          try {
                              stmt.close();
                              if(conn != null)
                                  conn.close();
                          } catch (SQLException e) {
                              System.out.println("SQLException異常"+e.getMessage());
                              e.printStackTrace();
                          }
                      }
                  }
              }
              
              public static void main(String[] args) {
                  try {
                      Class.forName(driver);
                      System.out.println("數據庫連接成功");
                  } catch (ClassNotFoundException e) {
                      System.out.println("ClassNotFoundException");
                  }
                  try {
                      conn = DriverManager.getConnection(url, userName, password);
                      System.out.println("connect database successful");
                      stmt = conn.createStatement();
                      new MyFrame();
                  } catch (SQLException e) {
                      System.out.println("SQLException異常"+e.getMessage());
                      e.printStackTrace();
                  }
                  
              }
          }

          posted @ 2015-03-08 16:43 marchalex 閱讀(661) | 評論 (0)編輯 收藏
          MapReduce是一種可用于數據處理的變成模型。
          這里主要講述Java語言實現MapReduce。
          一個投票模型:
          Jobs很喜歡給女生打分,好看的打100分,難看的打0分。有一次他給Lucy打了0分,結果被Lucy痛打了一頓。
          還有一次,Jobs給兩個美女打分,給美女Alice打了99分,給美女Candice打了98分。
          這個時候Alex就看不下去了,他于是站起來說:“明明是Candice比較好看嘛!”。
          兩人于是爭執起來,為了證明自己的觀點,結果爆發了一場大戰!什么降龍十八掌啊,黯然銷魂掌啊,他們都不會。
          那么怎么才能讓對方輸的心服口服呢?他們想到“群眾的眼睛是雪亮的”!于是他們發動了班上的20名同學進行投票。
          結果出來了,Alice的平均分是98.5,Candice的平均分是99.7,以壓倒性的優勢獲得了勝利。
          但是Jobs不服,于是把班上每個女生的照片放到了網上,讓大家來評分,最后他得到了好多文件,用自己的電腦算根本忙不過來,于是他想到了用Hadoop寫一個MapReduce程序。
          一直輸入文件的格式是:"[user]\t[girlname]\t[point]".例:
          alex    alice   88
          alex    candice 100
          jobs    alice   100
          john    lucy    89

          在這里,我們假設每個人的評分都為0到100的整數,最終的結果向下取整。那么MapReduce程序可以寫成如下:

          我們需要三樣東西:一個map函數,一個reduce函數,和一些用來運行作業的代碼。
          map函數由Mapper接口實現來表示,后者聲明了一個map()方法。
          AverageMapper.java

          import java.io.IOException;

          import org.apache.hadoop.io.IntWritable;
          import org.apache.hadoop.io.Text;
          import org.apache.hadoop.mapred.MapReduceBase;
          import org.apache.hadoop.mapred.Mapper;
          import org.apache.hadoop.mapred.OutputCollector;
          import org.apache.hadoop.mapred.Reporter;

          public class AverageMapper extends MapReduceBase
            implements Mapper<IntWritable, Text, Text, IntWritable> {
                  
                  public void map(IntWritable key, Text value,
                                  OutputCollector<Text, IntWritable> output, Reporter reporter)
                                  throws IOException {
                          
                          String s = value.toString();
                          String name = new String();
                          int point = 0;
                          int i;
                          for(i=0;i<s.length() && s.charAt(i)!='\t';i++);
                          for(i++;i<s.length() && s.charAt(i)!='\t';i++) {
                                  name += s.charAt(i);
                          }
                          for(i++;i<s.length();i++) {
                                  point = point * 10 + (s.charAt(i) - '0');
                          }
                          if(name.length() != 0 && point >=0 && point <= 100) {
                                  output.collect(new Text(name), new IntWritable(point));
                          }
                  }
          }

          該Mapper接口是一個泛型類型,他有四個形參類型,分別指定map函數的輸入鍵、輸入值、輸出鍵、輸出值的類型。
          以示例來說,輸入鍵是一個整形偏移量(表示行號),輸入值是一行文本,輸出鍵是美女的姓名,輸出值是美女的得分。
          Hadoop自身提供一套可優化網絡序列化傳輸的基本類型,而不直接使用Java內嵌的類型。這些類型均可在org.apache.hadoop.io包中找到。
          這里我們使用IntWritable類型(相當于Java中的Integer類型)和Text類型(想到與Java中的String類型)。
          map()方法還提供了OutputCollector示例用于輸出內容的寫入。
          我們只在輸入內容格式正確的時候才將其寫入輸出記錄中。

          reduce函數通過Reducer進行類似的定義。
          AverageReducer.java

          import java.io.IOException;
          import java.util.Iterator;

          import org.apache.hadoop.io.IntWritable;
          import org.apache.hadoop.io.Text;
          import org.apache.hadoop.mapred.MapReduceBase;
          import org.apache.hadoop.mapred.OutputCollector;
          import org.apache.hadoop.mapred.Reducer;
          import org.apache.hadoop.mapred.Reporter;


          public class AverageReducer extends MapReduceBase
            implements Reducer<Text, IntWritable, Text, IntWritable> {
                  
                  public void reduce(Text key, Iterator<IntWritable> values,
                                  OutputCollector<Text, IntWritable> output, Reporter reporter)
                                  throws IOException {
                          
                          long tot_point = 0, num = 0;
                          while(values.hasNext()) {
                                  tot_point += values.next().get();
                                  num ++;
                          }
                          int ave_point = (int)(tot_point/num);
                          output.collect(key, new IntWritable(ave_point));
                  }
          }

          第三部分代碼負責運行MapReduce作業。
          Average.java
          import java.io.IOException;

          import org.apache.hadoop.fs.Path;
          import org.apache.hadoop.io.IntWritable;
          import org.apache.hadoop.io.Text;
          import org.apache.hadoop.mapred.FileInputFormat;
          import org.apache.hadoop.mapred.FileOutputFormat;
          import org.apache.hadoop.mapred.JobConf;


          public class Average {
                  public static void main(String[] args) throws IOException {
                          if(args.length != 2) {
                                  System.err.println("Usage: Average <input path> <output path>");
                                  System.exit(-1);
                          }
                          JobConf conf = new JobConf(Average.class);
                          conf.setJobName("Average");
                          FileInputFormat.addInputPath(conf, new Path(args[0]));
                          FileOutputFormat.setOutputPath(conf, new Path(args[1]));
                          conf.setMapperClass(AverageMapper.class);
                          conf.setReducerClass(AverageReducer.class);
                          conf.setOutputKeyClass(Text.class);
                          conf.setOutputValueClass(IntWritable.class);
                  }
          }

          JobConf對象指定了作業執行規范。我們可以用它來控制整個作業的運行。
          在Hadoop作業上運行著寫作業時,我們需要將代碼打包成一個JAR文件(Hadoop會在集群上分發這些文件)。
          我們無需明確指定JAR文件的名稱,而只需在JobConf的構造函數中傳遞一個類,Hadoop將通過該類查找JAR文件進而找到相關的JAR文件。
          構造JobCOnf對象之后,需要指定輸入和輸出數據的路徑。
          調用FileInputFormat類的靜態方法addInputPath()來定義輸入數據的路徑。
          可以多次調用addInputOath()實現多路徑的輸入。
          調用FileOutputFormat類的靜態函數SetOutputPath()來指定輸出路徑。
          該函數指定了reduce函數輸出文件的寫入目錄。
          在運行任務前該目錄不應該存在,否則Hadoop會報錯并拒絕運行該任務。
          這種預防措施是為了防止數據丟失。
          接著,通過SetMapperClass()和SetReducerClass()指定map和reduce類型。
          輸入類型通過InputFormat類來控制,我們的例子中沒有設置,因為使用的是默認的TextInputFormat(文本輸入格式)。

          新增的Java MapReduce API


          新的Hadoop在版本0.20.0包含有一個新的Java MapReduce API,又是也稱為"上下文對象"(context object),旨在使API在今后更容易擴展。
          新特性:
          傾向于使用虛類,而不是接口;
          新的API放在org.apache.hadoop.mapreduce包中(舊版本org.apache.hadoop.mapred包);
          新的API充分使用上下文對象,使用戶代碼能與MapReduce通信。例如:MapContext基本具備了JobConf,OutputCollector和Reporter的功能;
          新的API同時支持“推”(push)和“拉”(pull)的迭代。這兩類API,均可以將鍵/值對記錄推給mapper,但除此之外,新的API也允許把記錄從map()方法中拉出、對reducer來說是一樣的。拉式處理的好處是可以實現批量處理,而非逐條記錄的處理。
          新的API實現了配置的統一。所有作業的配置均通過Configuration來完成。(區別于舊API的JobConf)。
          新API中作業控制由Job類實現,而非JobClient類,新API中刪除了JobClient類。
          輸出文件的命名稍有不同。

          用新上下文對象來重寫Average應用

          import java.io.IOException;

          import org.apache.hadoop.fs.Path;
          import org.apache.hadoop.io.IntWritable;
          import org.apache.hadoop.io.Text;
          import org.apache.hadoop.mapreduce.Job;
          import org.apache.hadoop.mapreduce.Mapper;
          import org.apache.hadoop.mapreduce.Reducer;
          import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
          import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

          public class NewAverage {
                  
                  static class NewAverageMapper
                    extends Mapper<IntWritable, Text, Text, IntWritable> {
                          
                          public void map(IntWritable key, Text value, Context context) 
                                  throws IOException, InterruptedException {
                                  
                                  String s = value.toString();
                                  String name = new String();
                                  int point = 0;
                                  int i;
                                  for(i=0;i<s.length() && s.charAt(i)!='\t';i++);
                                  for(i++;i<s.length() && s.charAt(i)!='\t';i++) {
                                          name += s.charAt(i);
                                  }
                                  for(i++;i<s.length();i++) {
                                          point = point * 10 + (s.charAt(i) - '0');
                                  }
                                  if(name.length() != 0 && point >=0 && point <= 100) {
                                          context.write(new Text(name), new IntWritable(point));
                                  }
                          }
                  }
                  
                  static class NewAverageReducer
                    extends Reducer<Text, IntWritable, Text, IntWritable> {
                          
                          public void reduce(Text key, Iterable<IntWritable> values,
                                          Context context)
                                          throws IOException, InterruptedException {
                                  
                                  long tot_point = 0, num = 0;
                                  for(IntWritable value : values) {
                                          tot_point += value.get();
                                          num ++;
                                  }
                                  int ave_point = (int)(tot_point/num);
                                  context.write(key, new IntWritable(ave_point));
                          }
                  }
                  
                  public static void main(String[] args) throws Exception {
                          if(args.length != 2) {
                                  System.err.println("Usage: NewAverage <input path> <output path>");
                                  System.exit(-1);
                          }
                          Job job = new Job();
                          job.setJarByClass(NewAverage.class);
                          
                          FileInputFormat.addInputPath(job, new Path(args[0]));
                          FileOutputFormat.setOutputPath(job, new Path(args[1]));
                          
                          job.setMapperClass(NewAverageMapper.class);
                          job.setReducerClass(NewAverageReducer.class);
                          job.setOutputKeyClass(Text.class);
                          job.setOutputValueClass(IntWritable.class);
                          
                          System.exit(job.waitForCompletion(true) ? 0 : 1);
                  }
          }
          posted @ 2015-03-08 13:27 marchalex 閱讀(1384) | 評論 (0)編輯 收藏
          之前我寫過獲得tmall上qfour某單品頁上第一張圖片的程序
          這次我又在qfour上面選了一個貓娘志2015春秋新款女裝顯瘦小清新碎花長袖田園連衣裙女單品頁用于獲得下面的這張圖。

          這張圖對應的url為:http://gi4.md.alicdn.com/bao/uploaded/i4/TB1aRpnHpXXXXaNXVXXXXXXXXXX_!!0-item_pic.jpg
          我寫了一個ImageDownload類,其中的download方法用于下載url對應的圖片并保存在特定的本地目錄上。代碼如下:
          import java.io.File;
          import java.io.FileOutputStream;
          import java.io.InputStream;
          import java.io.OutputStream;
          import java.net.URL;
          import java.net.URLConnection;


          public class ImageDownload {
              public static void download(String urlString, String filename) throws Exception {  

                  URL url = new URL(urlString); // 構造URL  
                  URLConnection con = url.openConnection();  // 打開鏈接
                  con.setConnectTimeout(5*1000);  //設置請求超時為5s  
                  InputStream is = con.getInputStream();  // 輸入流  
                  byte[] bs = new byte[1024];  // 1K的數據緩沖  
                  int len;  // 讀取到的數據長度  
                  int i = filename.length();
                  for(i--;i>=0 && filename.charAt(i) != '\\' && filename.charAt(i) != '/';i--);
                  String s_dir = filename.substring(0, i);
                  File dir = new File(s_dir);  // 輸出的文件流  
                  if(!dir.exists()){  
                      dir.mkdirs();  
                  }  
                  OutputStream os = new FileOutputStream(filename);  
                  // 開始讀取  
                  while ((len = is.read(bs)) != -1) {  
                    os.write(bs, 0, len);  
                  }  
                  // 完畢,關閉所有鏈接  
                  os.close();  
                  is.close();  
              }
              
              public static void main(String[] args) throws Exception {
                  download("http://gi4.md.alicdn.com/bao/uploaded/i4/TB1aRpnHpXXXXaNXVXXXXXXXXXX_!!0-item_pic.jpg", "d:\\qfour\\sample.jpg");
              }
          }  
          posted @ 2015-03-08 12:33 marchalex 閱讀(1759) | 評論 (0)編輯 收藏
          檢測設備的運行狀態,有的是使用ping的方式來檢測的。所以需要使用java來實現ping功能。
          為了使用java來實現ping的功能,有人推薦使用java的 Runtime.exec()方法來直接調用系統的Ping命令,也有人完成了純Java實現Ping的程序,使用的是Java的NIO包(native io, 高效IO包)。但是設備檢測只是想測試一個遠程主機是否可用。所以,可以使用以下三種方式來實現:

          1.Jdk1.5的InetAddresss方式

          自從Java 1.5,java.net包中就實現了ICMP ping的功能。
          見:Ping類的ping(String)函數。
          使用時應注意,如果遠程服務器設置了防火墻或相關的配制,可能會影響到結果。另外,由于發送ICMP請求需要程序對系統有一定的權限,當這個權限無法滿足時, isReachable方法將試著連接遠程主機的TCP端口 7(Echo)。

          2.最簡單的辦法,直接調用CMD

          見Ping類的ping02(String)函數。

          3.Java調用控制臺執行ping命令

          具體的思路是這樣的:
          通過程序調用類似“ping 127.0.0.1 -n 10 -w 4”的命令,這命令會執行ping十次,如果通順則會輸出類似“來自127.0.0.1的回復: 字節=32 時間<1ms TTL=64”的文本(具體數字根據實際情況會有變化),其中中文是根據環境本地化的,有些機器上的中文部分是英文,但不論是中英文環境, 后面的“<1ms TTL=62”字樣總是固定的,它表明一次ping的結果是能通的。如果這個字樣出現的次數等于10次即測試的次數,則說明127.0.0.1是百分之百能連通的。
          技術上:具體調用dos命令用Runtime.getRuntime().exec實現,查看字符串是否符合格式用正則表達式實現。
          見Ping類的ping(String,int,int)函數。
          import java.io.BufferedReader;
          import java.io.IOException;
          import java.io.InputStreamReader;
          import java.net.InetAddress;
          import java.net.UnknownHostException;
          import java.util.regex.Matcher;
          import java.util.regex.Pattern;

          public class Ping {
              
              public static boolean ping(String ipAddress) throws Exception {
                  int  timeOut =  3000 ;  //超時應該在3鈔以上        
                  boolean status = InetAddress.getByName(ipAddress).isReachable(timeOut);     // 當返回值是true時,說明host是可用的,false則不可。
                  return status;
              }
              
              public static void ping02(String ipAddress) throws Exception {
                  String line = null;
                  try {
                      Process pro = Runtime.getRuntime().exec("ping " + ipAddress);
                      BufferedReader buf = new BufferedReader(new InputStreamReader(
                              pro.getInputStream()));
                      while ((line = buf.readLine()) != null)
                          System.out.println(line);
                  } catch (Exception ex) {
                      System.out.println(ex.getMessage());
                  }
              }
              
              public static boolean ping(String ipAddress, int pingTimes, int timeOut) {  
                  BufferedReader in = null;  
                  Runtime r = Runtime.getRuntime();  // 將要執行的ping命令,此命令是windows格式的命令  
                  String pingCommand = "ping " + ipAddress + " -n " + pingTimes    + " -w " + timeOut;  
                  try {   // 執行命令并獲取輸出  
                      System.out.println(pingCommand);   
                      Process p = r.exec(pingCommand);   
                      if (p == null) {    
                          return false;   
                      }
                      in = new BufferedReader(new InputStreamReader(p.getInputStream()));   // 逐行檢查輸出,計算類似出現=23ms TTL=62字樣的次數  
                      int connectedCount = 0;   
                      String line = null;   
                      while ((line = in.readLine()) != null) {    
                          connectedCount += getCheckResult(line);   
                      }   // 如果出現類似=23ms TTL=62這樣的字樣,出現的次數=測試次數則返回真  
                      return connectedCount == pingTimes;  
                  } catch (Exception ex) {   
                      ex.printStackTrace();   // 出現異常則返回假  
                      return false;  
                  } finally {   
                      try {    
                          in.close();   
                      } catch (IOException e) {    
                          e.printStackTrace();   
                      }  
                  }
              }
              //若line含有=18ms TTL=16字樣,說明已經ping通,返回1,否則返回0.
              private static int getCheckResult(String line) {  // System.out.println("控制臺輸出的結果為:"+line);  
                  Pattern pattern = Pattern.compile("(\\d+ms)(\\s+)(TTL=\\d+)",    Pattern.CASE_INSENSITIVE);  
                  Matcher matcher = pattern.matcher(line);  
                  while (matcher.find()) {
                      return 1;
                  }
                  return 0; 
              }
              public static void main(String[] args) throws Exception {
                  String ipAddress = "127.0.0.1";
                  System.out.println(ping(ipAddress));
                  ping02(ipAddress);
                  System.out.println(ping(ipAddress, 5, 5000));
              }
          }

          小結:
          第一種方法:Jdk1.5的InetAddresss,代碼簡單。
          第二種方法:使用java調用cmd命令,這種方式最簡單,可以把ping的過程顯示在本地。
          第三種方法:也是使用java調用控制臺的ping命令,這個比較可靠,還通用,使用起來方便:傳入個ip,設置ping的次數和超時,就可以根據返回值來判斷是否ping通。
          posted @ 2015-03-08 09:48 marchalex 閱讀(22149) | 評論 (3)編輯 收藏
          在之前簡要介紹過深度優先搜索廣度優先搜索這兩個算法。
          同時我們之前也講過Java中隊列的使用。
          基于百度的推薦程序的基礎上,我們可以開展大規模搜索了,也就是說:
              今天,我寫的東西是 DFS/BFS 和 推薦 的 結合。
          我將會把網頁信息的挖取加上搜索從而達到得到更多信息的效果。
          舉個例子,比如我在百度搜索“一句話木馬”,百度會推薦給我一些信息,如“廣外女生木馬”,然后我再繼續搜“廣外女生木馬”,會得到一個“網絡神偷”的推薦詞;這個推薦詞是不包含在搜“一句話木馬”的推薦詞里面的,但是也是我感興趣的,所以我通過廣度優先搜索或者深度優先搜索來進行這種大規模的網絡上的搜索。
          RelateDigger類用于實現該功能。
          其中的bfs方法體現了廣度優先搜索的功能;dfs方法體現了深度優先搜索的功能。
          使用digInBFS方法進行大規模的bfs網頁挖取推薦信息功能。
          使用digInDFS方法進行大規模的dfs網頁挖取推薦信息功能。
          我用max_count限制廣度優先搜索搜索到的關鍵詞的最大數量,用max_depth限制搜索的深度。大家可以根據自己的需求更改這兩個常量。
          用HashMap來記錄得到的關鍵詞。
          代碼如下:
          import java.util.HashMap;
          import java.util.Iterator;
          import java.util.LinkedList;
          import java.util.Queue;


          public class RelateDigger {
              public static HashMap <String,Integer> map;
              
              private static final int max_count = 100;
              private static int count;
              
              private static final int max_depth = 3;
              
              private static void init() {
                  count = 0;
                  map = new HashMap<String, Integer>();
              }
              private static void dfs(String u, int depth) throws Exception {
                  System.out.println("digging in " + u);
                  String[] res = FindRelate.getRelate(u);
                  int n = res.length;
                  for(int i=0;i<n;i++) {
                      String v = res[i];
                      if(map.containsKey(v)) continue;
                      map.put(v, new Integer(1));
                      if(depth >= max_depth) return;
                      dfs(v, depth+1);
                  }
                  return;
              }
              public static void digInDFS(String word) throws Exception {
                  init();
                  map.put(word, new Integer(1));
                  dfs(word, 0);
                  Iterator<String> iter = map.keySet().iterator();
                  while(iter.hasNext()) {
                      String key = iter.next();
                      System.out.print(key);
                      if(iter.hasNext()) System.out.print(",");
                  }
              }
              private static void bfs(String u) throws Exception {
                  Queue<String> queue = new LinkedList<String>();  
                  queue.offer(u);
                  while((u=queue.poll())!=null){
                      System.out.println("digging in " + u);
                      String[] res = FindRelate.getRelate(u);
                      int n = res.length;
                      for(int i=0;i<n;i++) {
                          String v = res[i];
                          if(map.containsKey(v)) continue;
                          map.put(v, new Integer(1));
                          count ++;
                          queue.offer(v);
                          if(count >= max_count) return;
                      }
                  }
              }
              public static void digInBFS(String word) throws Exception {
                  init();
                  map.put(word, new Integer(1));
                  count ++;
                  bfs(word);
                  Iterator<String> iter = map.keySet().iterator();
                  while(iter.hasNext()) {
                      String key = iter.next();
                      System.out.print(key);
                      if(iter.hasNext()) System.out.print(",");
                  }
              }
              
              public static void main(String[] args) throws Exception {
                  digInDFS("一句話木馬");
                  digInBFS("珠穆朗瑪峰");
              }
          }
          其中digInDFS得到的結果為:
          null,中國十大最難懂方言,必應詞典,盜號木馬,震蕩波病毒,充值軟件,盜號,網絡神偷,塔佐蠕蟲,中越黑客大戰,黑客教程,蛀船蟲,中國黑客聯盟,小球病毒,宏病毒,中華吸血鬼,特洛伊木馬,qq木馬,鬼影病毒,后門木馬,動漫日語,中國紅客聯盟,CIH病毒,李俊,有道詞典,黑光病毒,伯樂木馬,百度殺毒,手機透視器,黑客教父,qq盜號木馬,機器狗病毒,米特尼克,qq槍手,冰河木馬,c病毒,火焰病毒,g病毒,免費黑客網,百度翻譯,華夏黑客聯盟,廣外女生木馬,oldboot,cih病毒,特洛伊:木馬屠城,玻璃蛇,網游大盜,學術翻譯,灰鴿子木馬,三角木馬,熊貓燒香,女巫的椅子,江民炸彈,黑客工具,網上學英語,米米病毒,金山詞霸,灰鴿子遠程控制軟件,莫里斯蠕蟲,百度衛士,僵尸世界大戰2,遠程控制軟件,懸玉環,食骨蠕蟲,千斤頂,超級工廠病毒,灰鴿子,靈格斯,磁碟機病毒,騎木馬驢,機器狗,震蕩波,幸運破解器,黑客基地,維羅妮卡病毒,nabau,一句話木馬,蠕蟲病毒,沖擊波病毒,黑客技術教程,大小姐木馬,木馬病毒,大麻病毒,不死木馬,2001中美黑客大戰,下村勉,trojan.generic,金豬報喜,qq尾巴,歡樂時光病毒,geohot,asp木馬,手機骷髏病毒,中國鷹派,世界十大黑客,海詞詞典,黑客,王江民,潘多拉,殺毒軟件,citrus,qq大盜,計算機病毒,g幼體,羅塞塔石碑,黑客技術,卡巴斯基免費版,喪尸,萬能登陸器,高危型人乳頭瘤病毒,鐵蓮花
          digInBFS得到的結果為:
          德令哈外星人遺址,百慕大三角,麥田怪圈,中國三大海峽,太陽墓,中國四大無人區,海底金字塔,中國最美十大名山,中國梯,巴黎性博物館,中國死海,玫瑰湖,天門山,大藍洞,貢嘎山,51區,西藏,普羅旺斯,中華十大名山,山西十大景區,克爾黑洞,暗物質,美國大峽谷空中走廊,魔鬼城,安納布爾納峰,羌塘,哭島,全球被遺棄的31個景點,外星人,白洞,史瓦西黑洞,羅布泊,中國五大淡水湖,恐怖谷理論,道教四大名山,性博物館,托木爾峰,中國四大名塔,幽靈島,乞力馬扎羅山,霍金,四大道教名山,喜馬拉雅山脈,怪坡,黑洞,可可西里,無底洞,毛里求斯,藏王,中國四大古鎮,藏北無人區,巧克力山,玉珠峰,撒哈拉之眼,大西國,愛因斯坦,奧林匹斯山,黃泉大道,天門山玻璃棧道,球狀閃電,帕巴拉神廟,中華侏羅紀公園,鳳凰山ufo事件,神農架,卡瓦格博,中國十大古城,珠峰大本營,亞特蘭蒂斯,昆侖山死亡谷,查亞峰,魔鬼塔,巨人之路,貴州時光隧道,潘洛斯階梯,處女峰,怒江72拐,希勒湖,喬戈里峰,倒懸空寺,魚人島,慕士塔格峰,日本龍三角,地心人,列寧峰,全球十大驚悚地點,不可能圖形,死亡谷,巴比倫通天塔,珠穆朗瑪峰,馬爾代夫太陽島,天下第一橋,藍洞,9.8新疆ufo事件,沈陽怪坡,雁蕩山,中國四大古城,四姑娘山,三山五岳,墨脫水電站,黑林錯覺
          posted @ 2015-03-07 22:20 marchalex 閱讀(223) | 評論 (0)編輯 收藏
          第一種:
          Map map = new HashMap();
          Iterator iter = map.entrySet().iterator();
          while (iter.hasNext()) {
              Map.Entry entry = (Map.Entry) iter.next();
              Object key = entry.getKey();
              Object val = entry.getValue();
          }
          第二種:
          Map map = new HashMap();
          Iterator iter = map.keySet().iterator();
          while (iter.hasNext()) {
              Object key = iter.next();
              Object val = map.get(key);
          }
          其中,第一種方法效率較高。
          posted @ 2015-03-07 21:46 marchalex 閱讀(145) | 評論 (0)編輯 收藏
          不同于深度優先搜索,廣度優先搜索(breadth-first search,簡稱BFS,又稱寬度優先搜索)采取的工具是隊列。
          我們回顧一下深度優先搜索,可以發現:
          深度優先搜索是通過遞歸實現的,其實就相當于在內存中開了一個來實現。
          而廣度優先搜索通過隊列來實現,其解決問題的大體思路如下:
          首先,將代表初始狀態的節點放入隊列queue中;
          然后,循環進行以下操作:
              從隊列里面推出一個元素u,將通過u能夠聯系到的且可以優化的節點v推入隊列中
          即: 深度優先搜索用棧(stack)來實現,整個過程可以想象成一個倒立的樹形:
          1、把根節點壓入棧中。
          2、每次從棧中彈出一個元素,搜索所有在它下一級的元素,把這些元素壓入棧中。并把這個元素記為它下一級元素的前驅。
          3、找到所要找的元素時結束程序。
          4、如果遍歷整個樹還沒有找到,結束程序。
          廣度優先搜索使用隊列(queue)來實現,整個過程也可以看做一個倒立的樹形:
          1、把根節點放到隊列的末尾。
          2、每次從隊列的頭部取出一個元素,查看這個元素所有的下一級元素,把它們放到隊列的末尾。并把這個元素記為它下一級元素的前驅。
          3、找到所要找的元素時結束程序。
          4、如果遍歷整個樹還沒有找到,結束程序。
          廣度優先搜索可以用來解決很多問題,比如,求最短路的SPFA算法就是用了寬度優先搜索的思想。
          posted @ 2015-03-07 21:14 marchalex 閱讀(238) | 評論 (0)編輯 收藏
          深度優先搜索(depth-first search,簡稱dfs)就是遞歸地進行一系列操作,直到找到想要的結果或者搜到頭了(無路可走)。
          我對深度優先搜索的總結就是:
              (1)不見南墻不回頭
              (2)找到以后往回走
          深度優先搜索其實和我們大多數人小時候走迷宮時選擇的策略非常類似。

          深度優先搜索有一個很簡單的例子:求n!。
          int f(int n) {
              if(n == 0 || n == 1) return 1;
              return f(n-1) * n;
          }
          我們以現在ACM競賽中一道簡單的競賽題 -- 素數環 為例,來講解深度優先搜索。點此進入題目描述

          這道題目的意思是,找到所有的素數環輸出。
          我們可以寫下對應的偽代碼:
          function dfs(深度) {
              if(深度 == 1) {
                  第1個點確定為1;
                  第1個點標記訪問過了;
                  dfs(深度+1);
                  撤銷第1個點的標記;
              }
              else {
                  for(i = 1 to n) {
                      if(i加上第(深度-1)個點的值是素數 and i沒有被訪問過) {
                          第(深度)個點確定為i;
                          第i個點標記訪問過了;
                          dfs(深度+1);
                          撤銷第i個點的標記;
                      }
                  }
              }
              if(深度 > n) {
                  if(第(深度-1)個點的值+1是素數) {
                      輸出這串素數環;
                  }
                  return;
              }
              return;
          }
          簡單了解了深度優先搜索,并且差不多看懂了這個偽代碼,我們就可以用代碼實現一下了。下面是完整的Java代碼:
          import java.util.Scanner;


          public class Main {
              
              public static boolean isprime(int n) {
                  if(n ==2 || n == 3 || n == 5 || n == 7 || n == 11 || n == 13 || n == 17 || n == 19 ||
                          n == 23 || n == 29 || n == 31 || n == 37 || n == 41)
                      return true;
                  return false;
              }
              
              private static boolean[] vis = new boolean[22];
              private static int[] ans = new int[22];
              private static Scanner in;
              
              public static void dfs(int dep,int n) {
                  for(int i=1;i<=n;i++) {
                      if(vis[i] == false && isprime(ans[dep-1] + i)) {
                          vis[i] = true;
                          ans[dep] = i;
                          if(dep == n && isprime(1+i)) {
                              System.out.print(ans[1]);
                              for(int i1=2;i1<=n;i1++) System.out.print(" " + ans[i1]);
                              System.out.println("");
                              vis[i] = false;
                              return;
                          } else if(dep == n) {
                              vis[i] = false;
                              return;
                          }
                          dfs(dep+1, n);
                          vis[i] = false;
                      }
                  }
                  return;
              }
              
              public static void main(String[] args) {
                  
                  in = new Scanner(System.in);
                  int cnt = 0;
                  while(in.hasNext()) {
                      int n = in.nextInt();
                      for(int i=1;i<=n;i++) vis[i] = false;
                      cnt ++;
                      System.out.println("Case " + cnt + ":");
                      vis[1] = true;
                      ans[1] = 1;
                      dfs(2, n);
                      System.out.println("");
                  }
              }
              
          }

          遞歸地一種很好玩的現象:德羅斯特效應
          posted @ 2015-03-07 20:47 marchalex 閱讀(195) | 評論 (0)編輯 收藏
          上百度搜東西的時候,右邊總有一些推薦的東西很吸引我們的注意,因為那是百度的推薦系統給我推薦的我們感興趣的東西。
          那這些推薦的內容也在源代碼里面出現了。
          所以采用類似分析網頁源代碼的方法我們能夠把里面的東西全都挖下來。
          比如說我在百度搜索了“一句話木馬”,百度就會跳到一個固定的鏈接:
          https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=%E4%B8%80%E5%8F%A5%E8%AF%9D%E6%9C%A8%E9%A9%AC&rsv_pq=fcb3de5b00004128&rsv_t=6f62cGPSB5k0xYiyhhPSjjDXemE9KEBVk0diG3YR6PnVzpq1vmoq%2FDdFD8E&rsv_enter=1&rsv_n=2&rsv_sug3=1
          好長是不?
          其實我們可以將這個url縮短一下,變成:
          http://www.baidu.com/s?wd=%E4%B8%80%E5%8F%A5%E8%AF%9D%E6%9C%A8%E9%A9%AC
          等同于
          http://www.baidu.com/s?wd=一句話木馬
          網頁的右側出現了三個欄:“相關病毒”,“相關人物”和“其他人還搜”,直覺告訴我第一個是聯系比較緊密的。
          所以我的目的就是變成找出第一個欄(不光是這里)的所有推薦內容。
          分析網頁會發現每個欄目最前面都會有一個標志性的字符串:"<span title="
          而每個欄目里面的每個內容前面也會有一個標志性的字符串:"rsv_re_ename"
          據此我寫了一個分析的FinderRelate類,其中的getRelate(String word)用于獲得關鍵詞word對應的推薦的內容。
          import java.io.BufferedReader;
          import java.io.InputStreamReader;
          import java.net.HttpURLConnection;
          import java.net.URL;
          import java.util.StringTokenizer;


          public class FindRelate {
              
              public static String[] getRelate(String word) throws Exception {
                  String urlString = "http://www.baidu.com/s?wd=" + word;
                  String ans = "";
                  String s_span = "<span title=";
                  int len_span = s_span.length();
                  String s_rsv = "rsv_re_ename";
                  int len_rsv = s_rsv.length();
                  
                  URL url = new URL(urlString);
                  HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
                  BufferedReader reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "utf-8"));
                  String line;
                  boolean ok = false;
                  while ((line = reader.readLine()) != null){
                      int len = line.length();
                       for(int i=0;i+len_span<=len;i++) {
                           if(line.substring(i, i+len_span).equals(s_span)) {
                               if(ok == false) ok = true;
                               else {
                                   StringTokenizer st = new StringTokenizer(ans);
                                   int n = st.countTokens();
                                   String[] res = new String[n];
                                   for(int j=0;j<n;j++) {
                                       res[j] = st.nextToken();
                                   }
                                   return res;
                               }
                           }
                       }
                       if(ok == falsecontinue;
                       for(int i=0;i+len_rsv<=len;i++) {
                           if(line.substring(i, i+len_rsv).equals(s_rsv)) {
                               for(int j=i+len_rsv+3;j<len && line.charAt(j)!='\'';j++) {
                                   ans += line.charAt(j);
                               }
                               ans += " ";
                           }
                       }
                  }
                  String[] null_res = new String[1];
                  null_res[0] = null;
                  return null_res;
              }
              public static void main(String[] args) throws Exception {
                  String[] res = getRelate("一句話木馬");
                  int len = res.length;
                  for(int i=0;i<len;i++)
                      System.out.println(res[i]);
              }
          }
          其輸出結果如下:
          廣外女生木馬
          qq尾巴
          熊貓燒香
          歡樂時光病毒
          灰鴿子
          大小姐木馬
          盜號
          機器狗
          盜號木馬
          冰河木馬
          沖擊波病毒
          莫里斯蠕蟲
          asp木馬
          cih病毒
          火焰病毒
          posted @ 2015-03-07 00:07 marchalex 閱讀(1557) | 評論 (0)編輯 收藏
          之前寫了一個FileHelper類用于實現文件的讀取和寫入。
          這次在原來的基礎上寫了一個WebpageMaker類,其createPage方法用于將特定文件中的內容生成在特定的網頁中。
          其中如果要插入代碼可以將代碼加入中。
          import java.util.StringTokenizer;


          public class WebpageMaker {
              public static String initBegin() {
                  String s = "<!doctype html><html><head><title></title></head><body>\r\n";
                  return s;
              }
              public static String initEnd() {
                  String s = "\r\n</body></html>\r\n";
                  return s;
              }
              public static void createPage(String inputfilename, String outputfilename) throws Exception {
                  String content = FileHelper.readFile(inputfilename);
                  StringTokenizer st = new StringTokenizer(content, "\r\n");
                  String ans = "";
                  ans += initBegin();
                  boolean isCoding = false;
                  while(st.hasMoreElements()) {
                      String s = st.nextToken();
                      int len = s.length();
                      for(int i=0;i<len;i++) {
                          if(i+6 <= len && s.substring(i,i+6).equals("<alex>")) {
                              isCoding = true;
                              ans += "<pre style=\"background-color:aliceblue\">";
                              i += 5;
                              continue;
                          }
                          if(i+7 <= len && s.substring(i,i+7).equals("</alex>")) {
                              isCoding = false;
                              ans += "</pre>";
                              i += 6;
                              continue;
                          }
                          char c = s.charAt(i);
                          if(c == '\"') ans += "&quot;";
                          else if(c == '&') ans += "&amp;";
                          else if(c == '<') ans += "&lt;";
                          else if(c == '>') ans += "&gt;";
                          else if(c == ' ') ans += "&nbsp;";
                          else if(c == '\t') ans += "&nbsp;&nbsp;&nbsp;&nbsp;";
                          else ans += c;
                      }
                      if(false == isCoding)
                          ans += "<br />\r\n";
                      else 
                          ans += "\r\n";
                  }
                  ans += initEnd();
                  FileHelper.writeFile(ans, outputfilename);
              }
              public static void main(String[] args) throws Exception {
                  createPage("D://test.txt", "D://test.html");
              }
          }

          樣例:
          輸入文件:test.txt
          hello world!
          大家好:)
          #include 
          int main() {
              printf("hello world!\n");
              return 0;
          }
          輸出文件:test.html
          <!doctype html><html><head><title></title></head><body>
          hello world!<br />
          大家好:)<br />
          <pre style="background-color:aliceblue">#include <stdio.h>
          int main() {
              printf("hello world!\n");
              return 0;
          }</pre><br />
          </body></html>
          
          效果如下:
          hello world!
          大家好:)
          #include <stdio.h>
          int main() {
              printf("hello world!\n");
              return 0;
          }
          posted @ 2015-03-06 16:36 marchalex 閱讀(365) | 評論 (2)編輯 收藏
          僅列出標題
          共6頁: 上一頁 1 2 3 4 5 6 下一頁 
          主站蜘蛛池模板: 邵阳市| 莒南县| 武陟县| 龙州县| 三明市| 龙川县| 天祝| 库车县| 尼木县| 印江| 贵港市| 罗甸县| 濮阳市| 巨鹿县| 屯昌县| 齐齐哈尔市| 桐乡市| 怀安县| 建瓯市| 梅河口市| 内丘县| 兴化市| 香格里拉县| 抚远县| 元谋县| 博客| 靖州| 锡林浩特市| 潼南县| 嘉义县| 诸城市| 兴山县| 法库县| 虹口区| 龙井市| 建阳市| 开鲁县| 西乌| 丰宁| 广州市| 安阳县|