Asp.net MVC 插件式应用框架 - Mobwiz - 博客园

mikel阅读(1127)

来源: Asp.net MVC 插件式应用框架 – Mobwiz – 博客园

这几年来做了很多个网站系统,一直坚持使用ASP.NET mvc建站,每次都从头开始做Layout,CSS,做权限管理等等,有点恼火,将这几年的代码好好整理了一下,准备搭建一个框架。

一、目标

0)面向领域:网站后台管理系统、MIS等结构相对规范的管理类应用;

a)基于ASP.NET MVC 4搭建系统框架

b)集成RBAC基于角色的权限管理机制,能够控制到控件级别

c)集成一些基础服务:数据字典、日志记录等

d)使用AJAX特性(使用JQuery与MVC的Partiview等实现)

e)插件机制:框架搭建完毕之后,新开发的功能模块能够直接以插件的形式安装到系统框架中运行

f)使用EF Codefirst

二、系统设计

A)基于RBAC的权限管理系统

参考了园子里一些权限管理系统,使用了  模块->资源->操作 作为最基础的权限元素,[资源,操作]作为 基本的权限原子,将权限原子赋给“角色”

为了配合RBAC的使用,继承 AuthorizeAttribute 来修饰Action

B)菜单框架

此应用框架主要面向管理系统,所以导航菜单设计为两级,顶部导航为一级菜单,左侧 边为二级菜单,菜单能与权限进行关联,配置权限时可影响到菜单;如图所示,Menu2根据所选择Menu1发生变化;

C)Ajax框架

此应用框架中,Content Area为Ajax更新内容,使用JQuery的 $.get 操作访问 Action,在Action中返回 PartialView,然后更新到 ContentArea中;

全部使用Ajax来载入,带来一个问题,无法使用前进、后退、还有刷新等操作,借鉴网上一些资料,使用了 “jQuery.bbq.js”的插件,通过url的hashchange使系统能够在浏览器中保持状态,能够使用 “前进“,”后退“,”刷新“等操作;通过将真实的请求代码加入到URL”#”后,来载入所需要的内容,JS代码如下:

复制代码
$(window).bind('hashchange', function (e) {
            var hash = window.location.hash || '';
            if (oldHash == '') {
                // 需要选择默认菜单
            }
            if (hash != '' && hash != oldHash) {
                if (hash == "#top") {
                    //TODO, Load the index page!!!!
                    return;
                }

                $('#contentPanel').html('<div class="wp"><img src="@Url.Content("~/Content/loading.gif")" border="0" /> &nbsp;载入中...</div>');
                oldHash = hash;

                $.get(hash.substr(1, hash.length - 1), {}, function (data, status) {
                    if (status == "success") {
                        if (data.substr(0, 7) == '"logon"') {
                            window.location = "/Home/Login";
                        } else {
                            $('#contentPanel').html(data);
                        }
                        //}
                    } else {
                        $('#contentPanel').html('error.. - ' + status);
                    }
                }, "html");
            }
        });
        $(window).trigger('hashchange');
复制代码

 

在这样的框架中,只需要关注Content Area中的部分视图即可,在该Content Area中还可以使用Ajax + JSON的方式实现更多的功能;

表单的处理

由于采用了上面的AJAX机制,不能再使用以往的表单提交方式,在本框架中,使用下面几种方式:

1)使用  $.post(url, $(‘#form’).serialize(), callback, “html”) 的方式,将返回值更新到 Content Area中;

2)使用  $.post(url, {‘field1′,’value1’} , callback, “json”) 的方式,根据结果,再通过JavaScript进行页面跳转;

D)配套的若干Helper

ajaxMenu,ajaxPager等:由于使用了上面的机制来载入部分视图,所有的URL都要以 /Home#/Real/Url?para1=value1 的方式来请求,所以写了一个Helper来完成该功能;分页也需要做同样的处理。

E)IoC Container

本例使用了Unity Block作为IoC容器,无他,因为这个比较熟悉;同时将MVC与Unity Container做了整合;

F)表单验证

由于使用了AJAX框架,unobtrusive扩展的验证大部分失效,所以直接使用 jQuery.validate进行客户端验证

G)插件机制

定义IPlugin接口,其中有Initialize方法,在系统启动时进行初始化,例如初始化Unity Container,MapRoute等等;

插件的使用:直接将插件复制到框架中的插件目录,并将插件所需要使用的Views文件复制到框架中的Views目录中。(暂无更好的解决方案,就这样搞定。考虑复制到插件目录,重写MVC中的视图引擎的代码来实现在插件目录中查找视图)

工作原理:系统启动时,通过反射载入插件中的Dll,并查找IPlugin接口,调用其初始化方法,插件在Unity容器中注册所需要使用的控制器,这样框架中就可以调用到所需要的控制器以及视图;

插件格式:插件也采用ASP.NET mvc 4 Web APP来写,最后只使用编译出的DLL与部分必要的View视图,其他资源均使用框架中的资源;

三、系统实现

1)数据库:采用了EntityFramework(Version 5.0) – CodeFirst完成,使用Enable Migrations;

2)数据访问层:定义仓储模式,IRepository实现基本的增删查改功能,

3)数据服务层:根据需要进行定义;

4)Portal:采用了ASP.NET MVC 4,Razor视图引擎,jQuery,JQuery UI, JQuery.Validate, jquery.bbq, Jquery BlockUI 等;

5)为面向内容管理,集成了CkEditor与CkFinder

——————-

目前系统代码还比较乱,先发个截图

 

 

iOS NSInteger/NSUInteger与int/unsigned int、long/unsigned long之间的区别!

mikel阅读(913)

在iOS开发中经常使用NSInteger和NSUInteger,而在其他的类似于C++的语言中,我们经常使用的是intunsigned int。我们知道iOS也可以使用g++编译器,那么它们之间是否有什么联系呢?

从NSUInteger和NSInteger的定义文件中 NSObjCRuntime.h发现有这样的语句:

#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64

typedeflong NSInteger;

typedefunsigned long NSUInteger;

#else

typedefint NSInteger;

typedefunsigned int NSUInteger;

#endif

这里可以清楚的看出NSInteger和int,NSUInteger和unsigned int之间的区别。mac的OS X系统即为__LP64__,而后面则是指具体的目标硬件设备。所以NSInteger/NSUIteger与对应的intunsigned int不是完全相等的,与对应的longunsigned long也不是完全相等的。而是要看具体的运行环境及其硬件设备架构。

为了更好的了解上面的定义,可以参考下面说的:

You usually want to use NSInteger when you don’t know what kind of processor architecture your code might run on, so you may for some reason want the largest possible int type, which on 32 bit systems is just an int, while on a 64-bit system it’s a long.

当你不知道程序运行哪种处理器架构时,你最好使用NSInteger,因为在有可能int在32位系统中只是int类型,而在64位系统,int可能变是long型。

I’d stick with using NSInteger instead of int/long unless you specifically require them.

除非不得不使用intlong型,坚持使用NSInteger。

