Monthly Archives: November 2007

mysql backup shell script

mysql backup shell script
#!/bin/sh
# mysql_backup.sh: backup mysql databases and keep newest 5 days backup.
#
# Last updated: 2006.9.6
# ———————————————————————-
# This is a free shell script under GNU GPL version
# Feedback/comment/suggestions : http://www.strongd.net
# ———————————————————————-


# your mysql login information
# db_user is mysql username
# db_passwd is mysql password
# db_host is mysql host
# —————————–
db_user=”root”
db_passwd=”passwd”
db_host=”localhost”


# the directory for story your backup file.
backup_dir=”/backup”


# date format for backup file (dd-mm-yyyy)
time=”$(date +”%d-%m-%Y”)”


# mysql, mysqldump and some other bin’s path
MYSQL=”$(which mysql)”
MYSQLDUMP=”$(which mysqldump)”
MKDIR=”$(which mkdir)”
RM=”$(which rm)”
MV=”$(which mv)”
GZIP=”$(which gzip)”


# check the directory for store backup is writeable
test ! -w $backup_dir && echo “Error: $backup_dir is un-writeable.” && exit 0


# the directory for story the newest backup
test ! -d “$backup_dir/backup.0/” && $MKDIR “$backup_dir/backup.0/”


# get all databases
all_db=”$($MYSQL -u $db_user -h $db_host -p$db_passwd -Bse ‘show databases’)”


for db in $all_db
do
    $MYSQLDUMP -u $db_user -h $db_host -p$db_passwd $db | $GZIP -9 > “$backup_dir/backup.0/$time.$db.gz”
done


# delete the oldest backup
test -d “$backup_dir/backup.5/” && $RM -rf “$backup_dir/backup.5”


# rotate backup directory
for int in 4 3 2 1 0
do
    if(test -d “$backup_dir”/backup.”$int”)
    then
        next_int=`expr $int + 1`
        $MV “$backup_dir”/backup.”$int” “$backup_dir”/backup.”$next_int”
    fi
done


exit 0;


How to write a shell script

How to write a shell script
Introduction
A shell is a command line interpretor. It takes commands and executes them. As such, it implements a programming language. The Bourne shell is used to create shell scripts — ie. programs that are interpreted/executed by the shell. You can write shell scripts with the C-shell; however, this is not covered here.


Creating a Script
Suppose you often type the command
    find . -name file -print


and you’d rather type a simple command, say
    sfind file


Create a shell script
    % cd ~/bin
    % emacs sfind
    % page sfind
    find . -name $1 -print
    % chmod a+x sfind
    % rehash
    % cd /usr/local/bin
    % sfind tcsh
    ./shells/tcsh


Observations
This quick example is far from adequate but some observations:
Shell scripts are simple text files created with an editor.
Shell scripts are marked as executeable
    %chmod a+x sfind


Should be located in your search path and ~/bin should be in your search path.
You likely need to rehash if you’re a Csh (tcsh) user (but not again when you login).
Arguments are passed from the command line and referenced. For example, as $1.
#!/bin/sh
All Bourne Shell scripts should begin with the sequence
    #!/bin/sh


From the man page for exec(2):
“On the first line of an interpreter script, following the “#!”, is the name of a program which should be used to interpret the contents of the file. For instance, if the first line contains “#! /bin/sh”, then the con- tents of the file are executed as a shell script.”


You can get away without this, but you shouldn’t. All good scripts state the interpretor explicitly. Long ago there was just one (the Bourne Shell) but these days there are many interpretors — Csh, Ksh, Bash, and others.


Comments
Comments are any text beginning with the pound (#) sign. A comment can start anywhere on a line and continue until the end of the line.
Search Path
All shell scripts should include a search path specifica- tion:
    PATH=/usr/ucb:/usr/bin:/bin; export PATH


A PATH specification is recommended — often times a script will fail for some people because they have a different or incomplete search path.
The Bourne Shell does not export environment variables to children unless explicitly instructed to do so by using the export command.


Argument Checking
A good shell script should verify that the arguments sup- plied (if any) are correct.


    if [ $# -ne 3 ]; then
         echo 1>&2 Usage: $0 19 Oct 91
         exit 127
    fi


This script requires three arguments and gripes accordingly.


Exit status
All Unix utilities should return an exit status.
    # is the year out of range for me?


    if [ $year -lt 1901  -o  $year -gt 2099 ]; then
         echo 1>&2 Year \”$year\” out of range
         exit 127
    fi


    etc…


    # All done, exit ok


    exit 0


A non-zero exit status indicates an error condition of some sort while a zero exit status indicates things worked as expected.
On BSD systems there’s been an attempt to categorize some of the more common exit status codes. See /usr/include/sysexits.h.


Using exit status
Exit codes are important for those who use your code. Many constructs test on the exit status of a command.
The conditional construct is:


    if command; then
         command
    fi


For example,
    if tty -s; then
         echo Enter text end with \^D
    fi


Your code should be written with the expectation that others will use it. Making sure you return a meaningful exit status will help.
Stdin, Stdout, Stderr
Standard input, output, and error are file descriptors 0, 1, and 2. Each has a particular role and should be used accordingly:
    # is the year out of range for me?


    if [ $year -lt 1901  -o  $year -gt 2099 ]; then
         echo 1>&2 Year \”$year\” out of my range
         exit 127
    fi


    etc…


    # ok, you have the number of days since Jan 1, …


    case `expr $days % 7` in
    0)
         echo Mon;;
    1)
         echo Tue;;


    etc…


Error messages should appear on stderr not on stdout! Output should appear on stdout. As for input/output dialogue:
    # give the fellow a chance to quit


    if tty -s ; then
         echo This will remove all files in $* since …
         echo $n Ok to procede? $c;      read ans
         case “$ans” in
              n*|N*)
    echo File purge abandoned;
    exit 0   ;;
         esac
         RM=”rm -rfi”
    else
         RM=”rm -rf”
    fi


Note: this code behaves differently if there’s a user to communicate with (ie. if the standard input is a tty rather than a pipe, or file, or etc. See tty(1)).
Language Constructs
For loop iteration
Substitute values for variable and perform task:


    for variable in word …
    do
         command
    done


