精华内容
下载资源
问答
  • 巧用Android网络通信技术,在网络上直接传输对象

    万次阅读 多人点赞 2013-05-25 07:57:01
    那么我们来看一下,一般Android应用程序里都是怎么实现网络交互的,这里拿一Boook对象为例,首先在手机端生成一Book对象,里面包含书名、作者、价格等数据。为了要将这些数据发送到服务器端,我们要从Book对象中...

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/8967080


    要做一个优秀的Android应用,使用到网络通信技术是必不可少的,很难想象一款没有网络交互的软件最终能发展得多成功。那么我们来看一下,一般Android应用程序里都是怎么实现网络交互的,这里拿一个Boook对象为例:




    如上图所示,首先在手机端生成一个Book对象,里面包含书名、作者、价格等数据。为了要将这些数据发送到服务器端,我们要从Book对象中把数据取出,然后组装成XML格式的字符串。接着通过网络API,把组装好的XML字符串发送到服务器端。服务器端接到了客户端发来的XML字符串,就要对该XML进行解析。然后把解析出的数据重新组装成Book对象,之后服务器端就可以对该对象进行一系列其它的操作了。


    当然XML格式的数据量比较大,现在很多Android应用为了节省流量,都改用JSON格式来传输数据了。不过不管是使用XML还是JSON,上图中描述的步骤总是少不了的。


    感觉使用这种方式来传输数据,每次封装和解析XML的过程是最繁琐的,那么能不能把这最繁琐的过程绕过去呢?




    如上图所示,如果可以调用网络API,直接把Book对象发送到服务器端,那么整个网络交互过程就会变得非常简单,下面我们就来看看如何实现。


    新建一个Android工程,命名为ClientTest作为客户端工程。这里第一个要确定的就是待传输的对象,我们新建一个Book类,代码如下:

    package com.test;
    
    import java.io.Serializable;
    
    public class Book implements Serializable {
    
    	private String bookName;
    
    	private String author;
    
    	private double price;
    
    	private int pages;
    
    	public String getBookName() {
    		return bookName;
    	}
    
    	public void setBookName(String bookName) {
    		this.bookName = bookName;
    	}
    
    	public String getAuthor() {
    		return author;
    	}
    
    	public void setAuthor(String author) {
    		this.author = author;
    	}
    
    	public double getPrice() {
    		return price;
    	}
    
    	public void setPrice(double price) {
    		this.price = price;
    	}
    
    	public int getPages() {
    		return pages;
    	}
    
    	public void setPages(int pages) {
    		this.pages = pages;
    	}
    
    }
    
    这个类就是一个简单的POJO,但是要注意一点,它实现了Serializable接口,如果想在网络上传输对象,那么该对象就一定要实现Serializable接口。


    接下来打开或新建activity_main.xml作为程序的主布局文件,加入如下代码:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#000"
        tools:context=".MainActivity" >
    
       <Button 
         android:id="@+id/send"  
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:text="发送"
         />
    
    </RelativeLayout>
    这个布局里面就是包含了一个按钮,点击这个按钮就去发出网络请求。


    接下来打开或新建MainActivity作为程序的主Activity,其中加入如下代码:

    public class MainActivity extends Activity implements OnClickListener {
    
    	private Button send;
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		send = (Button) findViewById(R.id.send);
    		send.setOnClickListener(this);
    	}
    
    	@Override
    	public void onClick(View v) {
    		Book book = new Book();
    		book.setBookName("Android高级编程");
    		book.setAuthor("Reto Meier");
    		book.setPages(398);
    		book.setPrice(59.00);
    		URL url = null;
    		ObjectOutputStream oos = null;
    		try {
    			url = new URL("http://192.168.1.103:8080/ServerTest/servlet/TestServlet");
    			HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    			connection.setDoInput(true);
    			connection.setDoOutput(true);
    			connection.setConnectTimeout(10000);
    			connection.setReadTimeout(10000);
    			connection.setRequestMethod("POST");
    			oos = new ObjectOutputStream(connection.getOutputStream());
    			oos.writeObject(book);
    			InputStreamReader read = new InputStreamReader(connection.getInputStream());
    			BufferedReader br = new BufferedReader(read);
    			String line = "";
    			while ((line = br.readLine()) != null) {
    				Log.d("TAG", "line is " + line);
    			}
    			br.close();
    			connection.disconnect();
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    
    		}
    	}
    
    }
    
    我们可以看到,在onClick方法中处理了按扭的点击事件。这里首先new出了一个Book对象作为待传输数据,接着new出了一个URL对象,指明了服务器端的接口地址,然后对HttpURLConnection的一些可选参数进行配置。接着通过调用ObjectOutputStream的writeObject方法,将Book对象发送到服务器端,然后等服务器端返回数据,最后关闭流和连接。


    注意由于我们使用了网络功能,因此需要在AndroidManifest.xml中加入如下权限:

    <uses-permission android:name="android.permission.INTERNET" />
    好了,目前Android端的代码已经开发完成,我们现在开始来编写服务器端代码。


    新建一个名为ServerTest的Web Project,要做的第一件事就在Web Project下建立一个和Android端一样的Book类。这里有个非常重要的点大家一定要注意,服务器端的Book类和Android端的Book类,包名和类名都必须相同,否则会出现类型转换异常。这里由于两个Book类的内容是完全一样的,我就不再重复贴出。


    然后新建一个Java Servlet作为网络访问接口,我们重写它的doPost方法,具体代码如下:

    public class TestServlet extends HttpServlet {
    
    	public void doPost(HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException {
    		ObjectInputStream ois = null;
    		try {
    			ois = new ObjectInputStream(request.getInputStream());
    			Book book = (Book) ois.readObject();
    			System.out.println("书名是: " + book.getBookName());
    			System.out.println("作者是: " + book.getAuthor());
    			System.out.println("价格是: " + book.getPrice());
    			System.out.println("页数是: " + book.getPages());
    			PrintWriter out = response.getWriter();
    			out.print("success");
    			out.flush();
    			out.close();
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			ois.close();
    		}
    	}
    	
    }
    可以看到,我们首先通过调用HttpServletRequest的getInputStream方法获取到输入流,然后将这个输入流组装成ObjectInputStream对象。接下来就很简单了,直接调用ObjectInputStream的readObject方法,将网络上传输过来的Book对象获取到,然后打印出Book中携带的数据,最后向客户端返回success。


    现在我们来运行一下程序,首先将ServerTest这个项目布置到服务器上,并开启服务器待命。接着在手机上打开ClientTest这个应用程序,如下图所示:




    点击发送发出网络请求,可以看到服务器端打印结果如下:




    而Android端打印结果如下:




    由此我们可以看出,网络上进行对象传输已经成功了!不需要通过繁琐的XML封装和解析,我们也成功将Book中的数据完整地从Android端发送到了服务器端。


    好了,今天的讲解到此结束,有疑问的朋友请在下面留言。


    源码下载,请点击这里


    关注我的技术公众号,每天都有优质技术文章推送。关注我的娱乐公众号,工作、学习累了的时候放松一下自己。

    微信扫一扫下方二维码即可关注:

            

    展开全文
  • 要点: *(1)ObjectInputStream和...*(2)使用ObjectInputStream和ObjectOutputStream来包装底层网络字节,TCP服务器和TCP客户端之间就可以传递对象类型的数据。 代码实现 import java.io.*; import java.n
    • 要点:
      *(1)ObjectInputStream和ObjectOutputStream可以从底层输入流中读取 对象类型的数据和将对象类型的数据写入到底层输出流。
      *(2)使用ObjectInputStream和ObjectOutputStream来包装底层网络字节,TCP服务器和TCP客户端之间就可以传递对象类型的数据。
      *(3)传递一个对象,必须将该对象进行序列化。

    • 代码实现

    import java.io.*;
    import java.net.*;
    public class  ObjectServer
    {
        public static void main(String[] args) throws Exception
        {
            ServerSocket ss = new ServerSocket(8001);
            Socket s = ss.accept();
            OutputStream ops = s.getOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(ops);
            //我们只是考虑服务器端向客户端传输一个对象,因此不用的到服务端的输入流了。
            Student stu = new Student(12,"zhangsan",23,"government");
            oos.writeObject(stu);
    
            //注意关闭的对象的顺序:后创建的先关闭
            oos.close();//关闭包装类,会自动关闭包装类中所有包装的底层类。
            s.close();
            ss.close();
        }
    }
    import java.io.*;
    import java.net.*;
    public class ObjectClient 
    {
        public static void main(String[] args) throws Exception
        {
            if(args.length<2)
            {
                System.out.println("Usage:java TcpCLient ServerIP ServerPort");
                return;
            }
    
            Socket s = new Socket(args[0],Integer.parseInt(args[1]));
            //Socket s = new Socket(InetAddress.getByAddress(args[0]),Integer.parseInt(args[1]));
    
            //Socket s = new Socket("202.117.131.7",8001);
    
           ////客户端不需要对服务器端写入数据,所以我们只需要得到客户端的Socket的输入流对象即可
            InputStream ips = s.getInputStream();
            ObjectInputStream ois = new ObjectInputStream(ips);
    
            Student stu = (Student)ois.readObject();
            System.out.println("        id: " + stu.id);
            System.out.println("      name: " + stu.name);
            System.out.println("       age: " + stu.age);
            System.out.println("department: " + stu.department);
    
            //注意关闭的对象的顺序:后创建的先关闭
            ois.close();//关闭包装类,会自动关闭包装类中所有包装的底层类。
            s.close();
        }
    }
    
    import java.io.Serializable;
    public class Student implements Serializable
    {
        int id;
        String name;
        int age;
        String department;
    
        public Student(int id ,String name,int age,String department)
        {
            this.id = id;
            this.name = name;
            this.age = age;
            this.department = department;
        }
    }
    • 运行步骤:
      第一步,在CMD窗口同时编译ObjetcServer.java和ObjectClient.java程序:javac ObjetcServer.java ObjectClient.java
      第二步,在第一步的CMD窗口中输入start,打开一个新的CMD窗口
      第三步,在第一步的CMD窗口中运行服务器程序:java ObjetcServer
      第四步,在第二步新打开的CMD窗口中运行客户端程序:java ObjectClient

    • 运行操作及运行结果:
      第一步,D:\JavaProject\demo19_ObjectTCP>javac ObjectServer.java ObjectClient.java
      第二步,D:\JavaProject\demo19_ObjectTCP>start
      第三步,D:\JavaProject\demo19_ObjectTCP>java ObjectServer
      第四步,D:\JavaProject\demo19_ObjectTCP>java ObjectClient

                    id : 12
                  name : zhangsan
                   age : 23
            department : government
    展开全文
  • 创建智能网络蜘蛛 ——如何使用Java网络对象和HTML对象(翻译) 作者:Mark O. Pendergast原文:http://www.javaworld.com/javaworld/jw-11-2004/jw-1101-spider.html 摘要 你是否想过创建自己的符合特定标准的...

    创建智能网络蜘蛛

           ——如何使用Java网络对象和HTML对象(翻译)

           作者:Mark O. Pendergast

    原文:http://www.javaworld.com/javaworld/jw-11-2004/jw-1101-spider.html

     

    摘要

           你是否想过创建自己的符合特定标准的网站数据库呢?网络蜘蛛,有时也称为网络爬虫,是一些根据网络链接从一个网站到另外一个网站,检查内容和记录位置的程序。商业搜索站点使用网络蜘蛛丰富它们的数据库,研究人员可以使用蜘蛛获得相关的信息。创建自己的蜘蛛搜索的内容、主机和网页特征,比如文字密度和内置的多媒体内容。这篇文章将告诉你如何使用JavaHTML和网络类来创建你自己的功能强大的网络蜘蛛。

     

           这篇文章将介绍如何在标准Java网络对象的基础上创建一个智能的网络蜘蛛。蜘蛛的核心是一个基于关键字/短语标准和网页特征进行深入网络搜索的递归程序。搜索过程在图形上类似于JTree结构。我主要介绍的问题,例如处理相关的URL,防止循环引用和监视内存/堆栈使用。另外,我将介绍再访问和分解远程网页中如何正确是用Java网络对象。

     

    l         蜘蛛示例程序

    示例程序包括用户界面类SpiderControl、网络搜索类Spider,两个用作创建JTree显示结果的类UrlTreeNodeUrlNodeRenderer,和两个帮助验证用户界面中数字输入的类IntegerVerifierVerifierListener。文章末尾的资源中有完整代码和文档的琏接。

    SpiderControl界面由三个属性页组成,一个用来设置搜索参数,另一个显示结果搜索树(JTree),第三个显示错误和状态信息,如图1搜索参数属性页

    1 搜索参数属性页

    搜索参数包括访问网站的最大数量,搜索的最大深度(链接到链接到链接),关键字/短语列表,搜索的顶级主机,起始网站或者门户。一旦用户输入了搜索参数,并按下开始按钮,网络搜索将开始,第二个属性页将显示搜索的进度。

    搜索树2 搜索树

           一个Spider类的实例以独立进程的方式执行网络搜索。独立进程的使用是为了SpiderControl模块可以不断更新搜索树显示和处理停止搜索按钮。当Spider运行时,它不断在第二个属性页中为JTree增加节点(UrlTreeNode)。包含关键字和短语的搜索树节点以蓝色显示(UrlNodeRenderer)

    当搜索完成以后,用户可以查看站点的统计,还可以用外部浏览器(默认是位于Program Files目录的Internet Explorer)查看站点。统计包括关键字出现次数,总字符数,总图片数和总链接数。

    l         Spider

    Spider类负责搜索给出起点(入口)的网络,一系列的关键字和主机,和搜索深度和大小的限制。Spider继承了Thread,所以可以以独立线程运行。这允许SpiderControl模块不断更新搜索树显示和处理停止搜索按钮。

    构造方法接受包含对一个空的JTree和一个空的JtextArea引用的搜索参数。JTree被用作创建一个搜索过程中的分类站点记录。这样为用户提供了可见的反馈,帮助跟踪Spdier循环搜索的位置。JtextArea显示错误和过程信息。

    构造器将参数存放在类变量中,使用UrlNodeRenderer类初始化显示节点的JTree。直到SpiderControl调用run()方法搜索才开始。

    run()方法以独立的线程开始执行。它首先判断入口站点是否是一个Web引用(httpftp或者www开始)或是一个本地文件引用。它接着确认入口站点是否具有正确的符号,重置运行统计,接着调用searchWeb()开始搜索:

         public void run()

         {

           DefaultTreeModel treeModel = (DefaultTreeModel)searchTree.getModel(); // get our model

           DefaultMutableTreeNode root = (DefaultMutableTreeNode)treeModel.getRoot();

           String urllc = startSite.toLowerCase();

           if(!urllc.startsWith("http://") && !urllc.startsWith("ftp://") &&

                !urllc.startsWith("www."))

             {

              startSite = "file:///"+startSite;   // Note you must have 3 slashes !

             }

             else // Http missing ?

              if(urllc.startsWith("www."))

              {

                startSite = "http://"+startSite; // Tack on http:// 

              }

            

            startSite = startSite.replace('//', '/'); // Fix bad slashes

      

           sitesFound = 0;

           sitesSearched = 0;

           updateStats();

           searchWeb(root,startSite); // Search the Web

           messageArea.append("Done!/n/n");

         }

    searchWeb()是一个接受搜索树父节点和搜索Web地址参数的递归方法。searchWeb()首先检查给出的站点是否已被访问和未被执行的搜索深度和站点。SearchWeb()接着允许SpiderControl运行(更新界面和检查停止搜索按钮是否按下)。如果所有正常,searchWeb()继续,否则返回。

    searchWeb()开始读和解析站点以前,它首先检验基于站点创建的URL对象是否具有正确的类型和主机。URL协议被检查来确认它是一个HTML地址或者一个文件地址(不必搜索mailto:和其他协议)。接着检查文件扩展名(如果当前有)来确认它是一个HTML文件(不必解析pdf或者gif文件)。一旦这些工作完成,通过isDomainOk()方法检查根据用户指定的列表检查主机:

    ...URL url = new URL(urlstr); // Create the URL object from a string.

     

       String protocol = url.getProtocol(); // Ask the URL for its protocol

       if(!protocol.equalsIgnoreCase("http") && !protocol.equalsIgnoreCase("file"))

       {

          messageArea.append("    Skipping : "+urlstr+" not a http site/n/n");

          return;

       }

     

       String path = url.getPath();  // Ask the URL for its path

       int lastdot = path.lastIndexOf("."); // Check for file extension

       if(lastdot > 0)

       {

          String extension = path.substring(lastdot);  // Just the file extension

          if(!extension.equalsIgnoreCase(".html") && !extension.equalsIgnoreCase(".htm"))

          return;  // Skip everything but html files

       }

     

       if(!isDomainOk(url))

       {

          messageArea.append("    Skipping : "+urlstr+" not in domain list/n/n");

          return;

       }

     

    这里,searchWeb()公平的确定它是否有值得搜索的URL,接着它为搜索树创建一个新节点,添加到树中,打开一个输入流解析文件。下面的章节涉及很多关于解析HTML文件,处理相关URL和控制递归的细节。

    l         解析HTML文件

    这里有两个为了查找A HREF来解析HTML文件方法——一个麻烦的方法和一个简单的方法。

    如果你选择麻烦的方法,你将使用JavaStreamTokenizer类创建你自己的解析规则。使用这些技术,你必须为StreamTokenizer对象指定单词和空格,接着去掉<>符号来查找标签,属性,在标签之间分割文字。太多的工作要做。

    简单的方法是使用内置的ParserDelegator类,一个HTMLEditorKit.Parser抽象类的子类。这些类在Java文档中没有完善的文档。使用ParserDelegator有三个步骤:首先为你的URL创建一个InputStreamReader对象,接着创建一个ParserCallback对象的实例,最后创建一个ParserDelegator对象的实例并调用它的public方法parse()

       UrlTreeNode newnode = new UrlTreeNode(url); // Create the data node

       InputStream in = url.openStream(); // Ask the URL object to create an input stream

       InputStreamReader isr = new InputStreamReader(in); // Convert the stream to a reader

       DefaultMutableTreeNode treenode = addNode(parentnode, newnode); 

       SpiderParserCallback cb = new SpiderParserCallback(treenode); // Create a callback object

       ParserDelegator pd = new ParserDelegator(); // Create the delegator

       pd.parse(isr,cb,true); // Parse the stream

       isr.close();  // Close the stream

    parse()接受一个InputStreamReader,一个ParseCallback对象实例和一个指定CharSet标签是否忽略的标志。parse()方法接着读和解码HTML文件,每次完成解码一个标签或者HTML元素后调用ParserCallback对象的方法。

    在示例代码中,我实现了ParserCallback作为Spider的一个内部类,这样就允许ParseCallback访问Spider的方法和属性。基于ParserCallback的类可以覆盖下面的方法:

    n         handleStartTag():当遇到起始HTML标签时调用,比如>A <

    n         handleEndTag():当遇到结束HTML标签时调用,比如>/A<

    n         handleSimpleTag():当遇到没有匹配结束标签时调用

    n         handleText():当遇到标签之间的文字时调用

    在示例代码中,我覆盖了handleSimpleTag()以便我的代码可以处理HTMLBASEIMG标签。BASE标签告诉当处理相关的URL引用时使用什么URL。如果没有BASE标签出现,那么当前URL就用来处理相关的引用。HandleSimpleTag()接受三个参数,一个HTML.Tag对象,一个包含所有标签属性的MutableAttributeSet,和在文件中的相应位置。我的代码检查标签来判断它是否是一个BASE对象实例,如果是则HREF属性被提取出来并保存在页面的数据节点中。这个属性以后在处理链接站点的URL地址中被用到。每次遇到IMG标签,页面图片数就被更新。

    我覆盖了handleStartTag以便程序可以处理HTMLATITLE标签。方法检查t参数是否是一个事实上的A标签,如果是则HREF属性将被提取出来。

    fixHref()被用作清理大量的引用(改变反斜线为斜线,添加缺少的结束斜线),链接的URL通过使用基础URL和引用创建URL对象来处理。接着递归调用searchWeb()来处理链接。如果方法遇到TITLE标签,它就清除存储最后遇到文字的变量以便标题的结束标记具有正确的值(有时网页的title标签之间没有标题)

    我覆盖了handleEndTag()以便HTMLTITLE结束标记可以被处理。这个结束标记指出前面的文字(存在lastText)是页面的标题文字。这个文字接着存在页面的数据节点中。因为添加标题信息到数据节点中将改变树中数据节点的显示,nodeChanged()方法必须被调用以便树可以更新。

    我覆盖了handleText()方法以便HTML页面的文字可以根据被搜索的任意关键字或者短语来检查。HandleText()接受一个包含一个子符数组和该字符在文件中位置作为参数。HandleText()首先将字符数组转换成一个String对象,在这个过程中全部转换为大写。接着在搜索列表中的每个关键字/短语根据String对象的indexof()方法来检查。如果indexof()返回一个非负结果,则关键字/短语在页面的文字中显示。如果关键字/短语被显示,匹配被记录在匹配列表的节点中,统计数据被更新:

    public class SpiderParserCallback extends HTMLEditorKit.ParserCallback {

    /**

      * Inner class used to html handle parser callbacks

      */

      public class SpiderParserCallback extends HTMLEditorKit.ParserCallback {

          /** URL node being parsed */

          private UrlTreeNode node;

          /** Tree node */

          private DefaultMutableTreeNode treenode;

          /** Contents of last text element */

          private String lastText = "";

          /**

           * Creates a new instance of SpiderParserCallback

           * @param atreenode search tree node that is being parsed

           */

         public SpiderParserCallback(DefaultMutableTreeNode atreenode) {

                treenode = atreenode;

                node = (UrlTreeNode)treenode.getUserObject();

         }

         /**

          *  Handle HTML tags that don't have a start and end tag

          * @param t HTML tag

          * @param a HTML attributes

          * @param pos Position within file

          */

         public void handleSimpleTag(HTML.Tag t,

                                 MutableAttributeSet a,

                                 int pos)

         {

           if(t.equals(HTML.Tag.IMG))

           {

             node.addImages(1);

             return;

           }

            if(t.equals(HTML.Tag.BASE))

           {

             Object value = a.getAttribute(HTML.Attribute.HREF);

             if(value != null)

              node.setBase(fixHref(value.toString()));

     

           }   

            

         }

         /**

          *  Take care of start tags

          * @param t HTML tag

          * @param a HTML attributes

          * @param pos Position within file

          */

          public void handleStartTag(HTML.Tag t,

                                 MutableAttributeSet a,

                                 int pos)

         {

            if(t.equals(HTML.Tag.TITLE))

           {

             lastText="";

             return;

           }

           if(t.equals(HTML.Tag.A))

           {

             Object value = a.getAttribute(HTML.Attribute.HREF);

             if(value != null)

             {

              node.addLinks(1);

              String href = value.toString();

              href = fixHref(href);

              try{

                URL referencedURL = new URL(node.getBase(),href);

                searchWeb(treenode, referencedURL.getProtocol()+"://"+referencedURL.getHost()+referencedURL.getPath());

              }

              catch (MalformedURLException e)

              {

                messageArea.append("    Bad URL encountered : "+href+"/n/n");  

                return; 

              }

             }

           }

             

         }

         

          /**

          *  Take care of start tags

          * @param t HTML tag

          * @param pos Position within file

          */

          public void handleEndTag(HTML.Tag t,

                                    int pos)

         {

           if(t.equals(HTML.Tag.TITLE) && lastText != null)

           {

             node.setTitle(lastText.trim());

             DefaultTreeModel tm = (DefaultTreeModel)searchTree.getModel();

             tm.nodeChanged(treenode);

            }

             

         }

          /**

           * Take care of text between tags, check against keyword list for matches, if

           * match found, set the node match status to true

           * @param data Text between tags

           * @param pos position of text within Webpage

           */

          public void handleText(char[] data, int pos)

          {

            lastText = new String(data);

            node.addChars(lastText.length());

            String text = lastText.toUpperCase();

            for(int i = 0; i < keywordList.length; i++)

            {

              if(text.indexOf(keywordList[i]) >= 0)

              {

                if(!node.isMatch())

                {

                 sitesFound++;

                 updateStats();

                }

                node.setMatch(keywordList[i]);

                return;

              }

            }

          }

         

      

      }

     

    l         处理和补全URL

    当遇到相关页面的链接,你必须在它们基础URL上创建完整的链接。基础URL可能通过BASE标签在页面中明确的定义,或者暗含在当前页面的链接中。JavaURL对象为你解决这个问题提供了构造器,提供了根据它的链接结构创建相似的。

           URL(URL context, String spec)接受spec参数的链接和context参数的基础链接。如果spec是一个相关链接,构建器将使用context来创建一个完整引用的URL对象。URL它推荐URL遵循严格的(Unix)格式。使用反斜线,在Microsoft Windows中,而不是斜线,将是错误的引用。如果spec或者context指向一个目录(包含index.htmldefault.html),而不是一个HTML文件,它必须有一个结束斜线。fixHref()方法检查这些引用并且修正它们:

              public static String fixHref(String href)

       {

          String newhref = href.replace('//', '/'); // Fix sloppy Web references

          int lastdot = newhref.lastIndexOf('.');

          int lastslash = newhref.lastIndexOf('/');

          if(lastslash > lastdot)

          {

          if(newhref.charAt(newhref.length()-1) != '/')

             newhref = newhref+"/";  // Add missing /

          }

       

          return newhref;    

          

       }

    l         控制递归

    searchWeb()开始是为了搜索用户指定的起始Web地址而被调用的。它接着在遇到HTML链接时调用自身。这形成了深度优先搜索的基础,也带来了两种问题。首先非常危险的内存/堆栈溢出问题将因为太多的递归调用而产生。如果出现环形的引用,这个问题就将发生,也就是说,一个页面链接另外一个链接回来的连接,这是WWW中常见的事情。为了预防这种现象,searchWeb()检查搜索树(通过urlHasBeenVisited()方法)来确定是否引用的页面已经存在。如果已经存在,这个链接将被忽略。如果你选择实现一个没有搜索树的蜘蛛,你仍然必须维护一个以访问站点的列表(Vector或数组中)以便你可以判断是否你正在重复访问站点。

    递归的第二个问题来自深度优先的搜索和WWW的结构。根据选择的入口,深度优先的搜索在初始页面的初始链接在完成处理以前造成大量的递归调用。这就造成了两种不需要的结果:首先内存/堆栈溢出可能发生,第二被搜索过的页面可能很久才被从初始入口众多的结果中删除。为了控制这些,我为蜘蛛添加了最大搜索深度设置。用户可以选择可以达到的深度等级(链接到链接到链接),当遇到每个链接时,当前深度通过调用depthLimitExceeded()方法进行检查。如果达到限制,链接就被忽略。测试仅仅检查JTree中节点的级别。

    示例程序也增加了站点限制,用户来指定,可以在特定数目的URL被检查以后停止搜索,这样确保程序可以最后停止!站点限制通过一个简单的数字计数器sitesSearched来控制,这个数字每次调用searchWeb()后都被更新和检查。

    l         UrlTreeNodeUrlNodeRenderer

    UrlTreeNodeUrlNodeRenderer是用来在SpiderControl用户界面中创建JTree中个性化的树节点的类。UrlTreeNode包含每个搜索过的站点钟的URL信息和统计数据。UrlTreeNode以作为用户对象属性的标准DefaultMutableTreeNode对象形式存储在JTree中。数据包括节点中跟踪关键字出现的能力,节点的URL,节点的基础URL,链接的数量,图片的数量和字符的个数,以及节点是否符合搜索规则。

    UrlTreeNodeRendererDefaultTreeCellRenderer界面的实现。UrlTreeNodeRenderer使节点包含匹配关键字显示为蓝色。UrlTreeNodeRenderer也为JtreeNodes加入了个性化的图标。个性化的显示通过覆盖getTreeCellRendererComponent()方法(如下)实现。这个方法在树中创建了一个Component对象。大部分的Component属性通过子类来进行设置,UrlTreeNodeRenderer改变了文字的颜色(前景色)和图标:

       public Component getTreeCellRendererComponent(

                              JTree tree,

                              Object value,

                              boolean sel,

                              boolean expanded,

                              boolean leaf,

                              int row,

                              boolean hasFocus) {

     

              super.getTreeCellRendererComponent(

                              tree, value, sel,

                              expanded, leaf, row,

                              hasFocus);

             

              UrlTreeNode node = (UrlTreeNode)(((DefaultMutableTreeNode)value).getUserObject());

              if (node.isMatch()) // Set color

                  setForeground(Color.blue);

               else

                  setForeground(Color.black);

            

              if(icon != null)    // Set a custom icon

              {

                  setOpenIcon(icon);

                  setClosedIcon(icon);

                  setLeafIcon(icon);

              }

             

     

              return this;

        }

    l         总结

    这篇文章向你展示了如何创建网络蜘蛛和控制它的用户界面。用户界面使用JTree来跟踪蜘蛛的进展和记录访问过的站点。当然,你也可以使用Vector来记录访问过的站点和使用一个简单的计数器来显示进展。其他增强可以包含通过数据库记录关键字和站点的接口,增加通过多个入口搜索的能力,用大量或者很少的文字内容来显现站点,以及为搜索引擎提供同义搜索的能力。

    这篇文章中展示的Spider类使用递归调用搜索程序,当然,一个新蜘蛛的独立线程可以在遇到每个链接时开始。这样的好处是允许链接远程URL并发执行,提高速度。然而记住那些叫做DefaultMutableTreeNodeJTree对象,不是线程安全的,所以程序员必须自己实现同步。

     

    资源:

    该文章的源代码和Java文档:

    http://www.javaworld.com/javaworld/jw-11-2004/spider/jw-1101-spider.zip

     

    展开全文
  • 网络图片URL转化为Bitmap对象

    千次阅读 2018-07-20 19:57:30
    在平时的开发中我们会经常用到网络图片的加载,有时候需要把网络图片的URL地址转换为Bitmap对象 来供我们使用: 方法如下: 1:首先我们自定义一接口因为牵涉到网络基本上都要使用异步加载,这里先定义一...

    在平时的开发中我们会经常用到网络图片的加载,有时候需要把网络图片的URL地址转换为Bitmap对象来供我们使用:

    方法如下:

    1:首先我们自定义一个接口因为牵涉到网络基本上都要使用异步加载,这里先定义一个接口回调:

    //自定义一个接口
    public interface HttpCallBackListener {
        void onFinish(Bitmap bitmap);
        void onError(Exception e);
    }
    

    2:牵涉到图片问题我们很自然的想到图片的大小问题,如果图片太大可能导致OOM的问题:

        这里再先写一个方法来用来压缩bitmap使之符合我们的要求代码如下:

    public Bitmap createBitmapThumbnail(Bitmap bitmap,boolean needRecycler){
        int width=bitmap.getWidth();
        int height=bitmap.getHeight();
        int newWidth=80;
        int newHeight=80;
        float scaleWidth=((float)newWidth)/width;
        float scaleHeight=((float)newHeight)/height;
        Matrix matrix=new Matrix();
        matrix.postScale(scaleWidth,scaleHeight);
        Bitmap newBitMap=Bitmap.createBitmap(bitmap,0,0,width,height,matrix,true);
        if(needRecycler)bitmap.recycle();
        return newBitMap;
    }

    3:最后也是最下面的最重要的方法了是用来解析网络图片URL地址并转换成bitmap对象

    /**
     * bitmap转换
     * @param
     * @return
     */
    public void getImage(final String path, final HttpCallBackListener listener) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                URL imageUrl = null;
                try {
                    imageUrl = new URL(path);
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                }
                try {
                    HttpURLConnection conn = (HttpURLConnection) imageUrl.openConnection();
                    conn.setDoInput(true);
                    conn.connect();
                    InputStream is = conn.getInputStream();
                    Bitmap bitmap = BitmapFactory.decodeStream(is);
                    Bitmap bitmap1= createBitmapThumbnail(bitmap,false);
                    if (listener != null) {
                        listener.onFinish(bitmap1);
                    }
                    is.close();
                } catch (IOException e) {
                    if (listener != null) {
                        listener.onError(e);
                    }
                    e.printStackTrace();
                }
            }
           
        }).start();
    
    }

    4:通过这样三步就基本上可以实现解决我们的问题了。

    展开全文
  • 神经网络解决对象分类和定位问题

    千次阅读 2019-02-19 19:55:14
    图像分类:即算法遍历图片,判断其中的对象是不是汽车 定位分类问题:即用算法判断图中是否有汽车还要在图中标记出它的位置,用红色方框圈起来。 图像分类,例如输入一张图片到多层卷积神经网络,它会输出一特征...
  • 本节学习JavaScript的对象和方法(函数)~Object 对象提供所有 JScript 对象通用的功能。obj = new Object([value]) 参数 obj 必选项。要赋值为 Object 对象...)如果 value 为一个对象,返回不作改动的该对象。如果
  • 突飞猛进的网络技术似乎在一瞬间就把这概念普及到千家万户,现在云存储已经是大家司空见惯的一个网络服务了。比如大家用的百度云盘、已经成为实质上的业界标准的亚马逊S3、微软的OneDrive、苹果公司的iCloud和谷歌...
  • 1:KSOAP2完成POJO对象序列化网络传输  在Android应用中对象的序列化传输总是一很重要的话题,我们再往程序中提交信息的时候,总是尝试着以对象的形式来封装,然后传递的也是对象。序列化传输是Java的基础知识...
  • 小生最近在使用电脑时,发现了一大问题,进入系统后,打开我的电脑后就出现零个对象,导致电脑里的东西无法看到,我就试着重启电脑,有时候重启计算机一两次这问题就自动消失了,但这次我把电脑重启了六次才把这问题...
  • int size = 0; try { URL url = new URL(destUrl); httpUrl = (HttpURLConnection) url.openConnection(); httpUrl.connect(); File file = FileUtil.inputStreamToFile(httpUrl.getInputStream(),"url.png"); ...
  • 本节讲Dom和Bom模型概念...写了2输出到页面的函数。function println(param){ document.write(param+" "); } function print(param){ document.write(param); }window对象中的方式:方法: confirm : bCo
  • 大多数其他网络类都要用到这类,包括Socket,ServerSocket,URL,DatagramSocket,DatagramPacket等。一般地讲,它包括一主机名和一IP地址。 创建新的InetAddress对象 InetAddress类没有公共构造函数。实际上...
  • 传输对象模式

    千次阅读 2019-09-25 19:58:52
    传输对象是一具有 getter/setter 方法的简单的 POJO 类,它是可序列化的,所以它可以通过网络传输。它没有任何的行为。服务器端的业务类通常从数据库读取数据,然后填充 POJO,并把它发送到客户端或按值传递它。...
  • 对象存储

    千次阅读 2018-09-01 22:21:45
    对象存储到底是什么鬼 对象存储到底是什么鬼 小小河 2016-7-23 &nbsp; 存储圈真会玩,块存储、文件存储、混合存储,今年又火了一个对象存储。银行,公安局,各大单位一言不合就换成对象存...
  • 首先是一out.js文件内容(输出到网页中的自定义输出方法):function println(parma){ document.write(parma+" "); } function print(parma){ document.write(parma); } Date 对象启用基本存储器并
  • java将网络上的url图片转换成File对象

    千次阅读 2021-01-05 10:13:01
    while ((bytesRead = inStream.read(buffer, 0, 8192)) != -1) { os.write(buffer, 0, bytesRead); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (null != os) { os.close(); } if (null ...
  • while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) { os.write(buffer, 0, bytesRead); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (null != outputStream) { ...
  • 4.7 自定义对象 JS除了内置对象之外,还允许我们程序自己定义...构造器,就是一普通的函数,函数中可以定义0到N参数,具体的代码如下: /*对象构造器,就是一普通函数*/function Student(stuName,age,pas...
  • 不管是使用urllib.request.urlopen()方法,还是使用opener.open()方法,都返回同样类型的HTTPResponse对象,用法总结如下: # !/usr/bin/env python # -*- coding:utf-8 -*- from urllib import request from urllib...
  • 课程《Java基础至高级应用》从基础入门开始进行系统教学,全套课程精细讲解,高级课程超过其他机构30%的课程量,经过我们全套课程系统学习的同学,可轻松从事Java高级工程师或系统架构师岗位,课程提供全套代码...
  • 【Java工具】将一个对象转换成Map

    千次阅读 2016-05-17 10:49:13
    利用反射获取对象的属性值
  • 浅谈一下JAVA对象对象引用以及对象赋值

    万次阅读 多人点赞 2013-09-19 00:50:29
    浅谈一下JAVA对象对象引用以及对象赋值   今天有班级同学问起JAVA对象的引用是什么。正好趁着这次机会,自己总结一下JAVA对象对象引用以及对象赋值。自己总结了所看到的网上相关方面的不少帖子,整理汇总形成...
  • 对象序列化:就是将对象保存到磁盘中,或者在网络中传输对象 这种机制就是使用一字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存储的属性等信息 字节序列写到文件后,相当于文件中持久...
  • 因为在保存一个对象或者大型数据类型时,因为平台的不同(比如操作系统不同),需要通过网络传递时,需要适应对方的环境或者网络的协议,要将对象的数据转化成一种标准的字节流序列,从而能在其他平台还原出来和符合...
  • 由于我们在网络编程中,经常以对象作为发送的单元,所以接受端必须对粘包做处理,还原原来的对象。 下图说明了接受端接收到数据的各种情况: 当然,接收到第一种情况是最理想的,也不须处理。本文...
  • DirectoryEntry 对象

    千次阅读 2017-03-03 14:24:28
    DirectoryEntry 对象在 System.DirectoryServices 中,目录中的每个对象都由 DirectoryEntry 对象表示。DirectoryEntry 在内存中创建一对象;在调用 CommitChanges 方法之前,它实际上并没有在目录中创建该对象...
  • 对象关系数据库

    千次阅读 2014-05-30 11:23:53
    使用面向对象方法学可以定义任何一种DBMS数据库,即网络型、层次型、关系型、面向对象型均可,甚至文件系统设计可以遵循面向对象的思路。对象-关系数据库正是把面向对象方法学与关系数据库系统技术相结合的产物。 ...
  • Java深入 | 对象如何创建&Class对象

    千次阅读 2016-04-27 21:07:54
    类作为程序中的一部分,每类都有一Class对象(即,每当编写且编译了一新类,就会产生一Class对象,这个对象被保存在一同名的.class文件中) 简述:  Class 类是在Java语言中定义一特定类的实现。一类...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 749,117
精华内容 299,646
关键字:

网络0个对象