从上面的定义可以看出NSInteger/NSUInteger是一种动态定义的类型,在不同的设备,不同的架构,有可能是int类型,有可能是long类型。

With regard to the correct format specifier you should use for each of these types, see the String Programming Guide’s section on Platform Dependencies

为了正确的使用这些类型,可以参考String Programming Guide’s section on Platform Dependencies为了更简单的知道NSInteger和long的大小,我们只需要记住它们的大小总是等于指针的大小,即在32bit系统中是32bit,在64bit系统大小总是64bit。NSInteger and long are always pointer-sized. That means they’re 32-bits on 32-bit systems, and 64 bits on 64-bit systems.)
1.当需要使用int类型的变量的时候,可以像写C的程序一样,用int,也可以用NSInteger,但更推荐使用NSInteger,因为这样就不用考虑设备是32位的还是64位的。

2.NSUInteger是无符号的,即没有负数,NSInteger是有符号的。

3.有人说既然都有了NSInteger等这些基础类型了为什么还要有NSNumber?它们的功能当然是不同的。

 NSInteger是基础类型,但是NSNumber是一个类。如果想要存储一个数值,直接用NSInteger是不行的,比如在一个Array里面这样用:
 NSArray *array = [[NSArray alloc]init];
[array addObject:3];//会编译错误

这样是会引发编译错误的,因为NSArray里面放的需要是一个类,但‘3’不是。这个时候需要用到NSNumber:

 NSArray *array = [[NSArray alloc]init];
[array addObject:[NSNumber numberWithInt:3]];

Cocoa提供了NSNumber类来包装(即以对象形式实现)基本数据类型。
例如以下创建方法:

+ (NSNumber *) numberWithChar: (char) value;
+ (NSNumber *) numberWithInt: (int) value;
+ (NSNumber *) numberWithFloat: (float) value;
+ (NSNumber *) numberWithBool: (BOOL) value;

将基本类型数据封装到NSNumber中后,就可以通过下面的实例方法重新获取它:

– (char) charValue;
– (int) intValue;
– (float) floatValue;
– (BOOL) boolValue;
– (NSString *) stringValue;

苹果所有常用证书,appID,Provisioning Profiles配置说明及制作图文教程(精)

mikel阅读(900)

转自holydancer的CSDN专栏,原文地址:http://blog.csdn.net/holydancer/article/details/9219333

 

概述:

苹果的证书繁锁复杂,制作管理相当麻烦,今天决定重置一个游戏项目中的所有证书,做了这么多次还是感觉很纠结,索性直接记录下来,日后你我他查阅都方便;

首先得描述一下各个证书的定位,作用,这样在制作的时候心中有谱,对整个流程的把握也会准确一些;

1、开发者证书(分为开发和发布两种,类型为ios Development,ios Distribution),这个是最基础的,不论是真机调试,还是上传到appstore都是需要的,是一个基证书,用来证明自己开发者身份的;

2、appID,这是每一个应用的独立标识,在设置项中可以配置该应用的权限,比如是否用到了PassBook,GameCenter,以及更常见的push服务,如果选中了push服务,那么就可以创建生成下面第3条所提到的推送证书,所以,在所有和推送相关的配置中,首先要做的就是先开通支持推送服务的appID;

3、推送证书(分为开发和发布两种,类型分别为APNs Development ios,APNs Distribution ios),该证书在appID配置中创建生成,和开发者证书一样,安装到开发电脑上;

4、Provisioning Profiles,这个东西是很有苹果特色的一个东西,我一般称之为PP文件,该文件将appID,开发者证书,硬件Device绑定到一块儿,在开发者中心配置好后可以添加到Xcode上,也可以直接在Xcode上连接开发者中心生成,真机调试时需要在PP文件中添加真机的udid;是真机调试和必架必备之珍品;

平常我们的制作流程一般都是按以上序列进行,先利用开发者帐号登陆开发者中心,创建开发者证书,appID,在appID中开通推送服务,在开通推送服务的选项下面创建推送证书(服务器端的推送证书见下文),之后在PP文件中绑定所有的证书id,添加调试真机等;

具体操作流程如下:

1、开发者证书的制作,首先登陆到开发者中心,找到证书配置的版块,猛戳进入,点进证书,会显示如下界面,点击右上角的加号

会出现以下界面,该操作重复两次,分别创建开发测试证书和发布证书,开发测试证书用于真机调试,发布证书用于提交到appStore,我们以开发测试证书为例,选择第一个红框中的内容;
然后下一步,会提示创建CSR文件,也就是证书签名请求文件,会有很详细的操作说明,如果英文不太好,可以参考下图;

之后将该CSR文件保存到一处;

备注:CSR文件尽量每个证书都制作一次,将常用名称区分开来,因为该常用名称是证书中的密钥的名字;

之后在开发者中心将该CSR文件提交;

提交上去后就会生成一个cer证书,如图所示,有效期为一年;

利用同样的方法配置一下Distribution发布证书,下载保存,双击安装;在钥题串登陆证书中可以查看,其中专用密钥的名字即为CSR请求文件中的常用名称;

2、以上开发者证书的配置完成了,下面我们来配置appID和推送证书;在左边栏中选择appID,勾选右边的push可选项,为该appID所对应的应用添加推送功能,下面会看到创建证书的按钮,分别为开发证书和发布证书,下面的流程就和上述1中创建证书一样了,都是先建立证书请求文件,然后提交生成就行了,需要注意的是,虽然在左边栏证书栏中也可以直接创建推送证书,但是还是建议在appID中,勾选了push服务后在此处创建,这样会避免因为忘了开通push服务而导致推送不可用的情况发生;

证书创建完成后,下载保存,双击安装即可;

3、最后我们来进行PP文件的制作

该流程进行两次,分别创建开发测试用PP文件和发布PP文件,前者用于真机测试,后者用于提交发布;Ad Hoc格式一般用于企业帐号,此处我们忽略;

选择后提交

会自动检测匹配appID,另外下拉项中还可以选择wildCard格式,该格式为自动生成,使用*通配符,适用于批量的,没有推送,PassCard等服务的应用;我们选择我们刚刚创建的appID,之后下一步选择证书;

继续,这里有一个区别,因为PP文件的开发测试版需要真机调试,所以我们需要绑定真机,这里因为之前我添加过一些设备,所以这里就可以直接全选添加,如果没有的话,需要将真机的udid复制出来在此添加,在发布PP文件中,是没有这一步的;

之后就是输入一个PP文件的名字了,然后生成,下载保存,双击添加到Xcode库中,这样在真机调试或者发布时,就可以分别有不同的PP文件与其对应;

添加到Xcode中的效果如下:

到目前为止,客户端开发和上架所需要的证书文件配置都已经配齐了,天色已晚,明天再配置服务端所用到的推送证书吧,到时候另起一章,将ios诡异的推送流程也捋一捋,本来想写到一篇里的,没想到整了这么长,下班回家开黑去喽!

Android 显示实时时间的方法。

mikel阅读(1305)

一、利用Android自带的模拟时钟和数字时钟。

模拟时钟AnalogClock和数字时钟DigitalClock,用法功能很简单,就是显示一个模拟时钟或是数字时钟