For example:
    for i in `cat $LOGS`
    do
            mv $i $i.$TODAY
            cp /dev/null $i
            chmod 664 $i
    done


Alternatively you may see:
    for variable in word …; do command; done


Case
Switch to statements depending on pattern match


    case word in
    [ pattern [ | pattern … ] )
         command ;; ] …
    esac


For example:


    case “$year” in


    [0-9][0-9])
            year=19${year}
            years=`expr $year – 1901`
            ;;
    [0-9][0-9][0-9][0-9])
            years=`expr $year – 1901`
            ;;
    *)
            echo 1>&2 Year \”$year\” out of range …
            exit 127
            ;;
    esac


Conditional Execution
Test exit status of command and branch


    if command
    then
         command
    [ else
         command ]
    fi


For example:
    if [ $# -ne 3 ]; then
            echo 1>&2 Usage: $0 19 Oct 91
            exit 127
    fi


Alternatively you may see:
    if command; then command; [ else command; ] fi


While/Until Iteration
Repeat task while command returns good exit status.


    {while | until} command
    do
         command
    done


For example:
    # for each argument mentioned, purge that directory


    while [ $# -ge 1 ]; do
            _purge $1
            shift
    done


Alternatively you may see:
    while command; do command; done


Variables
Variables are sequences of letters, digits, or underscores beginning with a letter or underscore. To get the contents of a variable you must prepend the name with a $.


Numeric variables (eg. like $1, etc.) are positional vari- ables for argument communication.



Variable Assignment
Assign a value to a variable by variable=value. For example:


    PATH=/usr/ucb:/usr/bin:/bin; export PATH


or
    TODAY=`(set \`date\`; echo $1)`


Exporting Variables
Variables are not exported to children unless explicitly marked.


    # We MUST have a DISPLAY environment variable


    if [ “$DISPLAY” = “” ]; then
            if tty -s ; then
     echo “DISPLAY (`hostname`:0.0)? \c”;
     read DISPLAY
            fi
            if [ “$DISPLAY” = “” ]; then
     DISPLAY=`hostname`:0.0
            fi
            export DISPLAY
    fi


Likewise, for variables like the PRINTER which you want hon- ored by lpr(1). From a user’s .profile:
    PRINTER=PostScript; export PRINTER


Note: that the Cshell exports all environment variables.


Referencing Variables
Use $variable (or, if necessary, ${variable}) to reference the value.


    # Most user’s have a /bin of their own


    if [ “$USER” != “root” ]; then
            PATH=$HOME/bin:$PATH
    else
            PATH=/etc:/usr/etc:$PATH
    fi


The braces are required for concatenation constructs.
$p_01


The value of the variable “p_01”.
${p}_01


The value of the variable “p” with “_01” pasted onto the end.


Conditional Reference


${variable-word}


If the variable has been set, use it’s value, else use word.
POSTSCRIPT=${POSTSCRIPT-PostScript};
export POSTSCRIPT


${variable:-word}


If the variable has been set and is not null, use it’s value, else use word.
These are useful constructions for honoring the user envi- ronment. Ie. the user of the script can override variable assignments. Cf. programs like lpr(1) honor the PRINTER environment variable, you can do the same trick with your shell scripts.


${variable:?word}


If variable is set use it’s value, else print out word and exit. Useful for bailing out.


Arguments
Command line arguments to shell scripts are positional vari- ables:


$0, $1, …


The command and arguments. With $0 the command and the rest the arguments.
$#


The number of arguments.
$*, $@


All the arguments as a blank separated string. Watch out for “$*” vs. “$@”.
And, some commands:
shift


Shift the postional variables down one and decrement number of arguments.
set arg arg …


Set the positional variables to the argument list.
Command line parsing uses shift:


    # parse argument list


    while [ $# -ge 1 ]; do
            case $1 in
         process arguments…
            esac
            shift
    done


A use of the set command:
    # figure out what day it is


    TODAY=`(set \`date\`; echo $1)`


    cd $SPOOL


    for i in `cat $LOGS`
    do
            mv $i $i.$TODAY
            cp /dev/null $i
            chmod 664 $i
    done


Special Variables
$$


Current process id. This is very useful for constructing temporary files.
         tmp=/tmp/cal0$$
         trap “rm -f $tmp /tmp/cal1$$ /tmp/cal2$$”
         trap exit 1 2 13 15
         /usr/lib/calprog >$tmp


$?


The exit status of the last command.
         $command
         # Run target file if no errors and …


         if [ $? -eq 0 ]
         then
  etc…
         fi



Quotes/Special Characters
Special characters to terminate words:


      ; & ( ) | ^ < > new-line space tab


These are for command sequences, background jobs, etc. To quote any of these use a backslash (\) or bracket with quote marks (“” or ”).
Single Quotes


Within single quotes all characters are quoted — including the backslash. The result is one word.



         grep :${gid}: /etc/group | awk -F: ‘{print $1}’


Double Quotes
Within double quotes you have variable subsitution (ie. the dollar sign is interpreted) but no file name generation (ie. * and ? are quoted). The result is one word.


         if [ ! “${parent}” ]; then
           parent=${people}/${group}/${user}
         fi


Back Quotes
Back quotes mean run the command and substitute the output.



         if [ “`echo -n`” = “-n” ]; then
   n=””
   c=”\c”
         else
   n=”-n”
   c=””
         fi


and
         TODAY=`(set \`date\`; echo $1)`


Functions
Functions are a powerful feature that aren’t used often enough. Syntax is


    name ()
    {
         commands
    }


For example:


    # Purge a directory


    _purge()
    {
            # there had better be a directory


            if [ ! -d $1 ]; then
     echo $1: No such directory 1>&2
     return
            fi


         etc…
    }


Within a function the positional parmeters $0, $1, etc. are the arguments to the function (not the arguments to the script).
Within a function use return instead of exit.


Functions are good for encapsulations. You can pipe, redi- rect input, etc. to functions. For example:


    # deal with a file, add people one at a time


    do_file()
    {
            while parse_one


            etc…
    }


    etc…


    # take standard input (or a specified file) and do it.


    if [ “$1” != “” ]; then
            cat $1 | do_file
    else
            do_file
    fi


Sourcing commands
You can execute shell scripts from within shell scripts. A couple of choices:


sh command


This runs the shell script as a separate shell. For example, on Sun machines in /etc/rc:


         sh /etc/rc.local


. command
This runs the shell script from within the current shell script. For example:


         # Read in configuration information
         .  /etc/hostconfig


What are the virtues of each? What’s the difference? The second form is useful for configuration files where environment variable are set for the script. For example:
    for HOST in $HOSTS; do


      # is there a config file for this host?


      if [ -r ${BACKUPHOME}/${HOST} ]; then
.  ${BACKUPHOME}/${HOST}
      fi
    etc…


Using configuration files in this manner makes it possible to write scripts that are automatically tailored for differ- ent situations.
Some Tricks
Test
The most powerful command is test(1).


    if test expression; then


         etc…


and (note the matching bracket argument)
    if [ expression ]; then


         etc…


On System V machines this is a builtin (check out the com- mand /bin/test).
On BSD systems (like the Suns) compare the command /usr/bin/test with /usr/bin/[.


Useful expressions are:


test { -w, -r, -x, -s, … } filename


is file writeable, readable, executeable, empty, etc?
test n1 { -eq, -ne, -gt, … } n2


are numbers equal, not equal, greater than, etc.?
test s1 { =, != } s2


Are strings the same or different?
test cond1 { -o, -a } cond2


Binary or; binary and; use ! for unary negation.
For example


    if [ $year -lt 1901  -o  $year -gt 2099 ]; then
         echo 1>&2 Year \”$year\” out of range
         exit 127
    fi


Learn this command inside out! It does a lot for you.


String matching
The test command provides limited string matching tests. A more powerful trick is to match strings with the case switch.


    # parse argument list


    while [ $# -ge 1 ]; do
            case $1 in
            -c*)    rate=`echo $1 | cut -c3-`;;
            -c)     shift;  rate=$1 ;;
            -p*)    prefix=`echo $1 | cut -c3-`;;
            -p)     shift;  prefix=$1 ;;
            -*)     echo $Usage; exit 1 ;;
            *)      disks=$*;       break   ;;
            esac


            shift


    done