两个时钟都不需要Java代码,只要在layout的xml里插入以下代码即可自动显示时间:

<AnalogClock android:id="@+id/AC"       android:layout_width="wrap_content"        android:layout_height="wrap_content"   />  <DigitalClock      android:id="@+id/DC"      android:layout_width="wrap_content"      android:layout_height="wrap_content"  />

二、利用多线程自己用TextView来显示时间。

先实现Runnable接口,在run方法中获取系统时间,然后用生成Message,在用Handler对象发送消息,在hanler对象中处理消息,即获得系统时间,再显示出来。

实现runnable方法:

public void run()
{
try{
do
{
curTime = dateformat.format(new Date());
sysTime = System.currentTimeMillis();
Thread.sleep(1000);
Message msg = new Message();
msg.what=msg_Key;
mHandler.sendMessage(msg);
}while(tr.interrupted()==false);
}catch(InterruptedException e)
{
e.printStackTrace();
}
}

下面是定义Hanler对象:

                        mHandler = new Handler()
{
public void handleMessage(Message msg)
{
super.handleMessage(msg);
switch(msg.what)
{
case msg_Key:
tv.setText(“当前时间:  “+curTime+ “\n系统时间:”+sysTime+” ms”);
break;
default:
break;
}
}
};
最后,可以用不同的格式来显示时间:

       dateformat = new SimpleDateFormat(“yyyy-mm-dd hh:mm:ss”); //设置显示格式

       curTime = dateformat.format(new Date());   //获得该格式的时间
sysTime = System.currentTimeMillis();    //获得系统时间,ms

java处理日期格式大全Date format SimpleDateFormat - qsfwy - ITeye技术网站

mikel阅读(1151)

Calendar now = Calendar.getInstance();

来源: java处理日期格式大全Date format SimpleDateFormat – qsfwy – ITeye技术网站

Java中日期格式转换

/**
   * 字符串转换为java.util.Date<br>
   * 支持格式为 yyyy.MM.dd G 'at' hh:mm:ss z 如 '2002-1-1 AD at 22:10:59 PSD'<br>
   * yy/MM/dd HH:mm:ss 如 '2002/1/1 17:55:00'<br>
   * yy/MM/dd HH:mm:ss pm 如 '2002/1/1 17:55:00 pm'<br>
   * yy-MM-dd HH:mm:ss 如 '2002-1-1 17:55:00' <br>
   * yy-MM-dd HH:mm:ss am 如 '2002-1-1 17:55:00 am' <br>
   * @param time String 字符串<br>
   * @return Date 日期<br>
   */
public static Date stringToDate(String time){
    SimpleDateFormat formatter;
    int tempPos=time.indexOf("AD") ;
    time=time.trim() ;
    formatter = new SimpleDateFormat ("yyyy.MM.dd G 'at' hh:mm:ss z");
    if(tempPos>-1){
      time=time.substring(0,tempPos)+
           "公元"+time.substring(tempPos+"AD".length());//china
      formatter = new SimpleDateFormat ("yyyy.MM.dd G 'at' hh:mm:ss z");
    }
    tempPos=time.indexOf("-");
    if(tempPos>-1&&(time.indexOf(" ")<0)){
      formatter = new SimpleDateFormat ("yyyyMMddHHmmssZ");
    }
    else if((time.indexOf("/")>-1) &&(time.indexOf(" ")>-1)){
      formatter = new SimpleDateFormat ("yyyy/MM/dd HH:mm:ss");
    }
    else if((time.indexOf("-")>-1) &&(time.indexOf(" ")>-1)){
      formatter = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");
    }
    else if((time.indexOf("/")>-1) &&(time.indexOf("am")>-1) ||(time.indexOf("pm")>-1)){
      formatter = new SimpleDateFormat ("yyyy-MM-dd KK:mm:ss a");
    }
    else if((time.indexOf("-")>-1) &&(time.indexOf("am")>-1) ||(time.indexOf("pm")>-1)){
      formatter = new SimpleDateFormat ("yyyy-MM-dd KK:mm:ss a");
    }
    ParsePosition pos = new ParsePosition(0);
    java.util.Date ctime = formatter.parse(time, pos);

    return ctime;
}

/**
   * 将java.util.Date 格式转换为字符串格式'yyyy-MM-dd HH:mm:ss'(24小时制)<br>
   * 如Sat May 11 17:24:21 CST 2002 to '2002-05-11 17:24:21'<br>
   * @param time Date 日期<br>
   * @return String   字符串<br>
   */
  

public static String dateToString(Date time){
    SimpleDateFormat formatter;
    formatter = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");
    String ctime = formatter.format(time);

    return ctime;
}

/**
   * 将java.util.Date 格式转换为字符串格式'yyyy-MM-dd HH:mm:ss a'(12小时制)<br>
   * 如Sat May 11 17:23:22 CST 2002 to '2002-05-11 05:23:22 下午'<br>
   * @param time Date 日期<br>
   * @param x int 任意整数如:1<br>
   * @return String 字符串<br>
   */
public static String dateToString(Date time,int x){
    SimpleDateFormat formatter;
    formatter = new SimpleDateFormat ("yyyy-MM-dd KK:mm:ss a");
    String ctime = formatter.format(time);

    return ctime;
}

/**
   *取系统当前时间:返回只值为如下形式
   *2002-10-30 20:24:39
   * @return String
   */
public static String Now(){
    return dateToString(new Date());
}

/**
   *取系统当前时间:返回只值为如下形式
   *2002-10-30 08:28:56 下午
   *@param hour 为任意整数
   *@return String
   */
public static String Now(int hour){
    return dateToString(new Date(),hour);
}

/**
   *取系统当前时间:返回值为如下形式
   *2002-10-30
   *@return String
   */
public static String getYYYY_MM_DD(){
    return dateToString(new Date()).substring(0,10);

}

/**
   *取系统给定时间:返回值为如下形式
   *2002-10-30
   *@return String
   */
   public static String getYYYY_MM_DD(String date){
    return date.substring(0,10);

}

public static String getHour(){
    SimpleDateFormat formatter;
    formatter = new SimpleDateFormat ("H");
    String ctime = formatter.format(new Date());
    return ctime;
    }

public static String getDay(){
      SimpleDateFormat formatter;
    formatter = new SimpleDateFormat ("d");
    String ctime = formatter.format(new Date());
    return ctime;
    }

public static String getMonth(){
    SimpleDateFormat formatter;
    formatter = new SimpleDateFormat ("M");
    String ctime = formatter.format(new Date());
    return ctime;
    }

public static String getYear(){
    SimpleDateFormat formatter;
    formatter = new SimpleDateFormat ("yyyy");
    String ctime = formatter.format(new Date());
    return ctime;
    }
      
public static String getWeek(){
    SimpleDateFormat formatter;
    formatter = new SimpleDateFormat ("E");
    String ctime = formatter.format(new Date());
    return ctime;
    }

在jsp页面中的日期格式和sqlserver中的日期格式不一样,怎样统一?

在页面上显示输出时,用下面的函数处理一下