Of course getopt would work much better.


SysV vs BSD echo
On BSD systems to get a prompt you’d say:


    echo -n Ok to procede?;  read ans


On SysV systems you’d say:
    echo Ok to procede? \c; read ans


In an effort to produce portable code we’ve been using:
    # figure out what kind of echo to use


    if [ “`echo -n`” = “-n” ]; then
            n=””;  c=”\c”
    else
            n=”-n”;     c=””
    fi


    etc…


    echo $n Ok to procede? $c; read ans


Is there a person?
The Unix tradition is that programs should execute as qui- etly as possible. Especially for pipelines, cron jobs, etc.


User prompts aren’t required if there’s no user.


    # If there’s a person out there, prod him a bit.


    if tty -s; then
         echo Enter text end with \^D
    fi


The tradition also extends to output.
    # If the output is to a terminal, be verbose


    if tty -s <&1; then
         verbose=true
    else
         verbose=false
    fi


Beware: just because stdin is a tty that doesn’t mean that stdout is too. User prompts should be directed to the user terminal.
    # If there’s a person out there, prod him a bit.


    if tty -s; then
         echo Enter text end with \^D >&0
    fi


Have you ever had a program stop waiting for keyboard input when the output is directed elsewhere?


Creating Input
We’re familiar with redirecting input. For example:


    # take standard input (or a specified file) and do it.


    if [ “$1” != “” ]; then
            cat $1 | do_file
    else
            do_file
    fi


alternatively, redirection from a file:
    # take standard input (or a specified file) and do it.


    if [ “$1” != “” ]; then
            do_file < $1
    else
            do_file
    fi


You can also construct files on the fly.
    rmail bsmtp <
    rcpt to:
    data
    from: <$1@newshost.uwo.ca>
    to:
    Subject: Signon $2


    subscribe $2 Usenet Feeder at UWO
    .
    quit
    EOF


Note: that variables are expanded in the input.


String Manipulations
One of the more common things you’ll need to do is parse strings. Some tricks



    TIME=`date | cut -c12-19`


    TIME=`date | sed ‘s/.* .* .* \(.*\) .* .*/\1/’`


    TIME=`date | awk ‘{print $4}’`


    TIME=`set \`date\`; echo $4`


    TIME=`date | (read u v w x y z; echo $x)`