public class DateUtil(){
    public static String fmtShortEnu(Date myDate) {
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
    String strDate = formatter.format(myDate);
    return strDate;
}
}

new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
new java.text.SimpleDateFormat("yyyy-MM-dd")
建议还是把sqlserver的字段类型改成varchar的吧,用字符串处理可以完全按照自己的意愿处理,没有特殊的需求,不要使用date型

字串日期格式转换 
用的API是SimpleDateFormat,它是属於java.text.SimpleDateFormat,所以请记得import进来!

用法: 
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
这一行最重要,它确立了转换的格式,yyyy是完整的西元年,MM是月份,dd是日期, 至於HH:mm:ss就不需要我再解释了吧! 
ps:为什麽有的格式大写,有的格式小写,那是怕避免混淆,例如MM是月份,mm是分;HH是24小时制,而hh是12小时制

1.字串转日期: 
 2002-10-8 15:30:22要把它转成日期,可以用 
 Date date=sdf.parse("2002-10-8 15:30:22"); 
2.日期转字串 
 假如把今天的日期转成字串可用 
 String datestr=sdf.format(new Date()); 
 这个字串的内容便类似2002-10-08 14:55:38

透过这个API我们便可以随心所欲的将日期转成我们想要的字串格式,例如希望将日期输出成2002年10月08日, 
我们可以这麽写: 
SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日"); 
String datestr=sdf.format(new Date()); 
datestr便会依照我们设定的格式输出

//对日期格式的转换成("yyyy-MM-dd")格式的方法
public java.sql.Date Convert(String str)
{
    java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd");
    try
    {
      java.util.Date d = sdf.parse(str);
      java.sql.Date d1 = new java.sql.Date(d.getTime());
      return d1;
    }
    catch(Exception ex)
    {
      ex.printStackTrace();
      return null;
    }
}
应用如下:
ctmt.setDate(7,this.Convert(info.getManBirth())); // @DATETIME

常用日期问题集锦

1、获取服务器端当前日期:
<%@ page import="java.util.Date"%>
<%
Date myDate = new Date();
%>

2、获取当前年、月、日:
<%@ page import="java.util.Date"%>

<%
Date myDate = new Date();
int thisYear = myDate.getYear() + 1900;//thisYear = 2003
int thisMonth = myDate.getMonth() + 1;//thisMonth = 5
int thisDate = myDate.getDate();//thisDate = 30
%>

3、按本地时区输出当前日期
<%@ page import="java.util.Date"%>
<%
Date myDate = new Date();
out.println(myDate.toLocaleString());
%>
输出结果为:
2003-5-30

4、获取数据库中字段名为”publish_time“、类型为Datetime的值
<%@ page import="java.util.Date"%>
<%
...连接数据库...
ResultSet rs = ...
Date sDate = rs.getDate("publish_time");
%>


5、按照指定格式打印日期

<%@ page import="java.util.Date"%>
<%@ page import="java.text.DateFormat"%>
<%
Date dNow = new Date();

SimpleDateFormat formatter = new SimpleDateFormat("E yyyy.MM.dd 'at' hh:mm:ss a zzz");
out.println("It is " + formatter.format(dNow));
%>

输出的结果为:
It is 星期五 2003.05.30 at 11:30:46 上午 CST 
(更为详尽的格式符号请参看SimpleDateFormat类)

6、将字符串转换为日期
<%@ page import="java.util.Date"%>
<%@ page import="java.text.DateFormat"%>
<%
String input = "1222-11-11";
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date t = null;
try{
t = formatter.parse(input);
out.println(t);
}catch(ParseException e){
out.println("unparseable using " + formatter);
}
%>
输出结果为:
Fri Nov 11 00:00:00 CST 1222

7、计算日期之间的间隔
<%@ page import="java.util.Date"%>
<%@ page import="java.text.DateFormat"%>
<%
String input = "2003-05-01";
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date d1 = null;
try{
d1 = formatter.parse(input);
}catch(ParseException e){
out.println("unparseable using " + formatter);
}

Date d2 = new Date();

long diff = d2.getTime() - d1.getTime();
out.println("Difference is " + (diff/(1000*60*60*24)) + " days.");
%>
输出结果为:
Difference is 29 days.

8、日期的加减运算
方法:用Calendar类的add()方法
<%@ page import="java.util.*"%>
<%@ page import="java.text.*"%>
<%
Calendar now = Calendar.getInstance();
SimpleDateFormat formatter = new SimpleDateFormat("E yyyy.MM.dd 'at' hh:mm:ss a zzz");
out.println("It is now " + formatter.format(now.getTime()));
now.add(Calendar.DAY_OF_YEAR,-(365*2));
out.println("<br>");
out.println("Two years ago was " + formatter.format(now.getTime()));
%>
输出结果为:
It is now 星期五 2003.05.30 at 01:45:32 下午 CST 
Two years ago was 星期三 2001.05.30 at 01:45:32 下午 CST

9、比较日期
方法:用equals()、before()、after()方法
<%@ page import="java.util.*"%>
<%@ page import="java.text.*"%>
<%
DateFormat df = new SimpleDateFormat("yyy-MM-dd");
Date d1 = df.parse("2000-01-01");
Date d2 = df.parse("1999-12-31");

String relation = null;
if(d1.equals(d2))
relation = "the same date as";
else if(d1.before(d2))
relation = "before";
else
relation = "after";
out.println(d1 +" is " + relation + ' ' + d2);
%>
输出结果为:
Sat Jan 01 00:00:00 CST 2000 is after Fri Dec 31 00:00:00 CST 1999

10、记录一件事所花费的时间
方法:调用两次System.getTimeMillis()方法,求差值
<%@ page import="java.text.*"%>
<%
long t0,t1;
t0 = System.currentTimeMillis();
out.println("Cyc starts at " + t0);
int k = 0;
for(int i =0;i<100000;i++){
k += i;
}
t1 = System.currentTimeMillis();
out.println("<br>");
out.println("Cyc ends at " + t1);
out.println("<br>");
out.println("This run took " + (t1-t0) + "ms.");
%>

输出结果为:
Cyc starts at 1054275312432 
Cyc ends at 1054275312442 
This run took 10ms.

其它:如何格式化小数

<%@ page import="java.text.*"%>
<%
DecimalFormat df = new DecimalFormat(",###.00");
double aNumber = 33665448856.6568975;
String result = df.format(aNumber);
out.println(result);
%>

输出结果为:
33,665,448,856.66

======================

日期比较:

在JAVA中日期的计算与比较可以使用Date和DateFormat来解决,下面是一段示例代码:

import java.text.*;
import java.util.*;

public class Test{

 public static void main(String[] args){
  try{
   Date date=new Date();
   DateFormat df=DateFormat.getDateTimeInstance();
   String now=df.format(date); 
   System.out.println("现在时间:"+now);

   System.out.println("现在时间是否在16:00之前:"+date.before(df.parse("2004-12-24 16:00:00"))); 
  }
  catch(ParseException e){System.out.print(e.getMessage());
  }
 }
}

忙来忙去没有目标