With some care, redefining the input field separators can help.


    #!/bin/sh
    # convert IP number to in-addr.arpa name


    name()
    {    set `IFS=”.”;echo $1`
         echo $4.$3.$2.$1.in-addr.arpa
    }


    if [ $# -ne 1 ]; then
         echo 1>&2 Usage: bynum IP-address
         exit 127
    fi


    add=`name $1`


    nslookup < < EOF | grep “$add” | sed ‘s/.*= //’
    set type=any
    $add
    EOF


Debugging
The shell has a number of flags that make debugging easier:


sh -n command


Read the shell script but don’t execute the commands. IE. check syntax.


sh -x command


Display commands and arguments as they’re executed. In a lot of my shell scripts you’ll see


    # Uncomment the next line for testing
    # set -x


 

Freez 3GP Video Converter







Freez 3GP Video Converter is a 3GP-converting tool for mobile phone users. With Freez 3GP Video Converter, you can convert batches of video files to 3gp, 3g2 formats to be played on mobile phones.

Freez 3GP Video Converter supports most popular video formats to be converted to 3gp video, including AVI, DivX, Xvid, MPEG 1/2/4, VOB, WMV, ASF, MP4, MOV, RM, RMVB, Flv, SWF etc. You can create both 3GPP and 3GPP2 video files. The output video codecs include MPEG4, XVID and H263; the audio codecs include AMR-NB and AAC-LC. You can set the video size, quality, framerate, audio bitrate, frequency, and channel. And there are two zoom modes: Stretch and Letterbox, which will add black letterbox on output video to keep aspect ratio.

Freez 3GP Video Converter is easy-to-use, fast and creates good quality. Have fun with it!


 

DOWNLOAD HERE: http://www.smallvideosoft.com/downloads/freez_3gpconverter.exe

AS3日积月累(3) – 利用AS3的图形界面开发及资源管理攻略

原文章地址:http://as3blog.com/as3/as3tip-take-care-of-resource


摒弃了attachMovie之后的AS3,采用了类似DOM的操作方式。addChild、removeChild、getChildAt等方法开始成为AS3中显示(在屏幕上渲染)、操作图形的主要方法。由于AS1、AS2完全是依赖于attchMovie的思想,因此对于传统Flash开发人员来说,转变到新的addChild的确需要下一番功夫。


由于新的“DisplayObject”在内存的使用上非常“敏感”。往往由于不良的编程习惯会造成不必要的内存泄漏,因此,我们不得不比AS1、AS2时代更加深入到内存管理了。我想,每一个Flash开发人员,包括我自己,都应该花一番功夫仔细体会“内存管理”这几个字的含义。毕竟我们学习AS3是为了开发比AS1、2时代更加先进、高效而且内存占用小的应用程序,如果还是开发一些简单的应用,也就失去我们每一个人使用AS3的意义了。


我觉得,由于GC是Flash应用程序内存管理的核心,我应该先从AS3中的Garbage Collector(简称GC)开始说起。AS3的GC功能比AS1、2中的要强大的多。然而,强大的同时,也带来了一定程度的复杂性。但是也不至于非常复杂,我觉得比C++等传统语言要容易掌握得多。


在研究内存如何回收之前,先说一下变量的创建:
在Flash中,我们每建立一个非原生变量时(Boolean, String, Number, uint, int这些是原生变量),这个变量名只是一个reference(指向,有时候也成为“引用”)而已,而并非这个变量本身。例如:
var a:int = 5; //a就是5
var b:int = a; //b是a,也就是5
a = 4;
trace(b); // 是5,而不是4!
//改变b的值,a不发生变化。反之亦然
var c:Object = {name:”aw”, blog:”www.awflasher.com/blog”}; //c只是指向一个内部的Object,为了描述方便,称其为“O”
var d:Object = c; //d指向c,指向了同一个Object“O”
c.name = “bw”
trace(d.name); //不是aw,而是bw了
//改变c也好,改变d也罢,其实是改变了那个“O”,因此改变c的时候,d的值也就变了。因此d.name已经被改变为了“bw”。


首先,明确一点,GC会按照一定的时间周期进行内存清理(memory sweep)。因此不要因为delete掉一个object后检查System.totalMemory内存就没有反应而怀疑GC是否正常。


那么GC为什么要按照一定的时间周期进行清理呢。这还要得从GC的具体工作原理说起。


GC的两个回收体系:
1、“Reference Counting” – 引用计数器
这个体系是自从AS1时代就有的体系,它的工作原理非常简单:系统计算每一个对象被指向,或者说引用的次数。比如
var a:Object = {name:”aw”, blog:”www.awflasher.com/blog”};
这时候,这个Object(我们仍然称为“O”),有一次引用,它的引用计数器为1(来自a)。
我们再建立一个对象b,并指向到a:
var b:Object = a;
这时候“O”引用计数器变为了2(来自a、b)
我们删除一个,比如先删除b:
delete b;
这时候引用计数器为(2-1=1)1,GC不操作
再删除另外一个a:
delete a;
“O”引用计数器变为(1-1=0)0,GC出面干掉这个对象。
这套体系很轻便,CPU压力较小。但是它也有缺陷。当我们的对象内部互相引用的时候,麻烦就来了。例如:
var a:Object = {name:”aw”, description:”unknown”};
// 建立一个对象a,仍然假设内部对象为“O”,这时O的引用次数为1
var b:Object = {nameObj:a, url:”awflasher.com”};
// b引用了a,同时创建了新的内部对象“P”。这时O的引用次数为2,P为1
a.myDescription = b;
// a的myDescription属性指向到了b。这样,P的引用次数也为2了。
// 是不是有点头晕?静下来,画个图慢慢看看:)
delete a;
delete b;
两次delete操作后,O、P的引用次数都是1,它们将继续占用你的内存。“Reference Counting” 体系无能为力了。


2、“Mark Sweeping” – 标记清除法则
GC的第一种机制“Reference Counting”,在FlashPlayer8之前是GC唯一的机制。FlashPlayer6和7由于引入了复杂的OOP开发模式,尤其是7引入了类似Java、C++等强大OOP语言的语法。利用Flash设计的复杂项目越来越多。由于Flash开发人员大多不了解GC,而Java、C++的开发人员又已经习惯了强大的GC(无论是自动的还是手动的)。因此FlashPlayer6、7的内存问题开始浮现出来。
Okay,Flash Player8引入了新的“Mark Sweeping”机制。我想这也是当年Marcomedia(Adobe)急于推出Player8的原因吧!(还记得当年Flash8的介绍视频么,效率提高是一个革命性的改进)
下面就来讲述“Mark Sweeping” – 标记清除法则的工作原理。
FlashPlayer会从root开始,遍历系统的每一个变量,并对有指向的对象之间,记录一次联系。在遍历结束之后,凡是与root不相联系的对象,被FlashPlayer无情地干掉:)
Okay,回到刚才的例子,当我们delete a,并delete b之后,root与O、P就划清了界线。这时候,GC就可以进行一次肃清了。
然而,由于这种“Mark Sweeping”要遍历所有的对象,因此非常消耗资源。这也就回到了当初的问题:“GC为什么要按照一定的时间周期进行清理“ – 因为不能给CPU造成太大的负担。
我个人猜测,GC的内部清除策略应该是在某一次事件(例如delete)发生后,在CPU比较空闲、RAM分配相对合理的情况下执行的。


3、关于delete。Gskinner《Understanding Delete》说的很清楚:
delete在AS3中,只能删除dynamic类的对象实例的属性/方法了。这意味着你不能像AS2那样用delete随意删除成员了。当然,替代方法还是有的:把成员设置为null即可。例如myobj.name=null;


Okay,不要以为有了“Mark Sweeping”就万事大吉了。由于GC不会即时进行,因此你的对象会在一段时间内“阴魂不散”!对于一个追求完美的开发人员来说,这意味着它们内部的某些机制会在被删除之后继续工作:AS语句会继续执行、声音会继续播放、事件会继续触发!


KirupaForum有网友说,“All you got to do is pray the garbage collector doesn’t break down.”,确实,如果一个应用程序要运行上一个多小时,那么慢慢流逝的内存会让你的用户对你的产品失望(例如游戏)。因此我们需要有一个良好的资源管理策略。


AS3日积月累(2) – 从AS1和AS2到AS3的观念转变


原文章地址:http://as3blog.com/as3/as3tip-new-philosophy/


AS1/2-AS3观念的转变(Meet with new philosophy)
对于AS1、AS2的开发模式来说,灵活是最大的优势。然而,灵活却造成了不稳定、紊乱。这是开发复杂的、长久的项目所忌讳的。关于(AS1/2/1+2)灵活轻便与稳定持久(AS3)的权衡,我个人觉得可以理解为”鱼和熊掌不可兼得”,但我希望已经习惯了AS1、AS2的朋友们不要把这个结论想得太悲观。


AS3是纯粹面向对象的,相比过去的AS2,我认为是更加敏捷的。纵然有着更多的约束,但在package内直接建立多个辅助类(Helper Class),不失为一个非常好的消息。就凭这一点,我觉得至少与笨拙的AS2相比,AS3的开发效率就不会打多大折扣。我们需要的其实只是语法、习惯,尤其是观念的转变而已。当然,这需要时间。我作为一个AS1/2的长期发开人员,在转变到AS3的过程之中,也遇到了很多问题和疑惑。但我很乐于与大家分享、交流我所获得的收获以及观念转变的心路历程。


ActionScript编程自它问世的那一天就是多姿多彩的。技术,尤其是Adobe产品线的技术体系,也绝然不是呆板的”学究式体系”。我希望我的”罗嗦”能让您获得一个更轻松的心态。


言归正传,先说说我在AS1/2(1+2)转变到AS3时所遭遇的最大困惑吧:
开局(How, and especially where, to get start) – 玩过星际争霸的朋友们一定知道,针对不同的地图,如Lost Temple和WCG-groky park(原来WCG有一个岛关,我忘记了),都有各自的经典、流行的开局方式。从AS1/2转变到AS3,无非是从Lost Temple转变到WCG-groky park的过程,你也许要先采气矿,造空军,才能顺利发展。


其实Flash从AS1到AS3,也有各自固定的、流行的开局方式。
对于习惯了用AS1编程的人来说,制作一个Flash的开局是非常灵活的:你一进入Flash就有一个长长时间轴以供使用。你往往需要一个loading,你可以用1-5帧先做一个loading(还记得N年前流行的FlashMTV制作教程么?);你也可以取一帧,放一个loading的MovieClip然后在这个MovieClip上写一个onEnterFrame来监听swf文件加载的进度(我热衷的做法)。接下来,你可以在第二帧或者第N帧部署程序界面。MovieClip强大的帧API能让你灵活地完成许多有趣的逻辑(gotoAndPlay、gotoAndStop、prevFrame等)。编程的时候也可以很随意地寻找自己要控制的资源,我现在还记得刚接触AS的时候,一个_root一个_global,曾经让我屡试不爽。每次遇到问题了就用这两个东西解决。
AS2的开局其实没有本质的变化,至少我是这么认为的。唯一的进步就是比AS1的OOP,模块封装的更加彻底。甚至还有些许退步,比如清一色基于MovieClip+attachMovie的模式,仍然容易造成运行时(Run-Time)效率低下,而且开发起来概念也模糊了。因为Library中设置了linkage,new的明明是自己的Class,attach的还是MovieClip。
于是很多人采用AS1+2的方式,这也是我所喜欢的。现在想起来,还是比较灵活快速的。
然而在AS3中,你却仿佛陷入一片黑暗。FlexBuilder没有时间轴。即便用”似曾相识”的FlashCS3的IDE开发,AS3也不支持MovieClip和Button上的代码。写在帧上也无法简单地使用”onRelease=functioin”了。上网搜一搜教程,往往得到如下的写法:
aw.addEventListener(”click”,fun);
function fun(e:Event){trace(1);}
实在让习惯了AS1、2的朋友们郁闷。


一方面看到人家用AS3设计出来的精彩demo羡慕不已,一方面又对程序入口摸不着边际。这种尴尬我想不是看一两篇教程就能解决的。


我们需要”洗心革面”,我们需要”忘记过去”(try to forget the past)。大胆地告诉自己,onRelease=function不仅已经被”杀死”,而且根本就不是好的写法,哪怕你仍然觉得它看起来那么顺眼。大胆地告诉自己,AS3中,所有的变量、函数都属于类(对象的属性和方法),而不再属于时间轴、帧,哪怕上面列举的两行代码也可以写在时间轴上生效。


我个人建议,传统AS1/2的程序员从Flash CS3 IDE入手AS3,比较合适。因为Flash CS3的入口(开局)非常明确:Document Class(文档类)。


运行FlashCS3,打开fla文件,在IDE下面属性面板中,找到”Document Class”,填入一个名字(由于是类名,最好是首字母大写,比如MyMainClass)。然后在fla文件所在的文件夹下面建立同名的as文件。当然,也可以把fla和类文件全部分离,这就需要设定类路径(File-Publish Settings-ActionScript version:Settings)。下面可以输入类路径。我个人建议输入相对路径。相对,意即相对当前的fla文件;路径,即我们电脑文件系统中的文件夹。不写死”x:\xxx”是为了让项目可以在不同的环境上运行,也可以更好的支持多人开发。相对路径的写法就是用”.”表示当前路径,用”..”表示上一级路径。比如可以写:
“./classes/”或者”../classes/”。
这里再补充说明一下,我的建议是把原文件放在一起,输出的swf放在别的目录(通常叫做”bin”)。输出目录在刚才面板中的”format”标签下,可以把原文件放到目录”src”中,然后把swf格式的file名设置为”../bin/somefile.swf”,建议只输出swf。HTML还是自己写的好。
别看我罗嗦了这么多篇幅讲这些设置,但它们真的对于规范你的开发习惯和开发观念有好处。让你潜移默化的接受AS3的Philosophy中的”分离”思想。