mikel阅读(919)

日志一天不写,就很难开头了。

不知不觉的天天写了这么长时间,结果日志总是要写的,因为每天都忙来忙去,却缺少了目标,世界总是那么大,想去看看的勇气都需要时间。

日志不写不用发布就没了那份坚持。不应该是坚持,应该是享受,其实很想享受这个写日志的过程。记录了自己从无到有的过程,总得记录下来,不说给谁看,权当是给自己一个交代了。

 

FileSystemWatch 对文件的监测 修改 创建 删除 并写入日志 - RunningMan1229 - 博客园

mikel阅读(1240)

来源: FileSystemWatch 对文件的监测 修改 创建 删除 并写入日志 – RunningMan1229 – 博客园

我做的这个主要是用来对文件的监测 修改 创建 删除 并写入日志

此外我做的WinForm程序

首先导入命名空间

1 using System.IO;

申明全局变量

1 private FileSystemWatcher watch = new FileSystemWatcher();
2 private FileStream fs = null;

先写一个写日志的方法,我这里写的路径都是固定的,你们可以给这个路径配置在App.config中,用户可以选择路径,选择完以后

修改config文件,下次用的时候可以默认选择上次的路径,这里我就不做了

复制代码
1 public void write(string message)
2 {
3 string path = “C:\\Log\\”;
4 if (!Directory.Exists(path))
5 {
6 Directory.CreateDirectory(path);
7 }
8 string fileName = path + “Log.txt”;
9
10 if (!File.Exists(fileName))
11 {
12 FileStream file = new FileStream(fileName, FileMode.Create);
13 file.Dispose();
14 }
15 fs = new FileStream(fileName, FileMode.Append, FileAccess.Write);
16 StreamWriter sw = new StreamWriter(fs, Encoding.UTF8);
17 sw.WriteLine(message);
18 sw.WriteLine(“———————–“);
19 sw.Dispose();
20 fs.Dispose();
21 }
复制代码

写监测的方法,我这里只是记录了一部分信息

复制代码
1 public void ReNameWatch(object sender, FileSystemEventArgs e)
2 {
3 write(DateTime.Now.ToString(“yyyy-MM-dd hh:mm:ss”) + ” ReName File : ” + e.Name.ToString());
4 }
5
6 public void DeleteWatch(object sender, FileSystemEventArgs e)
7 {
8 write(DateTime.Now.ToString(“yyyy-MM-dd hh:mm:ss”) + ” Delete File : ” + e.Name.ToString());
9 }
10
11 public void CreateWatch(object sender, FileSystemEventArgs e)
12 {
13 write(DateTime.Now.ToString(“yyyy-MM-dd hh:mm:ss”) + ” Create File : ” + e.Name.ToString());
14 }
15
16 public void ChangeWatch(object sender, FileSystemEventArgs e)
17 {
18 write(DateTime.Now.ToString(“yyyy-MM-dd hh:mm:ss”) + ” Change File : ” + e.Name.ToString());
19 }
复制代码

写按钮点击事件

复制代码
1 public void Watch(object sender, EventArgs e)
2 {
3 if (this.button1.Text == “Start”)
4 {
5 string path = “C:\\”;
6 watch.Path = path;
7 watch.Filter = “*.txt”;
8 watch.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.Attributes | NotifyFilters.CreationTime | NotifyFilters.DirectoryName | NotifyFilters.LastAccess | NotifyFilters.Security;
9
10 watch.Renamed += new RenamedEventHandler(ReNameWatch);
11 watch.Deleted += new FileSystemEventHandler(DeleteWatch);
12 watch.Created += new FileSystemEventHandler(CreateWatch);
13 watch.Changed += new FileSystemEventHandler(ChangeWatch);
14
15 watch.EnableRaisingEvents = true;
16 this.button1.Text = “Stop”;
17 }
18 else if (this.button1.Text == “Stop”)
19 {
20 watch.EnableRaisingEvents = false;
21 this.button1.Text = “Start”;
22 }
23 }
复制代码

写加载事件

1 public Two()
2 {
3 InitializeComponent();
4 this.KeyDown += new KeyEventHandler(Two_KeyDown);
5 this.button1.Click += new EventHandler(Watch);
6 }

生成日志文件Log.txt截图

Winform开发——本地磁盘目录树浏览 - Erebus_NET - 博客园

mikel阅读(1267)

来源: Winform开发——本地磁盘目录树浏览 – Erebus_NET – 博客园

这学期的项目做了一堆,几乎都是用Winform(C#)写的,一个大的项目涉及到的Winform控件非常多,基本的控件几乎都要使用一遍,有用VS自带的,有用第三方的,有用自己写的。这篇说一下常用的本地磁盘目录树以及当前文件夹内容浏览“套件”的开发。

本地磁盘内容浏览“套件”涉及到两个基本的控件:TreeView和ListView,其中TreeView用来显示磁盘目录的层次关系,节点为磁盘的某个文件夹,用户可以单击节点展开文件夹浏览其子文件夹的层次关系。ListView的视图类似Windows自带的资源管理器,可以给出当前浏览目录下的文件和文件和问文件夹图标,双击后可以进入下一层目录。

第一步:搞定ListView中每个显示项目的图标

系统中的文件夹和不同扩展名的文件在资源管理器中显示的图标也不同,如果在使用ListView显示当前文件夹下所有项目的图标时都自定义添加,这显然是不现实的。那么我们有没有一种办法可以让系统根据某个文件项目的扩展名自动从系统图标库中选取相应的图标呢?免去我们找各种图标图片的麻烦。答案是肯定的,只是我们需要调用一些Win32的API。

首先申明如下:

#region 图标

public static uint SHGFI_ICON = 0x100;

public static uint SHGFI_DISPLAYNAME = 0x150;

public static uint SHGFI_TYPENAME = 0x400;

public static uint SHGFI_ATTRIBUTES = 0x800;

public static uint SHGFI_ICONLOCATION = 0x1000;

public static uint SHGFI_EXETYPE = 0x1500;

public static uint SHGFI_SYSICONINDEX = 0x4000;

public static uint SHGFI_LINKOVERLAY = 0x8000;

public static uint SHGFI_SELECTED = 0x10000;

public static uint SHGFI_LARGEICON = 0x0;

public static uint SHGFI_SMALLICON = 0x1;

public static uint SHGFI_OPENICON = 0x2;

public static uint SHGFI_SHELLICONSIZE = 0x4;

public static uint SHGFI_PIDL = 0x8;

public static uint SHGFI_USEFILEATTRIBUTES = 0x10;

 

public static uint FILE_ATTRIBUTE_NORMAL = 0x80;

public static uint LVM_FIRST = 0x1000;

public static uint LVM_SETIMAGELIST = LVM_FIRST + 3;

public static uint LVSIL_NORMAL = 0;

public static uint LVSIL_SMALL = 1;

 

[DllImport(“Shell32.dll”)]

public static extern IntPtr SHGetFileInfo(string pszPath,

   uint dwFileAttributes, ref SHFILEINFO psfi,

   int cbfileInfo, uint uFlags);

 

public struct SHFILEINFO

{

   public IntPtr hIcon;

   public int iIcon;

   public int dwAttributes;

   public string szDisplayName;

   public string szTypeName;

}

 

[DllImport(“User32.DLL”)]

public static extern int SendMessage(IntPtr hWnd,

   uint Msg, IntPtr wParam, IntPtr lParam);

 

public void ListViewSysImages(ListView AListView)

{

   SHFILEINFO vFileInfo = new SHFILEINFO();

   IntPtr vImageList = SHGetFileInfo(“”, 0, ref vFileInfo,

      Marshal.SizeOf(vFileInfo), SHGFI_SHELLICONSIZE |

      SHGFI_SYSICONINDEX | SHGFI_LARGEICON);

 

   SendMessage(AListView.Handle, LVM_SETIMAGELIST, (IntPtr)LVSIL_NORMAL, vImageList);

   vImageList = SHGetFileInfo(“”, 0, ref vFileInfo,

      Marshal.SizeOf(vFileInfo), SHGFI_SHELLICONSIZE |

      SHGFI_SYSICONINDEX | SHGFI_SMALLICON);

   SendMessage(AListView.Handle, LVM_SETIMAGELIST, (IntPtr)LVSIL_SMALL, vImageList);

 

}

public int FileIconIndex(string AFileName)

{

   SHFILEINFO vFileInfo = new SHFILEINFO();

   SHGetFileInfo(AFileName, 0, ref vFileInfo,

      Marshal.SizeOf(vFileInfo), SHGFI_SYSICONINDEX);

   return vFileInfo.iIcon;

}

#endregion

假设现在我们有ListView控件实例testListView,在使用这个控件之前我们对其进行初始化处理:

ListViewSysImages(testListView);

当我们需要向testListView中添加项目时,使用如下语句:

ListViewItem lvi = new ListViewItem(FileName.Substring(FileName.LastIndexOf(“\\”) + 1));

lvi.ImageIndex = FileIconIndex(FileName);

第二步:树形结构添加节点

使用TreeView之前我们需要找到四个基本图标:选定状态的文件夹、未选定状态的文件夹、磁盘图标、CD驱动器图标。将这四个图标添加到ImageList控件中调整好顺序。

#region 树形结构

//树形结构初始化

private void InitialTreeView(TreeNode rootNode)

{

   //将驱动器字符串数组设为空

   string[] drivers = null;

   //检索此计算机上逻辑驱动器的名称

   drivers = Directory.GetLogicalDrives();

   int i = 0;

   //初始化每一个逻辑驱动器

   while (i < drivers.GetLength(0))

   {

      TreeNode newNode = new TreeNode(drivers[i].ToString().Substring(0, 2));

      newNode.Tag = drivers[i];

      //获得驱动器类型,设置图标

      DriveInfo di = new DriveInfo(drivers[i]);

      if (di.DriveType == DriveType.CDRom)

      {

        newNode.ImageIndex = 2;

        newNode.SelectedImageIndex = 2;

      }

      else

      {

        newNode.ImageIndex = 1;

        newNode.SelectedImageIndex = 1;

      }

      rootNode.Nodes.Add(newNode);

      string path = drivers[i];

      string[] dirs = null;

      try

      {

        //获得指定驱动器中第一级目录的名称

        dirs = Directory.GetDirectories(path);

      }

      catch (Exception error)

      {

        dirs = null;

        //错误处理为空,即忽略

      }

      if (dirs != null)

      {

        //为每一个代表驱动器的根节点添加子节点

        for (int j = 0; j < dirs.Length; j++)

        {

           if ((File.GetAttributes(dirs[j]) & FileAttributes.Hidden) == FileAttributes.Hidden && showHiden.Value == false)

           {

              continue;

           }

           //获得节点去掉路径的目录名

           TreeNode node = new TreeNode(dirs[j].ToString().Substring(dirs[j].ToString().LastIndexOf(“\\”) + 1));

           node.Tag = dirs[j];

           //设置不选定状态下的图标

           node.ImageIndex = 3;

           //设置打开状态下的图标

           node.SelectedImageIndex = 4;

           //添加节点

           rootNode.Nodes[i].Nodes.Add(node);

        }

      }

      //继续下一循环

      i++;

   }

}

//树形结构显示

private void TreeViewShow(TreeNode NodeDir)

{

   try

   {

      string[] dirs = null;

      int i = 0;

      while (i < NodeDir.Nodes.Count)

      {

        //添加子节点

        try

        {

           dirs = Directory.GetDirectories((string)NodeDir.Nodes[i].Tag);

        }

        catch

        {

           dirs = null;

        }

 

        if (dirs != null)

        {

           //删除以前节点

           NodeDir.Nodes[i].Nodes.Clear();

           //为驱动器根节点添加子节点

           for (int j = 0; j < dirs.Length; j++)

           {

              //获得节点去掉路径的目录名

              TreeNode node = new TreeNode(dirs[j].ToString().Substring(dirs[j].ToString().LastIndexOf(“\\”) + 1));

              node.Tag = dirs[j];

              //设置不选定状态下的图标

              node.ImageIndex = 3;

              //设置打开状态图标

              node.SelectedImageIndex = 4;

              //添加节点

              NodeDir.Nodes[i].Nodes.Add(node);

           }

        }

        i++;

      }

   }

 

   catch (Exception e)

   {

      MessageBox.Show(e.Message);

   }

}

//树形结构节点点击事件

private void treeView_AfterSelect(object sender, TreeViewEventArgs e)

{

   currentPath = (string)e.Node.Tag;

   if (currentPath != null && !currentPath.EndsWith(“\\”))

   {

      currentPath += “\\”;

   }

   urlBox.Text = currentPath;

   ListViewShow(e.Node);

}

//树形结构节点展开事件

private void treeView_AfterExpand(object sender, TreeViewEventArgs e)

{

   if (e.Node.Parent != null)

   {

      TreeViewShow(e.Node);

   }

}

#endregion

第三步:显示当前路径下的所有文件项目

#region 文件浏览

//初始化ListView控件,把TrreView控件中的数据添加进来

private void ListViewShow(TreeNode NodeDir)

{

   int itemNum = 0;//统计项目总数

   listView1.Clear();

   listView1.Columns.Add(“名称”, 150);

   listView1.Columns.Add(“修改日期”, 150);

   listView1.Columns.Add(“大小”, 100, HorizontalAlignment.Right);

   try

   {

      if (NodeDir.Parent == null)// 如果当前TreeView的父结点为空,就把我的电脑下的分区名称添加进来

      {

        foreach (string DrvName in Directory.GetLogicalDrives())//获得硬盘分区名

        {

           FileInfo fileInfo = new FileInfo(DrvName.Substring(0, 2));

           ListViewItem ItemList = new ListViewItem(DrvName.Substring(0, 2));

           ItemList.SubItems.Add(fileInfo.LastWriteTime.ToString());

           ItemList.ImageIndex = FileIconIndex(DrvName);

           listView1.Items.Add(ItemList);//添加进来

           itemNum++;

        }

      }

 

      else//如果当前父节点不为空,把点击的结点,做为一个目录文件的总结点

      {

        foreach (string DirName in Directory.GetDirectories((string)NodeDir.Tag))//遍历当前分区或文件夹下所有目录

        {

           if ((File.GetAttributes(DirName) & FileAttributes.Hidden) == FileAttributes.Hidden && showHiden.Value == false)

           {

              continue;

           }

           FileInfo fileInfo = new FileInfo(DirName);

           ListViewItem ItemList = new ListViewItem(DirName.Substring(DirName.LastIndexOf(“\\”) + 1));

           ItemList.SubItems.Add(fileInfo.LastWriteTime.ToString());

           ItemList.ImageIndex = FileIconIndex(DirName);

           ItemList.Tag = DirName;

           listView1.Items.Add(ItemList);

           itemNum++;

        }

 

        foreach (string FileName in Directory.GetFiles((string)NodeDir.Tag))//遍历当前分区或文件夹所有目录的文件

        {

           if ((File.GetAttributes(FileName) & FileAttributes.Hidden) == FileAttributes.Hidden && showHiden.Value == false)

           {

              continue;

           }

           FileInfo fileInfo = new FileInfo(FileName);

           ListViewItem ItemList = new ListViewItem(FileName.Substring(FileName.LastIndexOf(“\\”) + 1));

           ItemList.SubItems.Add(fileInfo.LastWriteTime.ToString());

           long length = fileInfo.Length / 1024;

           if (length == 0) length = 1;

           ItemList.SubItems.Add(length + ” KB”);

           ItemList.ImageIndex = FileIconIndex(FileName);

           ItemList.Tag = FileName;

           listView1.Items.Add(ItemList);

           itemNum++;

        }//

      }

   }

   catch { }

   itemNumber.Text = itemNum.ToString();

}

//获取当有文件夹内的文件和目录

public void ListViewShow(string DirFileName)

{

   int itemNum = 0;

   listView1.Clear();

   listView1.Columns.Add(“名称”, 150);

   listView1.Columns.Add(“修改日期”, 150);

   listView1.Columns.Add(“大小”, 100, HorizontalAlignment.Right);

   try

   {

      foreach (string DirName in Directory.GetDirectories(DirFileName))//遍历当前分区或文件夹所有目录

      {

        if ((File.GetAttributes(DirName) & FileAttributes.Hidden) == FileAttributes.Hidden && showHiden.Value == false)

        {

           continue;

        }

        FileInfo fileInfo = new FileInfo(DirName);

        ListViewItem ItemList = new ListViewItem(DirName.Substring(DirName.LastIndexOf(“\\”) + 1));

        ItemList.SubItems.Add(fileInfo.LastWriteTime.ToString());

        ItemList.ImageIndex = FileIconIndex(DirName);

        ItemList.Tag = DirName;

        listView1.Items.Add(ItemList);

        itemNum++;

      }

 

      foreach (string FileName in Directory.GetFiles(DirFileName))//编历当前分区或文件夹所有目录的文件

      {

        if ((File.GetAttributes(FileName) & FileAttributes.Hidden) == FileAttributes.Hidden && showHiden.Value == false)

        {

           continue;

        }

        FileInfo fileInfo = new FileInfo(FileName);

        ListViewItem ItemList = new ListViewItem(FileName.Substring(FileName.LastIndexOf(“\\”) + 1));

        ItemList.SubItems.Add(fileInfo.LastWriteTime.ToString());

        long length = fileInfo.Length / 1024;

        if (length == 0) length = 1;

        ItemList.SubItems.Add(length + ” KB”);

        ItemList.ImageIndex = FileIconIndex(FileName);

        ItemList.Tag = FileName;

        listView1.Items.Add(ItemList);

        itemNum++;

      }//

   }

   catch

   { }

 

   itemNumber.Text = itemNum.ToString();

}

//列表框鼠标双击事件

private void listView1_DoubleClick(object sender, EventArgs e)

{

   string fullName = currentPath + listView1.FocusedItem.Text;

   if (Directory.Exists(fullName))

   {

      currentPath = fullName + “\\”;

      fullName += “\\”;

      ListViewShow(fullName);

      urlBox.Text = currentPath;

   }

}

#endregion

第四步:回到上层目录

//工具栏上层目录

private void parentDir_Click(object sender, EventArgs e)

{

   if (currentPath != “” && currentPath != null)

   {

      currentPath = currentPath.Substring(0, currentPath.Length – 2);

      if (currentPath.LastIndexOf(‘\\’) > 0)

      {

        currentPath = currentPath.Substring(0, currentPath.LastIndexOf(‘\\’) + 1);

        urlBox.Text = currentPath;

        ListViewShow(currentPath);

      }

      else//如果是根节点,则添加磁盘驱动器

      {

        listView1.Items.Clear();

        currentPath = “”;

        urlBox.Text = currentPath;

        TreeNode rootNode = new TreeNode(“My”);

        ListViewShow(rootNode);

      }

   }

}

第五步:添加右键菜单

为了能够对控件组合能够更好的操作,我们通常情况下需要添加右键菜单,首先我们在窗体设计界面上添加ComtextMenuStrip控件listView1Menu:

//列表框鼠标点击事件

private void listView1_MouseClick(object sender, MouseEventArgs e)

{

   if (e.Button == MouseButtons.Right && currentPath != “” && currentPath != null)

   {

      Point position;

      position = new Point(e.X, e.Y);

      listView1Menu.Show(this.listView1, position);

   }

}

此时在运行程序后在ListView控件显示的项目上右键单击鼠标便会弹出listView1Menu菜单。

第六步:初始化,开始运行

运行之前需要在窗体加载事件中写入下面的代码:

#region treelist初始化

//初始化列表图标

ListViewSysImages(listView1);

ListViewSysImages(listView2);

ListViewSysImages(fileDownload);

//初始化树形结构

treeView.ImageList = imageList;

//添加根节点

TreeNode rootNode = new TreeNode(“我的电脑”);//初始化TreeList添加总根节点

rootNode.ImageIndex = 0;

rootNode.SelectedImageIndex = 0;

treeView.Nodes.Add(rootNode);

//初始化树形结构

InitialTreeView(rootNode);

rootNode.Expand();

ListViewShow(rootNode);

#endregion

之后,编译运行。

微博上看到的视频下载到电脑上的方法

mikel阅读(1788)

我们刷微博时经常会看到网友发表视频,看到一些很棒的视频你是不是想下载到电脑上呢?网上可以找到很多所谓的教程,适用范围都不普遍。现在分类介绍下载那些视频的方法。

工具/原料

  • 浏览器(建议使用IE)
  • 迅雷
  • 部分视频网站的专用下载工具(如优酷、土豆)

第一类:有专用下载器的(如优酷、土豆)

  1. 1

    首先,下载视频的第一步就是进入原网页。在微博上就能找到(红框所示)。每一条分享视频的微博都会有一个这样的图标,点它就能进入原网页。

  2. 2

    进入了原网页,接下来就是用那些下载器来下载了。第一类是比较简单的。

    END

第二类:美拍视频

  1. 1

    由美图秀秀推出的“美拍”应用如今越来越受欢迎,使用人数也很多。美拍的视频在电脑上可以用迅雷来下载。第一步依然是进入原网页。

  2. 2

    进入原网页后,在网页内空白处右击鼠标,选择“查看源代码”。

  3. 3

    在源代码界面里你会看到一个“http://…….mp4”的地址,如果找不到,可以按组合键Ctrl+F打开查找功能,输入“.mp4”查找。找 到这个地址后复制它,这时如果你的迅雷已经打开,就会自动弹出建立新任务的提示。这样就能把美拍的视频下载好了。美拍这一类视频的网页在源代码中有完整视 频地址,下载相对也比较方便。

    END

第三类:只能找缓存文件的(如秒拍、微博视频)

  1. 1

    秒拍似乎已经过气了,“微博视频”也是现在手机微博的功能,经常被使用。这两种视频是以Flash的形式播放的,地址在源代码里找不到。很多网友都 说可以在缓存文件里找到,但如今的主流浏览器(如360、百度)为了减少内存占用量,是不保存大部分视频的缓存文件的,实践证明用360看过这两种视频 后,缓存文件里根本找不到对应文件。因此假如你对这个视频有比较执着的喜爱,那就麻烦一下找IE浏览器帮忙吧。

  2. 2

    可以把视频的原网页网址复制到IE打开。在视频播放完后,打开缓存文件夹(浏览器菜单栏上,工具==>Internet选项==>常规==>浏览历史记录==>设置==>查看文件)

  3. 3

    然后会打开一个文件很多的文件夹。这个文件夹的显示方式和一般的文件夹是不一样的。查看方式选择“详细信息”,按“上次访问时间”排序。然后拉到最近的文件,找到一个视频文件(一般是MP4文件)。

  4. 4

    如果你想打开看看这个文件是不是你要找的,一定要注意不要直接打开。一方面这个文件夹是Internet的缓存文件夹,直接打开只能用浏览器;另一方面,这些缓存的媒体文件只要被打开后就会消失。所以先把文件复制到另一个文件夹再打开。

  5. 5

    以上三类可以解决微博上绝大多数视频的下载问题了。希望能对你有帮助。

iphone绘图的几个基本概念CGPoint、CGSize、CGRect、CGRectMake、window(窗口)、视图(view)

mikel阅读(995)

我一般情况下不会使用interface builder去画界面,而是用纯代码去创建界面,不是装B,而是刚从vi转到xcode不久,不太习惯interface builder而已。当然如果需要我也会使用它。一个东西的存在没有绝对的好与坏,只是存在时间与空间决定了它的价值。

(忘了讲了,我的环境是xcode4.2)

首先要弄懂几个基本的概念。

 

一)三个结构体:CGPoint、CGSize、CGRect