补充内容: 关于Flash CS3类路径的设置,如果您希望设计自己的package。那么则需要把这个package放在classpath下面,而不要把package文件夹自己设置为classpath


切入正题,我们逐步开局:
一、建立文档类(Document Class)
现在我们可以开始建立Document Class了。Flash CS3方便地提供了一个”编辑图标”,你可以方便地打开类文件。回忆一下,上一篇文章提到关于类的书写:每一个类都应该在一个package中。我个人的理解,觉得Document Class应该在一个单独的、无具体名称的”generic”package中,即:
package
{
import flash.display.Sprite;
public class MyMainClass extends Sprite
{
public function MyMainClass()
{
init();
}
private function init()
{
// do sth
}
}
}
// We can even use some help classes
class MyMainClassHelper{}
这里,我们就成功”开局”了。
注意,这个文档类必须为public的。而辅助类则不能定义为public、private的,必须是internal的。文档类必须继承自Sprite或者MovieClip。因为这个文档类代表了这个swf,显然swf是一个需要在屏幕上渲染显示(flash.display.DisplayObject)并提供资源承载能力(flash.display.InteractiveObject)的基础容器。


二、逻辑开局(Initialize the logic)
我们所有的逻辑入口都是从这个类的构造函数开始的。AS3的loading有一些麻烦,我们暂时跳过(稍后会介绍)。
构造函数一般要保持简洁,不妨用流行的init方式开局,即在构造函数内调用一个init函数。记住一点,AS3中,”_root”已死,这里就是传统意义上的”_root”了。你看到的这个类(文档类),第一反应应该是这个swf文件(就如同你原来看到”_root”就应该反应到swf文件一样)!在这里可以找到原来我们需要的许多资源,例如我们可以找到通过loaderInfo:LoaderInfo属性(继承自DisplayObject),获取外部参数:xxx.swf?somevar=1传进来的”somevar”,也可以通过stage:Stage属性(继承自DisplayObject),来进行原来的Stage类的各种操作。我也可以用contextMenu:ContextMenu属性(继承自InteractiveObject),来控制flash右键菜单的内容。
这一切都在文档类的init以及其他所属方法中进行。所有的其它功能,可以封装成别的类、包进行”模块式”调用。


三、事件机制(The new Event System)
习惯新的事件机制所花的勇气,我认为和开局相当。我曾经热衷于xxx_mc.onRelease = function(){}的写法,而且做过N多这样的项目。然而当我真正开始用addEventListener的时候,才发现这是多么优雅的写法。优雅在哪:



  1. 统一:只有addEventListener,没有addListener、没有on(…),代码可以统一地放置。
  2. 清晰:事件处理函数作为类的方法(Methods)列举分明,试想一个跟在onXXX后面的赋值函数放在代码当众多难找。
  3. 信息翔实、准确:新的事件机制通过传递Event对象让事件的信息完整无漏地传达给接受方;函数(方法)与类绑死,Delegate终于可以光荣退休了。

四、总结



  1. 接受新的OOP开发体系:类/对象(class/object)+构造函数(constructor)+成员属性(properties)+成员方法(methods),除了这些东西以外,ActionScript没有别的存在形式!把时间轴和实例上的代码都忘记吧!
    我们要”拥抱”类的概念!AS3中所有的一切围绕着类的概念进行。swf就是一个类,用Flex开发,叫做Application,用CS3,叫做Document Class(往往继承自Sprite)。任何变量(属性)都属于一个类,MovieClip有成员属性currentScene,它是Scene类的一个实例;Sprite有成员属性contextMenu和stage,它们继承自DispatchObject类,分别是ContextMenu类和Stage类的实例。
  2. 没有_root,所有的_root有关的操作,封装到文档类中的成员函数(方法)进行。_root不再是swf的代表,取而代之的是Document Class(或者Flex中的Application Class)
  3. 功能模块化、分离:
    不要把所有的事情都塞到文档类中去做,哪怕你可以定义很多辅助类,毕竟独立出来的文件更加便于管理、集成、再使用。而且界面(图形、动画)和代码要分离(事实上AS3的Document Class和addChild的内容管理体系帮我们完成了这个操作) 。无论你是一个人搞定代码+设计还是有一个团队协作分工编程与动画。分离的好处是让你的功能更加强大和易维护。

AS3日积月累(1) – AS3的面向对象特点概述

原文章地址:http://as3blog.com/as3/as3tip-oop/


本文是我(aw)在整理了相关文档和讨论之后,结合自己的亲自实验总结出来的一些经验和心得。我尽量描述详尽,避免模糊概念,当然也希望所有看官提出批评意见。为了表述方便,其中术语不限定语言,如我可能会一会儿用class,一会儿用“类”。


面向对象的难点部分就是理解变量作用域修饰符(modifier)其实也就是面向对象中我们已经熟悉的public、protected、private等等。本文还深入讨论了ActionScript3中新增的internal等概念。下面我依次列出:


一、关于package以及internal
package,用“形而上学”的方式理解,就是物理目录下的类集合。在AS2中只需要保证文件系统的路径匹配,然后用类似“import com.awflasher.someUtils”的方法导入即可。而AS3则要求您在所有的类中声明package关键词。package的大括号对“{}”内,我们只能定义一个类,我们可以在这个大括号外面定义一些辅助类,不过这些类只能被当前这个类(你在package大括号对内定义的类)访问。当然,一个package大括号对内只有一个类,这并不代表一个package内只有一个类。你可以在同一目录下定义多个属于该package(指代这个目录)的类。它的意义绝不是简单的“类文件集合容器”,而是一个让各种应该协同工作的类集中到一起的项目包。值得一提的是,所谓“协同工作”是指至少有一个class要引入其他一些class来进行功能设计,而这时候采用internal修饰可以省去很多getters和setters。我自己回忆起在湖南卫视的项目中用AS2开发的Vplayer,两个类AVCore和AVControl就有很多getter和setter,搞的特别麻烦。internal类似public,但限定在一个package内了。在同一个package内的类可以访问同一个package内其他类的internal变量,而其他包内的类无法访问。package与类的继承性毫无关系,比如TextField和Sprite、MovieClip都继承自DisplayObject类,但TextField属于flash.text包,而MovieClip和Sprite属于flahs.display包。也就是说,包对类的限定是与继承链毫无关联的、一个新的“维度”的限定。
附:使用一个类的时候,我们必须import这个类,或者包含这个类的package。AS2时直接写完整包路径的使用方法在AS3中不管用了,本文后面有详细介绍。