1.  CGPoint

  1. /* Points. */
  2. struct CGPoint {
  3.   CGFloat x;
  4.   CGFloat y;
  5. };
  6. typedef struct CGPoint CGPoint;

看到这个想必你已经懂了,不再解释。

 

 

2.  CGSize

 

  1. /* Sizes. */
  2. struct CGSize {
  3.   CGFloat width;
  4.   CGFloat height;
  5. };
  6. typedef struct CGSize CGSize;

不解释。

 

3.CGRect

  1. /* Rectangles. */
  2. struct CGRect {
  3.   CGPoint origin;//偏移是相对父窗口的
  4.   CGSize size;
  5. };
  6. typedef struct CGRect CGRect;

同样 不解释。

 

这三个结构体均在一个头文件里:CGGeometry.h

二)几个方法

1.CGRectMake

  1. CG_INLINE CGRect
  2. CGRectMake(CGFloat x, CGFloat y, CGFloat width, CGFloat height)
  3. {
  4.   CGRect rect;
  5.   rect.origin.x = x; rect.origin.y = y;
  6.   rect.size.width = width; rect.size.height = height;
  7.   return rect;
  8. }

没错,这个方法就是make一个rect,定好origin(起点,左上角),宽与高,就可以画出一个位置与大小确定的rect(矩形)这个函数被声明为内联函数,一是因为它比较小,二是因为在画界面时我们要求一定的效率。这个函数还是藏在刚刚那个头文件里面:CGGeometry.h

 