二、关于public
public定义的类或者属性可以在任何作用域内由任何来源访问。构造函数永远都是public的,Flex中的应用程序类(Application Class)和Flash CS3中的文档类(Document Class)必须是public的。且不能缺省public这个关键词声明。我在测试中发现,如果不声明public,Flash根本就不会获取类的定义,进而编译无法通过。
非常有必要啰嗦一下:public可以穿越package,而类又不能使用namespace(参阅FlashCS3帮助文档:Applying namespaces)。因此,所有被文档类调用的其它包中的类,应该一致声明为public的 。因为文档类在一个独立的包中。


三、关于protected
protected声明类似AS2的private,它定义的属性只能在自己子类中可见,而其它场合都是不可见的。这一点与Java等传统OOP语言类似。


四、关于private
注意AS3的private和AS2的private大不相同,它定义的属性只属于自己,子类可以定义毫无牵连的同名属性。
dynamic 和原来AS2的dynamic一样,用dynamic声明的类可以动态的加入属性。这些属性也可以通过delete来删除。动态加入的属性一旦被切断所有的引用就会被垃圾回收机制自动回收。有时候用System.totalMemory检测不到内存释放是因为垃圾回收机制并不是即时运行的。


五、关于dynamic
动态(dynamic)类允许在运行时动态地添加属性,常见的动态类有MovieClip和顶级(top-level)的Array。如果您的自定义类要继承于动态类,那么请也定义为动态的,不要省略dynamic关键词。如果您喜欢阅读英文教程,会看到很多“sealed class”,其含义即“非dynamic class”。只不过并没有sealed这个关键词(AS3中,类默认就是sealed的)。注意,在AS2中,“骨子里”是没有sealed class的!在run-time时,所有的AS2代码都变成了AS1的语法,sealed class无从说起了。可以说这是AS3的一个新产物。更多相关内容可以参见:http://as3blog.com/as3/as3tip-take-care-of-resource


六、关于继承(extends)和override
继承其实并不太复杂,唯一要说明的就是:子类的构造函数一定要用“super”调用一次父类的构造函数,否则报错!对于继承后的子类,如果要重新定义父类的非private方法,必须使用override关键词。在override的时候,如果我们需要调用父类的方法,可以使用super关键词(由于继承方法在逻辑上与父类往往有相似性,因此没有必要把方法逻辑完全重写)官方帮助中的这个例子非常易懂:
package {
import flash.display.MovieClip;
public class SuperExample extends MovieClip
{
public function SuperExample()
{
var myExt:Extender = new Extender()
trace(myExt.thanks()); // output: Mahalo nui loa
}
}
}


class Base {
public function thanks():String
{
return “Mahalo”;
}
}


class Extender extends Base
{
override public function thanks():String
{
return super.thanks() + ” nui loa”;
}
}


override不能用于重载变量(成员属性)。但是却可以用于重写getter和setter函数,例如:(官方帮助的例子)
package
{
import flash.display.MovieClip;
public class OverrideExample extends MovieClip
{
public function OverrideExample()
{
trace(currentLabel)
}
override public function get currentLabel():String
{
var str:String = “Override: “;
str += super.currentLabel;
return str;
}
}
}
这个例子中,我们直接重写了MovieClip类的currentLabel属性。注意调用父类属性的时候,用了super.currentLabel。
关于静态方法,比较麻烦。首先,静态方法是无法被重载的。必须通过类来访问。但是您也可以自己定义与静态方法同名的方法,我把官方的例子做了一下修改就一目了然了:
package
{
import flash.display.MovieClip;
public class StaticExample extends MovieClip
{
public function StaticExample()
{
var myExt:Extender = new Extender();
}
}
}


class Base {
public static var test:String = “static”;
}


class Extender extends Base
{
private var test:String = “instance”;
public function Extender()
{
trace(Base.test); // output: static
trace(test); //added by awflasher.com, output: instance
}
}
七、关于import语法
在AS2时代,“import”语法只是为了让编程时代码简洁(省去了包名),比如我们import了mx.transitions.Tween之后,就可以直接new Tween()了。而如果不import,我们也可以直接用全类名来构造实例,例如:
new mx.transitions.Tween();
然而,在AS3中,无论是否采用全名类声明,只要你用到这个类,就必须import。
import估计是传统Flash程序员所需要养成的一个最大的习惯,在刚切入AS3开发平台的时候,我常常忘记import一些常用的类,例如从IDE指向过来的文本和渲染元件,以及flash.event.*、flash.display.StageAlign等比较泛用的类。
AS3中不像AS2那样,我们不能用_root和Stage[”displayState”]来进行hacks了。(参见上面“五-关于 dynamic”)


八、关于编译时的注意事项
AS3不再像AS2那样简单地Complie-Time(编译时,即FlashCS3/FlexBuidler/其他编译器发布ActionScript及所有资源为SWF文件的那一时刻)进行类型检测了,AS3在Run-Time(运行时,级Flashplayer或者其他播放SWF的软件在播放SWF的时候)也有类型检测,因此AS2的Hacks(强制访问不能访问的属性)将不再有效。


九、一个不得不说的好消息
AS3中类所有的变量(属性)和函数(方法)的作用域都是运行时跟类/实例走的。这与AS2大有不同,我们不再需要去Delegate了。只要是类自己的方法,在调用的过程中,this永远指向类自己(实例)。