三)几个基本界面元素:window(窗口)、视图(view)

要在屏幕上显示内容首先要创建一个窗口承载内容,要创建一个窗口,需要一个边框(frame),含有边框信息的底层 结构就CGRect。每个能够在屏幕上显示自己的对象都有一个边框,定义了他的显示区域,不过许多高层的视图类会自动计算这一信息。其他的那些类则在视图初始化时通过一个initWithFrame的初始化方法来设置。

再来认识一个类:UIScreen。UIScreen类代表了屏幕,通过这个类我们可以获取一些想要的东东。

  1. CGrect screenBounds = [ [UIScreen mainScreen]bounds];//返回的是带有状态栏的Rect
  2. CGRect viewBounds = [ [UIScreen mainScreen]applicationFrame];//不包含状态栏的Rect
  3. //screenBounds 与 viewBounds 均是相对于设备屏幕来说的
  4. //所以 screenBounds.origin.x== 0.0 ;   screenBounds.oringin.y = 0.0;   screenBounds.size.width == 320;  screenBounds.size.height == 480(或者其他分辨率有所差异)
  5. //所以 screenBounds.origin.x== 0.0 ;   screenBounds.oringin.y = 20.0;(因为状态栏的高度是20像素)   screenBounds.size.width == 320;  screenBounds.size.height == 480

 

UIView

下面来认识一下UIView类,这个类继承自UIResponder,看这个名字我们就知道它是负责显示的画布,如果说把window比作画框的话。我们就是不断地在画框上移除、更换或者叠加画布,或者在画布上叠加其他画布,大小当然 由绘画者来决定了。有了画布,我们就可以在上面任意施为了。很多简单的东西我会把库里面的内容贴出来,如果东西太多贴出来就不太好,朋友们自己去库文件里面看吧。这个类在UIView.h里面。下面我们先学习一些基础的东西,其他的东东会在以后慢慢展开。

  1. UIView* myView =[[ UIView alloc]initWithFrame:CGRectMake(0.0,0.0,200.0,400.0)];//这里创建了一块画布,定义了相对于父窗口的位置, 以及大小。

我们可以把这块画布加到其他画布上,具体方法后面会讲到。我们还可以在这块画布上画上其它好玩的东东,具体情形后面会一一讲解。

 

 

UIWindow

UIWindow继承自UIView,关于这一点可能有点逻辑障碍,画框怎么继承自画布呢?不要过于去专牛角尖,画框的形状不就是跟画布一样吗?拿一块画布然后用一些方法把它加强,是不是可以当一个画框用呢?这也是为什么 一个view可以直接加到另一个view上去的原因了。

看一下系统的初始化过程(在application didFinishLauchingWithOptions里面):

  1. self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
  2. self.window.backgroundColor = [UIColor grayColor];//给window设置一个背景色