简要总结:
1、如果我需要属性公开,并且可以被自己的子类继承,那么定义成public的。子类也可重写(override)之。
2、如果我需要属性隐藏,但是可以被自己的子类继承,那么定义成protected的。与public类似,子类也可重写(override)之。
3、如果我的某一个类有一个属性不想在任何位置可见,包括其子类,那么定义为private的。其子类无需重写(override),因为它根本就不存在于子类中。


Collection of open source Flex 2 Projects


While was on Flex 2 beta 3, I did myself some little and basic projects for flex 2, if you are instresting in see them it’s a total of 25 projects with all source avaible. the total ammount of file it’s up to 80MB.


Here’s the link : Download it


Feel free to comment.


Removing HTML tags using mysql

Try this (ported from a T-SQL func by Robert Davis):


SET GLOBAL log_bin_trust_function_creators=1;
DROP FUNCTION IF EXISTS fnStripTags;
DELIMITER |
CREATE FUNCTION fnStripTags( Dirty varchar(4000) )
RETURNS varchar(4000)
DETERMINISTIC
BEGIN
  DECLARE iStart, iEnd, iLength int;
    WHILE Locate( ‘<‘, Dirty ) > 0 And Locate( ‘>’, Dirty, Locate( ‘<‘, Dirty )) > 0 DO
      BEGIN
        SET iStart = Locate( ‘<‘, Dirty ), iEnd = Locate( ‘>’, Dirty, Locate(‘<‘, Dirty ));
        SET iLength = ( iEnd – iStart) + 1;
        IF iLength > 0 THEN
          BEGIN
            SET Dirty = Insert( Dirty, iStart, iLength, ”);
          END;
        END IF;
      END;
    END WHILE;
    RETURN Dirty;
END;
|
DELIMITER ;
SELECT fnStripTags(‘this <html>is <b>a test</b>, nothing more</html>’);


Exploring Mysql CURDATE and NOW. The same but different.


Sometimes I see people attempting to use VARCHARS or CHARS to store dates in their MySQL database application. This is really fighting against MySQL, which has a variety of interchangeable date types. Internally MySQL is storing dates as numbers, which allows it to do all sorts of nice arithmetic and comparisons with very little effort on your part. For example, when you use a mysql DATE column to store a date, you don’t have to worry about sortation, or comparing that date to another DATE, because MySQL already understands how to do those things internally. A lot of people also don’t realize that they can output a DATE column in just about any way they choose using the DATE_FORMAT function. This causes people to shy away from using DATE, DATETIME, TIME, or TIMESTAMP columns, when they really should.


We can break down mysql DATE columns into 3 categories:

DATE: Has no Time component.

DATETIME and TIMESTAMP: Has both Date and Time component.

TIME: Has only Time component.


I tend to use DATETIME most often, and occassionally will use TIMESTAMP. I’ll talk about TIMESTAMP another day, and explain the pros and cons of using it.

In this entry I’m going to concentrate on two very important MySQL date functions: CURDATE() and NOW(). Take a look at these examples, and keep in mind that the semicolons are added to terminate the SQL statements as you would have to if you were using the mysql client application. If you’re using phpMyAdmin you don’t need the semicolons.


SELECT CURDATE();



CODE:

+————+
| CURDATE()  |
+————+
| 2004-11-30 |
+————+
1 row in set (0.00 sec)


CURDATE() returns you the date part of the mysql server’s datetime. The server gets this from the operating system, so basically it’s whatever the Date/Time is on the machine that is running your mysql server.

Notice that CURDATE() as its name implies has no TIME component. Let’s assume that what your application needs to do is find out what date it was “yesterday”. If Time really isn’t important, then CURDATE is the way to go, as it’s not concerned with TIME.

Although it’s not that intuitive, the way to get “YESTERDAY” is to use the DATE_ADD() function. The INTERVAL component allows us to Add a -1 DAY


SELECT DATE_ADD(CURDATE(), INTERVAL1 DAY);



CODE:

+————————————–+
| DATE_ADD(CURDATE(), INTERVAL -1 DAY) |
+————————————–+
| 2004-11-29                           |
+————————————–+
1 row in set (0.00 sec)


This is not to say that you can’t then use the DATE to compare against a DATETIME. You can! What happens is that mysql assumes for comparison purposes that your DATE is the equivalent to the “first second of that day” or that day at 12:00 am.

This little experiment illustrates the idea.


CODE:

mysql> create table onedate (onedate DATETIME);
Query OK, 0 rows affected (0.00 sec)

mysql> insert into onedate VALUES(NOW());
Query OK, 1 row affected (0.00 sec)

mysql> select * from onedate where onedate >= CURDATE();
+———————+
| onedate             |
+———————+
| 2004-11-30 17:52:01 |
+———————+
1 row in set (0.00 sec)


Notice that a row was returned, because CURDATE() will always be less than or equal to NOW().

Compare CURDATE() with NOW(). Like CURDATE(), NOW() returns you the system DATE but also includes the time component. If you need TIME in your application, tracking logins, or the date and time a message was entered by a user, then you need a mysql DATETIME rather than a MYSQL date, or you will not be able to capture the important time component.


SELECT * FROM onedate WHERE onedate >= CURDATE();



CODE:

+———————+
| NOW()               |
+———————+
| 2004-11-30 18:00:34 |
+———————+
1 row in set (0.00 sec)


Notice the 24 Hour time component.

Putting a nail in the issue, here’s the same DATE_ADD function called against NOW().


SELECT NOW(), DATE_ADD(NOW(), INTERVAL1 DAY);



CODE:

+———————+———————————-+
| NOW()               | DATE_ADD(NOW(), INTERVAL -1 DAY) |
+———————+———————————-+
| 2004-11-30 18:07:17 | 2004-11-29 18:07:17              |
+———————+———————————-+
1 row in set (0.00 sec)


What we get is exactly the same time, yesterday.

The intrinsic DATE types in a relational database are always the way to go when you need to handle date and time in your application. Let the database do the heavy lifting, and you will make your application faster, more reliable and easier to maintain in the long run.

flex2 License key

flex2 License

Flex License:
1307-1581-4356-2616-4951-7949 (Commercial Version)
1307-1581-4356-2939-1231-4484 (Education Version)

Charting License:

1301-4581-4356-7349-9369-3351 (Commercial Version)