Mozilla不仅是一个很好的浏览器,而且还是一个很不错的Flash播放器,尤其是它对中文的良好支持可以省去很多麻烦,见图1所示。在Red Hat中,Mollzia作为默认的浏览器,要想使其播放Flash动画,还必需安装一个Linux Mozilla插件。

    1.Linux Mozilla插件的下载

    下载网址为

     http://www.macromedia.com/shockwave/download/alternates/

     请选择相应的版本。

     2.Linux Mozilla插件的安装

   (1)解压文件包:

   [root@localhost Download]#tar zxvf flash_Linux.tar.gz;

   (2)复制文件插件到Mozilla的插件目录:

   将解压后的文件内的这两个文件
    /install_flash_player_7_linux/flashplayer.xpt
    /install_flash_player_7_linux/libflashplayer.so
    复制到
    /usr/lib/mozilla-1.2.1/plugins/   和    /usr/lib/mozilla/plugins/   内即可
  (以上方法仅供参考/测试环境:Red Hat 9)

   命令:[root@localhost install_flash_player_7_linux]  #cp flashplayer.xpt   /usr/lib/mozilla-1.2.1/plugins/

            [root@localhost install_flash_player_7_linux]  #cp libflashplayer.so   /usr/lib/mozilla/plugins/
create table index_analyse_xiangdong select * from relation limit 21000;

一、什么是索引?

索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存。如果没有索引,执行查询时MySQL必须从第一个记录开始扫描整个表的所有记录,直至找到符合要求的记录。表里面的记录数量越多,这个操作的代价就越高。如果作为搜索条件的列上已经创建了索引,MySQL无需扫描任何记录即可迅速得到目标记录所在的位置。如果表有1000个记录,通过索引查找记录至少要比顺序扫描记录快100倍。

假设我们创建了一个名为people的表:


CREATE TABLE people ( peopleid SMALLINT NOT NULL, name CHAR(50) NOT NULL );


然后,我们完全随机把1000个不同name值插入到people表。下图显示了people表所在数据文件的一小部分:




可以看到,在数据文件中name列没有任何明确的次序。如果我们创建了name列的索引,MySQL将在索引中排序name列:




对于索引中的每一项,MySQL在内部为它保存一个数据文件中实际记录所在位置的“指针”。因此,如果我们要查找name等于“Mike”记录的peopleid(SQL命令为“SELECT peopleid FROM people WHERE name='Mike';”),MySQL能够在name的索引中查找“Mike”值,然后直接转到数据文件中相应的行,准确地返回该行的peopleid(999)。在这个过程中,MySQL只需处理一个行就可以返回结果。如果没有“name”列的索引,MySQL要扫描数据文件中的所有记录,即1000个记录!显然,需要MySQL处理的记录数量越少,则它完成任务的速度就越快。

二、索引的类型

  MySQL提供多种索引类型供选择:


普通索引
这是最基本的索引类型,而且它没有唯一性之类的限制。普通索引可以通过以下几种方式创建:
创建索引,例如CREATE INDEX <索引的名字> ON tablename (列的列表);
修改表,例如ALTER TABLE tablename ADD INDEX [索引的名字] (列的列表);
创建表的时候指定索引,例如CREATE TABLE tablename ( [...], INDEX [索引的名字] (列的列表) );

唯一性索引
这种索引和前面的“普通索引”基本相同,但有一个区别:索引列的所有值都只能出现一次,即必须唯一。唯一性索引可以用以下几种方式创建:
创建索引,例如CREATE UNIQUE INDEX <索引的名字> ON tablename (列的列表);
修改表,例如ALTER TABLE tablename ADD UNIQUE [索引的名字] (列的列表);
创建表的时候指定索引,例如CREATE TABLE tablename ( [...], UNIQUE [索引的名字] (列的列表) );

主键
主键是一种唯一性索引,但它必须指定为“PRIMARY KEY”。如果你曾经用过AUTO_INCREMENT类型的列,你可能已经熟悉主键之类的概念了。主键一般在创建表的时候指定,例如“CREATE TABLE tablename ( [...], PRIMARY KEY (列的列表) ); ”。但是,我们也可以通过修改表的方式加入主键,例如“ALTER TABLE tablename ADD PRIMARY KEY (列的列表); ”。每个表只能有一个主键。

全文索引
MySQL从3.23.23版开始支持全文索引和全文检索。在MySQL中,全文索引的索引类型为FULLTEXT。全文索引可以在VARCHAR或者TEXT类型的列上创建。它可以通过CREATE TABLE命令创建,也可以通过ALTER TABLE或CREATE INDEX命令创建。对于大规模的数据集,通过ALTER TABLE(或者CREATE INDEX)命令创建全文索引要比把记录插入带有全文索引的空表更快。本文下面的讨论不再涉及全文索引,要了解更多信息,请参见MySQL documentation。
三、单列索引与多列索引

索引可以是单列索引,也可以是多列索引。下面我们通过具体的例子来说明这两种索引的区别。假设有这样一个people表:


CREATE TABLE people ( peopleid SMALLINT NOT NULL AUTO_INCREMENT, firstname CHAR(50) NOT NULL, lastname CHAR(50) NOT NULL, age SMALLINT NOT NULL, townid SMALLINT NOT NULL, PRIMARY KEY (peopleid) );


下面是我们插入到这个people表的数据:




这个数据片段中有四个名字为“Mikes”的人(其中两个姓Sullivans,两个姓McConnells),有两个年龄为17岁的人,还有一个名字与众不同的Joe Smith。

这个表的主要用途是根据指定的用户姓、名以及年龄返回相应的peopleid。例如,我们可能需要查找姓名为Mike Sullivan、年龄17岁用户的peopleid(SQL命令为SELECT peopleid FROM people WHERE firstname='Mike' AND lastname='Sullivan' AND age=17;)。由于我们不想让MySQL每次执行查询就去扫描整个表,这里需要考虑运用索引。

首先,我们可以考虑在单个列上创建索引,比如firstname、lastname或者age列。如果我们创建firstname列的索引(ALTER TABLE people ADD INDEX firstname (firstname);),MySQL将通过这个索引迅速把搜索范围限制到那些firstname='Mike'的记录,然后再在这个“中间结果集”上进行其他条件的搜索:它首先排除那些lastname不等于“Sullivan”的记录,然后排除那些age不等于17的记录。当记录满足所有搜索条件之后,MySQL就返回最终的搜索结果。

由于建立了firstname列的索引,与执行表的完全扫描相比,MySQL的效率提高了很多,但我们要求MySQL扫描的记录数量仍旧远远超过了实际所需要的。虽然我们可以删除firstname列上的索引,再创建lastname或者age列的索引,但总地看来,不论在哪个列上创建索引搜索效率仍旧相似。

为了提高搜索效率,我们需要考虑运用多列索引。如果为firstname、lastname和age这三个列创建一个多列索引,MySQL只需一次检索就能够找出正确的结果!下面是创建这个多列索引的SQL命令:



ALTER TABLE people ADD INDEX fname_lname_age (firstname,lastname,age);


由于索引文件以B-树格式保存,MySQL能够立即转到合适的firstname,然后再转到合适的lastname,最后转到合适的age。在没有扫描数据文件任何一个记录的情况下,MySQL就正确地找出了搜索的目标记录!

那么,如果在firstname、lastname、age这三个列上分别创建单列索引,效果是否和创建一个firstname、lastname、age的多列索引一样呢?答案是否定的,两者完全不同。当我们执行查询的时候,MySQL只能使用一个索引。如果你有三个单列的索引,MySQL会试图选择一个限制最严格的索引。但是,即使是限制最严格的单列索引,它的限制能力也肯定远远低于firstname、lastname、age这三个列上的多列索引。

四、最左前缀

多列索引还有另外一个优点,它通过称为最左前缀(Leftmost Prefixing)的概念体现出来。继续考虑前面的例子,现在我们有一个firstname、lastname、age列上的多列索引,我们称这个索引为fname_lname_age。当搜索条件是以下各种列的组合时,MySQL将使用fname_lname_age索引:


firstname,lastname,age
firstname,lastname
firstname
从另一方面理解,它相当于我们创建了(firstname,lastname,age)、(firstname,lastname)以及(firstname)这些列组合上的索引。下面这些查询都能够使用这个fname_lname_age索引:



SELECT peopleid FROM people WHERE firstname='Mike' AND lastname='Sullivan' AND age='17'; SELECT peopleid FROM people WHERE firstname='Mike' AND lastname='Sullivan'; SELECT peopleid FROM people WHERE firstname='Mike'; The following queries cannot use the index at all: SELECT peopleid FROM people WHERE lastname='Sullivan'; SELECT peopleid FROM people WHERE age='17'; SELECT peopleid FROM people WHERE lastname='Sullivan' AND age='17';


五、选择索引列

在性能优化过程中,选择在哪些列上创建索引是最重要的步骤之一。可以考虑使用索引的主要有两种类型的列:在WHERE子句中出现的列,在join子句中出现的列。请看下面这个查询:



SELECT age ## 不使用索引 FROM people WHERE firstname='Mike' ## 考虑使用索引 AND lastname='Sullivan' ## 考虑使用索引


这个查询与前面的查询略有不同,但仍属于简单查询。由于age是在SELECT部分被引用,MySQL不会用它来限制列选择操作。因此,对于这个查询来说,创建age列的索引没有什么必要。下面是一个更复杂的例子:



SELECT people.age, ##不使用索引 town.name ##不使用索引 FROM people LEFT JOIN town ON people.townid=town.townid ##考虑使用索引 WHERE firstname='Mike' ##考虑使用索引 AND lastname='Sullivan' ##考虑使用索引


与前面的例子一样,由于firstname和lastname出现在WHERE子句中,因此这两个列仍旧有创建索引的必要。除此之外,由于town表的townid列出现在join子句中,因此我们需要考虑创建该列的索引。

那么,我们是否可以简单地认为应该索引WHERE子句和join子句中出现的每一个列呢?差不多如此,但并不完全。我们还必须考虑到对列进行比较的操作符类型。MySQL只有对以下操作符才使用索引:<,<=,=,>,>=,BETWEEN,IN,以及某些时候的LIKE。可以在LIKE操作中使用索引的情形是指另一个操作数不是以通配符(%或者_)开头的情形。例如,“SELECT peopleid FROM people WHERE firstname LIKE 'Mich%';”这个查询将使用索引,但“SELECT peopleid FROM people WHERE firstname LIKE '%ike';”这个查询不会使用索引。

六、分析索引效率

现在我们已经知道了一些如何选择索引列的知识,但还无法判断哪一个最有效。MySQL提供了一个内建的SQL命令帮助我们完成这个任务,这就是EXPLAIN命令。EXPLAIN命令的一般语法是:EXPLAIN 。你可以在MySQL文档找到有关该命令的更多说明。下面是一个例子:



EXPLAIN SELECT peopleid FROM people WHERE firstname='Mike' AND lastname='Sullivan' AND age='17';


这个命令将返回下面这种分析结果:


table type possible_keys key key_len ref rows Extra
people ref fname_lname_age fname_lname_age 102 const,const,const 1 Where used

下面我们就来看看这个EXPLAIN分析结果的含义。


table:这是表的名字。
type:连接操作的类型。下面是MySQL文档关于ref连接类型的说明:

“对于每一种与另一个表中记录的组合,MySQL将从当前的表读取所有带有匹配索引值的记录。如果连接操作只使用键的最左前缀,或者如果键不是UNIQUE或PRIMARY KEY类型(换句话说,如果连接操作不能根据键值选择出唯一行),则MySQL使用ref连接类型。如果连接操作所用的键只匹配少量的记录,则ref是一种好的连接类型。”

在本例中,由于索引不是UNIQUE类型,ref是我们能够得到的最好连接类型。

如果EXPLAIN显示连接类型是“ALL”,而且你并不想从表里面选择出大多数记录,那么MySQL的操作效率将非常低,因为它要扫描整个表。你可以加入更多的索引来解决这个问题。预知更多信息,请参见MySQL的手册说明。

possible_keys:
可能可以利用的索引的名字。这里的索引名字是创建索引时指定的索引昵称;如果索引没有昵称,则默认显示的是索引中第一个列的名字(在本例中,它是“firstname”)。默认索引名字的含义往往不是很明显。

Key:
它显示了MySQL实际使用的索引的名字。如果它为空(或NULL),则MySQL不使用索引。

key_len:
索引中被使用部分的长度,以字节计。在本例中,key_len是102,其中firstname占50字节,lastname占50字节,age占2字节。如果MySQL只使用
    前些日子,突然接到表妹打来电话,我想都好久没有联系了,难道是有什么事情要请我帮忙,以前在想要是有能力后, 一定让我表妹来北京给她找份工作,在我心中表妹是很聪明伶俐的,从小学一块上学比我低一个年级之外,而到后来,我到了县里念书后,除了寒假暑期回家外,就很少和她见面了,还记得小时候到外婆家,老是留恋不想回家,不就是有她在嘛,但时光就是那样的催人,转眼间我初中毕业,那时她成绩也不错,本来我是想让她和我一样读个高中(说实话当时也就想永无休止的学完初中就考个师范得了,也是我父母的想法,但那年不招师范了,得等下年,在初中班主任老师的游说下,考了高中,也上了高中,成绩也相当不错),没想到她由于种种原因就读了个中专,到现在还在福州打工,今天突然接到她电话:
第一句话是:哥,你现在上班了没得呀?
我很急忙回答道:5月份都开始上班了啦,当时给你说你还不相信
。。。。。。。。。。
突然,她话题一转说:
哥,我想给你说个事情
我问:什么事情?
她问我过年回家不?
一想到回家,又要说道自己大学几年,一直没有回家,唏嘘的感慨一年年。
不能怪谁,怪得怪自己,过年本来到杭州了,但是还是没有和妈妈一块回去,这里面一是自己二还是自己的情况,我很相信成也它,败也它、、、
最后一直在想这个是怎么回事呀,难道想我回去找我玩,但从她口气上说的是,过年回来耍,我们 那边回来耍是有另外一件含意在里面的,最后呢,我说有啥事呢?她回答道回来耍嘛。我越听糊涂,呵呵
最后在我的
在论坛里看了许多相关帖子,自己也实验了多次,终于在前几天测试成功,感谢cu里的前辈们为我们新人铺路,因为我实际工作中要用到这些,以前是兄弟公司的哥们帮我们配置。现在我也配置成功,和大家分享一下成果吧。一直从cu里吸取精华,希望我的文档能给一些新人有帮助。
  说明:实现WEB服务器能运行html、php、jsp等格式文件

一、 所用软件及版本
1、 操作系统:RHEL as4u3
2、 Apache:httpd-2.2.2.tar.gz
apr-util-1.2.7.tar.gz
apr-1.2.7.tar.gz
3、 Tomcat:apache-tomcat-5.5.15.tar.gz
4、 Mysql:mysql-5.0.22.tar.gz
5、 Jdk:jdk-1_5_0_07-linux-i586.bin
6、 Apache和Tomcat连接:tomcat-connectors-1.2.18-src.tar.gz
7、 Php: php-5.1.4.tar.gz
二、 安装步骤:
1、 安装操作系统:这里就不介绍了,主要将相关的开发包装上。我将所有开发包都安装了。
2、 Apache安装:将以上所需要的所有软件上传到/usr/local下。
先解压:
tar xvfz httpd-2.2.2.tar.gz
cd httpd-2.2.2

首先可以看看里面的安装说明INSTALL和README。
在安装apache之前先安装apr-util-1.2.7.tar.gz和apr-1.2.7.tar.gz
首先安装apr。

tar xvfz apr-1.2.7.tar.gz
cd apr-1.2.7
./configure --prefix=/usr/local/apr-httpd
make
make install
cd ..

再安装apr-util-1.2.7.tar.gz

tar xvfz apr-util-1.2.7.tar.gz
cd apr-util-1.2.7
./configure --prefix=/usr/local/apr-util-httpd --with-apr=/usr/local/apr-httpd
make
make install

3、 接下来继续安装apache

cd ../httpd-2.2.2
./configure --prefix=/usr/local/apache --enable-mods-shared=all --enable-module=most --with-apr=/usr/local/apr-httpd --with-apr-util=/usr/local/apr-util-httpd --enable-so
make
make install

如果没有报错,apache基本安装完毕。
4、 安装JDK
回到local目录下:

cd ..
./jdk-1_5_0_07-linux-i586.bin
ln –s jdk1.5.0_07 jdk

设置JDK环境变量

vi /etc/profile

再文件尾部增加以下几句:

JAVA_HOME=/usr/local/jdk
JRE=$JAVA_HOME/jre
LC_ALL=zh_CN.GBK
PATH=$JAVA_HOME/bin:$JRE/bin:$PATH
CLASSPATH=.:$JAVA_HOME/bin/tools.jar:$JAVA_HOME/lib/dt.jar
export JAVA_HOME JRE LC_ALL CLASSPATH PATH


5、 安装MYSQL

tar xvfz mysql-5.0.22.tar.gz
cd mysql-5.0.22
./configure --prefix=/usr/local/mysql/ --with-unix-socket-path=/usr/local/mysql/tmp/mysql.sock --with-client-ldflags=-all-static --with-mysqld-ldflags=-all-static --enable-assembler
make
make install
groupadd mysql
useradd -g mysql mysql
cp support-files/my-medium.cnf /etc/my.cnf
cd /usr/local/mysql
bin/mysql_install_db --user=mysql
chown -R root  .
chown -R mysql var
chgrp -R mysql .
bin/mysqld_safe --user=mysql &
mysqladmin –uroot password new-password

6、 安装php

tar xvfz php-5.1.4.tar.gz
cd php-5.1.4
./configure --prefix=/usr/local/php --with-mysql=/usr/local/mysql --with-apxs2=/usr/local/apache/bin/apxs
make && make install
cp php.ini-dist /usr/local/lib/php.ini

7、 安装tomcat

tar xvfz apache-tomcat-5.5.15.tar.gz
mv apache-tomcat-5.5.15 tomcat

8、 安装Apache和Tomcat连接

tar zxvf tomcat-connectors-1.2.18-src.tar.gz
cd tomcat-connectors-1.2.18-src/ native/
./configure --with-apxs=/usr/local/apache/bin/apxs
make && make install

三、 配置httpd.conf

cd /usr/local/conf/
vi httpd.conf

1、 注释掉一下几行

#ServerAdmin you@example.com
#ServerName www.example.com:80
#DocumentRoot "/usr/local/apache/htdocs"

2、 修改里面相关内容
A、

   Options FollowSymLinks
#    AllowOverride None
    AllowOverride all
    Order deny,allow
#    Deny from all
    Allow from all


B、
#

   #
   # Possible values for the Options directive are "None", "All",
   # or any combination of:
   #   Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
   #
   # Note that "MultiViews" must be named *explicitly* --- "Options All"
   # doesn't give it to you.
   #
   # The Options directive is both complicated and important.  Please see
   # http://httpd.apache.org/docs/2.2/mod/core.html#options
   # for more information.
   #
#    Options Indexes FollowSymLinks
   #
   # AllowOverride controls what directives may be placed in .htaccess files.
   # It can be "All", "None", or any combination of the keywords:
   #   Options FileInfo AuthConfig Limit
   #
   AllowOverride None

   #
   # Controls who can get stuff from this server.
   #
   Order allow,deny
   Allow from all



因为我这里将网站放在/usr/local/tomcat/webapps下

C、将
#Include conf/extra/httpd-vhosts.conf
这行#除掉

3、 增加以下内容:
A、在AddType application/x-gzip .gz .tgz下增加以下两行

AddType application/x-httpd-php .php .phtml
  AddType application/x-httpd-php-source .phps

B、结尾增加

#add mod_jk module
LoadModule jk_module modules/mod_jk.so
# Update this path to match your modules location
# Where to find workers.properties
# Update this path to match your conf directory location (put workers.properties next to #httpd.conf)
 JkWorkersFile /usr/local/apache/conf/workers.properties
# Where to put jk logs
# Update this path to match your logs directory location (put mod_jk.log next to access_log)
 JkLogFile     /usr/local/apache/logs/mod_jk.log
# Set the jk log level [debug/error/info]
 JkLogLevel    info
# Select the log format
 JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
# JkOptions indicate to send SSL KEY SIZE,
 JkOptions     +ForwardKeySize +ForwardURICompat -ForwardDirectories
# JkRequestLogFormat set the request format
 JkRequestLogFormat     "%w %V %T"
# Send everything for context /examples to worker named worker1 (ajp13)
 JkMount  /*.jsp worker1


C、在/usr/local/apache/conf下增加一个workers.properties文件,内容如下:

# Define 1 real worker using ajp13
 worker.list=worker1
# Set properties for worker1 (ajp13)
 worker.worker1.type=ajp13
 worker.worker1.host=localhost
 worker.worker1.port=8009
 worker.worker1.lbfactor=50
 worker.worker1.cachesize=10
 worker.worker1.cache_timeout=600
 worker.worker1.socket_keepalive=1
 worker.worker1.reclycle_timeout=300

D、再编辑/usr/local/apache/conf/extra/下httpd-vhosts.conf文件

vi httpd-vhosts.conf

将里面例子修改一下



DirectoryIndex index.htm index.html index.jsp index.php

   ServerAdmin xxx@126.com
   DocumentRoot /usr/local/tomcat/webapps/ROOT
   ServerName 192.168.0.170
   ErrorLog logs/170-error_log
   CustomLog logs/170-access_log common


因为没有做域名解析,我这里在ServerName下直接用的是IP地址。
四、 测试
先启动tomcat,再启动apache。启动apache之前可以到apache/bin下测试一下虚拟域是否配置正确。./httpd –S 如果配置有错误会提示你。
没有问题后,在IE地址栏输入http://192.168.0.170 此时将显示的是tomcat的默认界面,证明可以正常访问jsp文件了。再将/usr/local/tomcat/webapps/ROOT下index.jsp换一个index.php文件,只要在index.php里输入以下内容即可测试:


重启apache,再在IE地址栏输入http://192.168.0.170 将能看到php的相关信息。
主要参考文章有:
http://www.chinaunix.net/jh/13/669895.html
http://www.chinaunix.net/jh/13/770898.html
http://httpd.apache.org/docs/2.2/
linux下安装php运行环境
Submitted by phpox on 2007, April 16, 12:44 PM. Linux

首先我在 /root 目录下建了一个 soft 文件夹来保存我要安装的源码包
mkdir /root/soft
cd /root/soft

先找到 apache php mysql proftpd 源码包下载的URL地址
请浏览
http://www.apache.org
http://www.php.net
http://www.mysql.com
http://www.proftpd.org/


第一步:安装apache
注:当前目录为/root/soft ,
目录下有
httpd-2.0.55.tar.gz, php-5.0.5.tar.gz
等二进制源码包
#号代表为root 根权限,#后是输入的一条命令

执行下列命令
解压源码包
# tar -zxf httpd-2.0.55.tar.gz
进入安装目录
# cd httpd-2.0.55
配置apache安装信息
# ./configure --prefix=/usr/local/apache --enable-modules=so --enable-rewrite
执行make安装
# make; make install
安装完后
# vi /usr/local/apache/conf/httpd.conf
找到 prefork.c 下的
MaxClients 150
改为
ServerLimit 2000
MaxClients 1000
apache默认工作在prefork.c模式下,并发进程为150,超过后就无法访问,150是远远不够的,所以这里按自己网站的需求改, 如1000
由于apache默认最大并发进程是 256 所以要先设置 ServerLimit 2000 将服务器可设的最大并发数设为2000, 然后再设置最大并发数 MaxClients 1000

找到 #ServerName www.example.com:80 在其下设置 ServerName 如下
ServerName www.mysite.com
基中 www.mysite.com 为你网站名,也可用IP代替
找到 DocumentRoot "/usr/local/apache/htdocs"
设置你的 WEB 服务器的根目录 如
DocumentRoot "/myweb"
找到 DirectoryIndex index.html index.html.var 改为
DirectoryIndex index.html index.php index.htm
找到 ForceLanguagePriority Prefer Fallback 在其下加上
AddDefaultCharset gb2312
改完后保存(vi 的用法请查 Linux vi 命令)
用下面命令启动WEB服务器
# /usr/local/apache/bin/apachectl start
查看自己的站点是否正常 http://www.mysite.com 也可用IP
用 # /usr/local/apache/bin/apachectl stop 可停止服务


安装MYSQL
# tar -zxf mysql-standard-5.0.15-linux-i686.tar.gz
# cp -r mysql-standard-5.0.15-linux-i686 /usr/local/mysql
# vi /usr/local/mysql/support-files/my-medium.cnf
在后面加上
max_connections = 1000
log-slow-queries
long_query_time = 5
注 max_connections 为允许的最大连接数
log-slow-queries 打开低速查询日志
long_query_time 低速查询的秒数(运行一句sql达到此时间记录在日志里)
然后COPY 它为 /etc/my.cnf 文件
# cp /usr/local/mysql/support-files/my-medium.cnf /etc/my.cnf
添加mysql用户及用户组
# groupadd mysql
# useradd -g mysql mysql
修改mysql目录权限
# chown -R root /usr/local/mysql
# chgrp -R mysql /usr/local/mysql
# chown -R mysql /usr/local/mysql/data
生成mysql系统数据库
# /usr/local/mysql/scripts/mysql_install_db --user=mysql&
启动mysql服务
# /usr/local/mysql/bin/mysqld_safe --user=mysql&
如出现 Starting mysqld daemon with databases from /usr/local/mysql/data
代表正常启动mysql服务了, 按Ctrl + C 跳出
修改 mysql 的 root 密码
# /usr/local/mysql/bin/mysqladmin -u root -p password 123456
回车出现 Enter password: 最开始密码默认为空 继续回车即可
123456 即为你的新密码

安装GD库(让PHP支持GIF,PNG,JPEG)
首先下载 jpeg6,libpng,freetype 并安装模块
wget http://www.ijg.org/files/jpegsrc.v6b.tar.gz
wget http://nchc.dl.sourceforge.net/sourceforge/libpng/libpng-1.2.8.tar.gz
wget http://keihanna.dl.sourceforge.net/sourceforge/freetype/freetype-2.1.10.tar.gz
wget http://www.boutell.com/gd/http/gd-2.0.33.tar.gz

安装 jpeg6
建立目录
# mkdir /usr/local/jpeg6
# mkdir /usr/local/jpeg6/bin
# mkdir /usr/local/jpeg6/lib
# mkdir /usr/local/jpeg6/include
# mkdir /usr/local/jpeg6/man
# mkdir /usr/local/jpeg6/man/man1
# cd /root/soft
# tar -zxf jpegsrc.v6b.tar.gz
# cd jpeg-6b
# ./configure --prefix=/usr/local/jpeg6/ --enable-shared --enable-static
# make; make install

安装libpng
# cd /root/soft
# tar -zxf libpng-1.2.8.tar.gz
# cd libpng-1.2.8
# cp scripts/makefile.std makefile
# make; make install

安装 freetype
# cd /root/soft
# tar -zxf freetype-2.1.10.tar.gz
# cd freetype-2.1.10
# ./configure --prefix=/usr/local/freetype
# make;make install

安装最新的GD库
# cd /root/soft
# tar -zxf gd-2.0.33.tar.gz
# cd gd-2.0.33
# ./configure --prefix=/usr/local/gd2 --with-jpeg=/usr/local/jpeg6/ --with-png --with-zlib --with-freetype=/usr/local/freetype/
# make; make install

安装最新的Curl库
# cd /root/soft
# wget http://curl.haxx.se/download/curl-7.15.0.tar.gz
# tar -zxf curl-7.15.0.tar.gz
# ./configure --prefix=/usr/local/curl
# make; make install

安装PHP

由于php5需libxml2的支持, 所以先下载并安装libxml2
# cd /root/soft
# wget http://ftp.gnome.org/pub/GNOME/sources/libxml2/2.6/libxml2-2.6.19.tar.gz
# tar -zxf libxml2-2.6.19.tar.gz
# cd libxml2-2.6.19
# ./configure --prefix=/usr/local/libxml2
# make; make install

安装 libxslt
# cd /root/soft
# wget http://ftp.gnome.org/pub/GNOME/sources/libxslt/1.1/libxslt-1.1.15.tar.gz
# tar -zxf libxslt-1.1.15.tar.gz
# cd libxslt-1.1.15
# ./configure --prefix=/usr/local/libxslt --with-libxml-prefix=/usr/local/libxml2
# make; make install

# tar -zxf php-5.0.5.tar.gz
# cd php-5.05
# ./configure --prefix=/usr/local/php --with-apxs2=/usr/local/apache/bin/apxs --with-mysql=/usr/local/mysql/ --with-curl=/usr/local/curl --enable-ftp --with-libxml-dir=/usr/local/libxml2 --with-expat-dir=/usr/lib --enable-soap --with-xsl=/usr/local/libxslt --enable-xslt --with-gd=/usr/local/gd2/ --with-jpeg-dir=/usr/local/jpeg6/ --with-zlib-dir=/usr/lib --with-png --with-freetype-dir=/usr/local/freetype
# make
# make install

其中./configure 后的
--prefix=/usr/local/php
--with-apxs2=/usr/local/apache/bin/apxs
--with-mysql=/usr/local/mysql/
--with-libxml-dir=/usr/local/libxml2
是必要的选项

--with-gd=/usr/local/gd2/
--with-jpeg-dir=/usr/local/jpeg6/
--with-png
--with-zlib-dir=/usr/lib
--with-freetype-dir=/usr/local/freetype
这是让PHP支持GD库的配置选项

--with-curl=/usr/local/curl 支持CURL库
--enable-ftp 打开FTP库函数支持

--enable-soap --with-xsl=/usr/local/libxslt --enable-xslt
让PHP支持SOAP, 上面这些一般用得少, 可以去掉

配置 httpd.conf 让apache支持PHP
# vi /usr/local/apache/conf/httpd.conf
找到 AddType application/x-gzip .gz .tgz 在其下添加如下内容
AddType application/x-httpd-php .php
AddType application/x-httpd-php-source .phps

重启apache
# /usr/local/apache/bin/apachectl restart
在你Web目录里建一内容为 PHP文件, 输入URL地址查看PHP配置是否正确


安装 phpmyadmin
下载
# cd /root/soft
# wget http://nchc.dl.sourceforge.net/sourceforge/phpmyadmin/phpMyAdmin-2.6.4-pl3.tar.gz
# tar -zxf phpMyAdmin-2.6.4-pl3.tar.gz
# vi phpMyAdmin-2.6.4-pl3/config.inc.php
找到 $cfg['Servers'][$i]['auth_type'] = 'config'; 将config 改为 http
保存后
mv phpMyAdmin-2.6.4-pl3 /你的phpmyadmin目录
关于mysql4.1-4移植4.0旧数据库中文乱码问题的解决方法
进入phpmyadmin管理
建立你数据库名并选上 gb2312_bin 的编码
然后导入你先前备份好的SQL文件, 导入时选择 文件的字符集:gb2312
完成后就OK了
注: PHP连接mysql4.1和5.0 数据库后需指定字符集 需执行如 mysql_query("SET NAMES 'gb2312' ");
否则会产生中文乱码问题!
如何修改MYSQL数据库,数据表,字段的编码(解决JSP乱码)

要解决JSP乱码,首先就要了解JSP乱码的原因

1.架设服务器安装MYSQL时的会让你选择一种编码,如果这种编码与你的网页不一致,可能就会造成JSP页面乱码
2.在PHPMYADMIN或mysql-front等系统 创建数据库时会让你选择一种编码,如果这种编码与你的网页不一致,也有可能造成JSP页面乱码
3.创建表时会让你选择一种编码,如果这种编码与你的网页编码不一致,也可能造成JSP页面乱码
4.创建表时添加字段是可以选择编码的,如果这种编码与你的网页编码不一致,也可能造成JSP页面乱码
5.用户提交JSP页面的编码与显示数据的JSP页面编码不一致,就肯定会造成JSP页面乱码.
如用户输入资料的JSP页面是big5码, 显示用户输入的JSP页面却是gb2312,这种100%会造成JSP页面乱码
6.字符集不正确
要注意:
1.平时你在某些网站看到的文字可能有几种编码, 如你看到一个繁体字,它有可能是big5编码,也有 可能是utf-8编码的,更有可能是gb码的,没错,也就是说有简体编码的繁体字,也有繁体编码的简体字,一定要了解这一点.
如果你是做一个简体编码的网页,编码定为GB2312,如果有香港和台湾地区的访客提交繁体的信息,就可能会造成乱码,解决方法就是(1)将网站编码设为utf-8,这样可以兼容世界上所有字符, (2)如果网站已经运作了好久,已有很多旧数据,不能再更改简体中文的设定,那么建议将页面的编码设为GBK,
GBK与GB2312的区别就在于:GBK能比GB2312显示更多的字符,要显示简体码的繁体字,就只能用GBK
7.JSP连接MYSQL数据库语句指定的编码不正确
8.JSP页面没有指定数据提交的编码,就会造成乱码:

所以,JSP乱码的原因无非就是以上几种,知道原因之后,要解决JSP乱码的方法也容易多了
我们一一来表达:
1.如果安装mysql的编码已不能更改,很多朋友是购买虚拟主机建立网站,无权更改MYSQL的安装编码,这一关我们可以跳过,因为只要后面的步聚正确,一样能解决乱码问题
2.修改数据库编码,如果是数据库编码不正确: 可以在phpmyadmin 执行如下命令: ALTER DATABASE `test` DEFAULT CHARACTER SET utf8 COLLATE utf8_bin
以上命令就是将test数据库的编码设为utf8
3.修改表的编码:ALTER TABLE `category` DEFAULT CHARACTER SET utf8 COLLATE utf8_bin
以上命令就是将一个表category的编码改为utf8
4.修改字段的编码:
ALTER TABLE `test` CHANGE `dd` `dd` VARCHAR( 45 ) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL
以上命令就是将test表中 dd的字段编码改为utf8
5.如果是这种情况容易解决,只需检查下页面,修改源文件的charset即可
, //这个正确就无问题了
6.这种情况也是修改页面charset即可,
7.在JSP连接数据库的语句中,
private String url="jdbc:mysql://localhost/"+DB_NAME+" user="+LOGIN_NAME+"&password="+LOGIN_PASSWORD+"&characterEncoding=GBK"; //相键要看characterEncoding
8.这种乱码的情况,只需在页面开头加上request.setCharacterEncoding("GBK"); 指定提交的即可

注意:按照以上方法修改以后只能保证你新插入的数据不会乱码,举个例:如果你用户已提交的数据是BIG5,你却想通过以上方法改为可以在GB2312的网页正确显示是不可能的, 这种文字内码的变换只能通过另写程序来解决,请WEB745.com其它相关文章


总结:先要判断JSP乱码是插入数据库之后乱码,还是JSP页面刚提交过来就乱码了,如果JSP刚接收上一页面的数据显示就乱码了,肯定是字符集不对,可者没有加request.setCharacterEncoding("GBK");

如果是数据库的原因就参考上面的2,3,4种方法



以前偷工减料,到处乱抄东西,现在要几大原则同时进行:
1.不谈个人的情感
2.不谈私生活
3.不谈他人软肋
谈什么:
2.谈技术
3.谈生活

转载请注明 achieverain 找工作中
文章出处: http://php.cublog.cn
其实这并不是什么光彩的事,我原来所在的公司因为民营企业的死亡率最高的原因:资金链断裂而死亡。在近半年没有领到工资之后,终于在公司办公场所即将到期之前决定重新找份工作。
先自我介绍一下,我是一个开源CMS开发组的领导者和核心开发人员之一,开发了大约70%核心部分的代码。能够在linux下完成除图像处理以外的日常工作。我不敢说什么精通,但是至少该会的都会了。个人能力是:
PHP
XHTML + CSS
JAVAScript
C
shell阅读全文
周立功对人才的看法,想进周立功公司的应聘者必看。  2007年03月21日
阅读全文
<?php
class man{
var $sex="男";
var $heigh=1010;
var $weight;
function run(){
echo "I am run !";
}
function sleep($sexs){
echo "I am sleep";
$this->sex=$sexs;

}


}
?>

<?php
$xiangdong=new man();
$xiangdong->sleep(女);
echo "$xiangdong->sex";
echo "$xiangdong->heigh";
echo "$xiangdong->heigh";

echo "$xiangdong->run()--------------";

echo $xiangdong->sleep("男的啊");
$xiangdong->sex;

$serialize=serialize($xiangdong);
echo "序列化后的结果:<br> ";

echo $serialize;
echo " 开始反序列化:";

$unserialize=unserialize($serialize);

echo $unserialize->sex;
echo "<br>";
echo "$unserialize->sleep(\"男的a啊\")";
?>
example: select q.q_id from question as q where q.o_id not in (select answer.o_id from answer) order by q_id
               select count(*) from question as q where q.o_id not in (select answer.o_id from answer) and q.q_status!='del' order by q_id
user表:

id | name
———
1 | libk
2 | zyfon
3 | daodao

user_action表:

user_id | action
—————
1 | jump
1 | kick
1 | jump
2 | run
4 | swim

sql:
select id, name, action from user as u
left join user_action a on u.id = a.user_id

result:
id | name | action
——————————–
1 | libk | jump ①
1 | libk | kick ②
1 | libk | jump ③
2 | zyfon | run ④
3 | daodao | null ⑤

分析:
注意到user_action中还有一个user_id=4, action=swim的纪录,但是没有在结果中出现,
而user表中的id=3, name=daodao的用户在user_action中没有相应的纪录,但是却出现在了结果集中
因为现在是left join,所有的工作以left为准.
结果1,2,3,4都是既在左表又在右表的纪录,5是只在左表,不在右表的纪录

结论:
我们可以想象left join 是这样工作的
从左表读出一条,选出所有与on匹配的右表纪录(n条)进行连接,形成n条纪录(包括重复的行,如:结果1和结果3),
如果右边没有与on条件匹配的表,那连接的字段都是null.
然后继续读下一条。

引申:
我们可以用右表没有on匹配则显示null的规律, 来找出所有在左表,不在右表的纪录, 注意用来判断的那列必须声明为not null的。
如:
sql:
select id, name, action from user as u
left join user_action a on u.id = a.user_id
where a.user_id is NULL
(注意:1.列值为null应该用is null 而不能用=NULL
2.这里a.user_id 列必须声明为 NOT NULL 的)
result:
id | name | action
————————–
3 | daodao | NULL

——————————————————————————–

Tips:
1. on a.c1 = b.c1 等同于 using(c1)
2. INNER JOIN 和 , (逗号) 在语义上是等同的
3. 当 MySQL 在从一个表中检索信息时,你可以提示它选择了哪一个索引。
如果 EXPLAIN 显示 MySQL 使用了可能的索引列表中错误的索引,这个特性将是很有用的。
通过指定 USE INDEX (key_list),你可以告诉 MySQL 使用可能的索引中最合适的一个索引在表中查找记录行。
可选的二选一句法 IGNORE INDEX (key_list) 可被用于告诉 MySQL 不使用特定的索引。
4. 一些例子:
mysql> SELECT * FROM table1,table2 WHERE table1.id=table2.id;
mysql> SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id;
mysql> SELECT * FROM table1 LEFT JOIN table2 USING (id);
mysql> SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id
-> LEFT JOIN table3 ON table2.id=table3.id;
mysql> SELECT * FROM table1 USE INDEX (key1,key2)
-> WHERE key1=1 AND key2=2 AND key3=3;
mysql> SELECT * FROM table1 IGNORE INDEX (key3)
-> WHERE key1=1 AND key2=2 AND key3=3;

7.2.9. MySQL如何优化LEFT JOIN和RIGHT JOIN
在MySQL中,A LEFT JOIN B join_condition执行过程如下:

· 根据表A和A依赖的所有表设置表B。

· 根据LEFT JOIN条件中使用的所有表(除了B)设置表A。

· LEFT JOIN条件用于确定如何从表B搜索行。(换句话说,不使用WHERE子句中的任何条件)。

· 可以对所有标准联接进行优化,只是只有从它所依赖的所有表读取的表例外。如果出现循环依赖关系,MySQL提示出现一个错误。

· 进行所有标准WHERE优化。

· 如果A中有一行匹配WHERE子句,但B中没有一行匹配ON条件,则生成另一个B行,其中所有列设置为NULL。

· 如果使用LEFT JOIN找出在某些表中不存在的行,并且进行了下面的测试:WHERE部分的col_name IS NULL,其中col_name是一个声明为 NOT NULL的列,MySQL找到匹配LEFT JOIN条件的一个行后停止(为具体的关键字组合)搜索其它行。

RIGHT JOIN的执行类似LEFT JOIN,只是表的角色反过来。

联接优化器计算表应联接的顺序。LEFT JOIN和STRAIGHT_JOIN强制的表读顺序可以帮助联接优化器更快地工作,因为检查的表交换更少。请注意这说明如果执行下面类型的查询,MySQL进行全扫描b,因为LEFT JOIN强制它在d之前读取:

SELECT *
FROM a,b LEFT JOIN c ON (c.key=a.key) LEFT JOIN d ON (d.key=a.key)
WHERE b.key=d.key;阅读全文
同班的一个同学总是有很多丰富的问题,这些问题五花八门,但又别具一格,赏心悦目却又让人应接不暇.
这一次的问题是关于C语言的main主函数所带的参数问题,幸而下课时一旁的老师听见了,及时的帮我了个大忙,其实这个问题我也胡里胡涂.现在清楚多了.

每个应用程序后面都可以跟一些参数来控制程序初始化的状态.
看以下程序

程序代码
#include
void main(int argc, char *argv[])
{
int i;
for(i = 0; i < argc; i++)
printf("%s%s", argv[i], (i < argc - 1) ? " " : "");
printf("\n");
}


这个简单的程序什么都不干,只是将接收到的函数参数原原本本的打印出来,让我们看清楚我们的参数是如何被应用程序调用的.

int argc代表整形的传入的参数个数
char *argv[]代表指向传入的字符型参数地址的指针变量,通过访问这些指针,我们能得到传入的是什么

让我们输入一些参数来测试吧
切忌在命令行下进行操作,不然怎么加参数呢
什么?命令行是什么?
Windows NT/XP及以上用户运行cmd
Windows 98/Me及以下用户运行command(用这些操作系统的可以列为国家保护动物了)

命令行下直接输入程序名:我这里叫test(.exe)
程序返回的确实是所在磁盘路径D:\TURBOC2\WORKING\TEST.EXE
输入test 123
返回D:\TURBOC2\WORKING\TEST.EXE 123
这是一位在加拿大学computer science的朋友的本学期的一个小组作业,以下是题目与要求原文,这位朋友正在读大二。请问中国的大二学生作过这些吗?这就是中国和国外的教育差别。国外讲究合作与team work,从一个项目到手一开始就要通盘考虑,并分配任务,而且在整个大学学习期间,不求每个人做得最好,但都要有概念,都要养成良好的习惯。请问中国的大学生毕业之后有几个有这些能力的?也没有几个大学应届毕业生能够从整体上和全局方面考虑一个问题的,而往往通过自己的想象与所谓的经验来解决问题。由于在上学的时候没有训练思维与合作,结果就是一个个水平参差不齐。国外程序员的个人水平不一定高,但是他只要一个人水平高,并有驾驭全局的能力,基本上就能将一个项目带上正途。而中国的程序员总是想一个人全搞定,结果是你的能力限制了你的成果。中国的程序员还经常是从一开始写程序的时候就没有一点规划与设计,一上来就写;还有就是写程序的时候完全不考虑扩展和接口友好等问题,其实就是无合作精神的一种典型表现;另外,就是中国的程序员写作凭经验,而很少有人用理论指导实践的,结果就是最后得到同样的结果,凭经验的人要花更长的时间才能找到最合理的方法,而即使用了相同的方法,凭经验的人也对为什么只是似懂非懂或是事后诸葛亮。这些都是中国程序员存在的极大问题,总之就是从一开始学习的时候就只会啃书本,而不是成体系地并结合实践来学习,在国内也不会形成一个竞争气氛与紧迫感,因为国内除了几次考试外,别的都不重要,而在北美,平时的作业占的比重可到一半以上,因此平时的作业做好了,不但学到了东西,也保证了成绩。中国的教育方式有他自己的一些特点与优点,但是在培养学生的自主性、创造性与合作性方面实在是做得太差了,而且很多地方也不公平,导致了是为上学而上学,而不是为学习去学习。

就从以下的作业,基本可以看出,中国的大学与北美的大学在培养学生能力方面的不同。不错,北美的一些学生是笨,而且有的笨得可以,但笨不是全部,他们最后成绩可能不好,但很多思维方法与习惯都在不自觉中掌握了。而北美社会是个自由的社会,每个人都可以做他愿意做的事,只要你能做,你不会的事可以不做。而中国的大学生呢?往往是越是成绩好越是只会考试,别的反而什么都不会,这不是畸形吗?结果走上社会时除了成绩好没有什么优点,在工作中往往不能胜任,当然中国好一点是有些时间给你慢慢学,北美就没这么幸运了,你不行就被淘汰了。

在写程序方面,我觉得大多数中国的程序员写的很多程序都没有什么水平,象小孩写的东西,一点不象是专业人士写的。比如我前几天看到一个程序被作者冠为“最好的PHP的EMAIL的类”这么一个程序,一看,无非就是实现了规范要求的格式,最后通过SOCK发送出去。本来也没什么,但一看,居然一个缩进都没有,而且逻辑混乱,功能不紧凑单一,还被称为最好的,当时狂吐,中国的高手程序员都死绝了?!总之就是从一开始就没有培养好规范的作风与思考与分析问题解决问题的能力,结果就是大多数中国的程序员从来就是不入流的(指正规的专业人士),一个明显的表现就是中国根本缺乏世界著名的品牌,也很少有什么著名的大公司,一些著名的软件也大都只是小软件,没有大系统大制作,这与国外差得太远了,主要原因是没有人有能力搞这些,也没有人有长远的眼光进行投资。还有就是搞得太杂,结果是什么都做不好。而且中国的软件做得是实在是太小儿科不说,用户也不友好,运行也不稳定,好象压根没做什么严格测试的,试想一些所谓的中型程序一个人搞一个月就出台,还美其名曰高效,怎么可能?想FLASHGET这样的程序也不是只一个月能搞定的吧?光过硬的调试可能就花掉一个月,更别谈从设计到写码到成型到调试到测试到发布了。文档更是做得极差,有的连说明都没有,搞得人无所适从。国外的软件,无论是多大多小的程序,一般都有说明,至少是安装使用的简单说明——就是一般的文本,至少能让你入手。国人的程序唯一一个优点就是程序是中文的——但这往往比用英文软件还要不方便。比如说,我前几天装一个邮件服务器,一开始用国人写的某“著名”软件,一装,首先就感觉运行不流畅,打开界面一看,连最重要的STMP发送认证都找不到在哪儿,界面极其简陋,功能严重欠缺,安全性方面更不知道可不可靠了,看帮助也看不清,后来在一个与安全无关的地方找到了选项,再一看,很多基本策略都没有,无法保证安全性。直摇头,马上uninstall,后来装了MD,虽然是英文,但结构清楚,功能齐全,工作明显稳定很多,而且帮助文档、使用手册极其详细,有的还有概念解释,以方便非专业用户。虽然支持国产,但是国产不争气,没有办法。


其实下面的问题很简单,一个人做根本不用那么复杂,但是让一组人来协调地做,还真不是那么简单的事,要有一个有分析头脑的人做leader,要有人专门负责写文档,有人测试什么的。对了,这门课好象就是software engineering,软件工程,好象中国是不学的吧,至少我那时没学。


------------------ 这是这位朋友本周要做的任务 ----------------
- 2.5 Assumptions and Dependencies.
What do you assume the client to do/act/want, and what you depend on to produce a final result. Its design phases for everyone.


---------------------- 以下是原题目 ---------------------------
Dominion Pizza Store  
• Objectives:  
o Dominion Pizza Store (DPS) is planning an information system for their services. A customer may make an order through the Internet / Phone / in-person. The order may include several products. There are a few basic sorts of pizzas, which can be complemented with different toppings. The assortment and the toppings change from time to time, as do their prices. In addition to pizzas, other products are on offer. They are divided into product groups. There is a textual description of every product, and a picture of some of them, which the client may see when ordering through the WWW.  
o A bill will accompany each delivery. The price will be discounted according to time, if the delivery is late; for example, 45-minute delivery or FREE. The price of a product may, also, differ according to the time of day, for example. The time and place of delivery is set when the customer makes the order.  
o For an online / phone order, the customer is identified by his/her telephone number, or other contact information. A delivery status time stamp (i.e. to kitchen, to delivery, and to customer) is registered for each delivery. The client may cancel or change the order only if the order has not gone to the kitchen. For an online/phone order, customer's information is checked in the database for an existing, or new client. If the client is new then take and store contact details. For an existing client (or address), past history will be checked for any problems.  

• Main Modules:  
1. Client Interface  
 Browsing the Products, and their Prices  
 Making an order  
 Delivery time stamping  
2. Agent Interface (Phone / in-person orders)  
 Entering Agent Info (e.g. ID)  
 Browsing the Products, and their Prices  
 Delivery time stamping  
 Checking past history (for any problems, and/or past frequent orders for either quick order taking or special offers)  
3. Inventory Management  
 Food supplies  
 Misc. supplies (e.g. Cleaning)  
 Entering and maintaining product information (inc. pricing) in the database  
4. Finances Management  
 Account Receivables  
 Account Payables  
5. Delivery Management  
 Order Status (i.e. to kitchen - when, to delivery - when)  
 Special offers (e.g. late order, new product introduction)  
 Printing an order list - for kitchen (?)  
 Printing a receipt  
6. Payroll  
 Employee Information (e.g. Contact Info, Salary Info, Bonuses, Taxes, GST/PST)  
 Hiring / Firing / Training etc.  
7. Anything you may suggest (will be considered towards the Bonus Marks for the best project, if above modules done reasonably well
花了不少时间和心思作了这个东西, 使用PHP去读取或修改 MP3或WMA文件的头信息(主要有专辑,歌名,歌手等)  

其实网上搜索有不少 MP3 的类似程序,但 WMA 的几乎没有,如果有也是windows平台下直接使用API的,想在 Unix/Linux 下使用简直没门。。。。

由于我的音乐站刚开通,需要这方面的功能,所以就下决心花时间去查资料搞清楚MP3和wma的数据头格式,全部代码由PHP编写,有兴趣可以仔细研究,或加以完善。

其实这东西技术上并没有难点,麻烦在于先要搞清楚它的结构和格式,这个代码也是一个使用PHP操作二进制(binary data)的例子,这几天群里刚好也有人问起这个,主要就是pack和unpack2个函数啦,呵呵,像MP3的原始头信息几乎是一个bit表示一个信息,这时就要用到大量的“按位操作”来分析它。

下面是源码照贴(含例子),呵,这也作为实习版主的一个小贡献吧,挺希望这里能见到一些原创并且对它人有用的代码(类库)出现。!!在此抛砖先了。  


// AudioExif.class.php
// 用PHP进行音频文件头部信息的读取与写入
// 目前只支持 WMA 和 MP3 两种格式, 只支持常用的几个头部信息
//
// 写入信息支持: Title(名称), Artist(艺术家), Copyright(版权), Description (描述)
//               Year(年代),  Genre (流派),   AlbumTitle (专辑标题)
// 其中 mp3 和 wma 略有不同, 具体返回的信息还可能更多, 但只有以上信息可以被写入
// mp3 还支持 Track (曲目编号写入)
// 对于 MP3 文件支持 ID3v1也支持ID3v2, 读取时优先 v2, 写入时总是会写入v1, 必要时写入v2
//
// 用法说明: (由于 wma 使用 Unicode 存取, 故还需要 mb_convert_encoding() 扩展
//           返回数据及写入数据均为 ANSI 编码, 即存什么就显示什么 (中文_GB2312)
//
// require ('AudioExif.class.php');
// $AE = new AudioExif;
// $file = '/path/to/test.mp3';
//
// 1. 检查文件是否完整 (only for wma, mp3始终返回 true)
//
// $AE->CheckSize($file);
//
// 2. 读取信息, 返回值由信息组成的数组, 键名解释参见上方
//
// print_r($AE->GetInfo($file));
//
// 3. 写入信息, 第二参数是一个哈希数组, 键->值, 支持的参见上方的, mp3也支持 Track
//    要求第一参数的文件路径可由本程序写入
// $pa = array('Title' => '新标题', 'AlbumTitle' => '新的专辑名称');
// $AE->SetInfo($file, $pa);
//
// 版本: 0.1
// 作者: hightman
// QQ群: 17708754  (非纯PHP进阶交流群)
// 时间: 2007/01/25
// 其它: 该插件花了不少时间搜集查找 wma及mp3 的文件格式说明文档与网页, 希望对大家有用.
//       其实网上已经有不少类似的程序, 但对 wma 实在太少了, 只能在 win 平台下通过 M$ 的
//       API 来操作, 而 MP3 也很少有可以在 unix/linux 命令行操作的, 所以特意写了这个模块
//
// 如果发现 bug 或提交 patch, 或加以改进使它更加健壮, 请告诉我.
// (关于 ID3和Wma的文件格式及结构 在网上应该都可以找到参考资料)
//

if (!extension_loaded('mbstring'))
{
 trigger_error('PHP Extension module `mbstring` is required for AudioExif', E_USER_WARNING);
 return true;
}

// the Main Class
class AudioExif
{
 // public vars
 var $_wma = false;
 var $_mp3 = false;

 // Construct
 function AudioExif()
 {
   // nothing to do
 }

 // check the filesize
 function CheckSize($file)
 {
   $handler = &$this->_get_handler($file);
   if (!$handler) return false;
   return $handler->check_size($file);
 }

 // get the infomations
 function GetInfo($file)
 {
   $handler = &$this->_get_handler($file);
   if (!$handler) return false;
   return $handler->get_info($file);
 }

 // write the infomations
 function SetInfo($file, $pa)
 {
   if (!is_writable($file))
   {
     trigger_error('AudioExif: file `' . $file . '` can not been overwritten', E_USER_WARNING);
     return false;
   }
   $handler = &$this->_get_handler($file);
   if (!$handler) return false;
   return $handler->set_info($file, $pa);
 }

 // private methods
 function &_get_handler($file)
 {
   $ext = strtolower(strrchr($file, '.'));
   $ret = false;
   if ($ext == '.mp3')
   {  // MP3
     $ret = &$this->_mp3;
     if (!$ret) $ret = new _Mp3Exif();
   }
   else if ($ext == '.wma')
   {  // wma
     $ret = &$this->_wma;
     if (!$ret) $ret = new _WmaExif();
   }
   else
   {  // unknown
     trigger_error('AudioExif not supported `' . $ext . '` file.', E_USER_WARNING);
   }
   return $ret;
 }
}

// DBCS => gb2312
function dbcs_gbk($str)
{
 // strip the last "\0\0"
 $str = substr($str, 0, -2);
 return mb_convert_encoding($str, 'GBK', 'UCS-2LE');
}

// gb2312 => DBCS
function gbk_dbcs($str)
{
 $str  = mb_convert_encoding($str, 'UCS-2LE', 'GBK');
 $str .= "\0\0";
 return $str;
}

// file exif
class _AudioExif
{
 var $fd;
 var $head;
 var $head_off;
 var $head_buf;
 
 // init the file handler
 function _file_init($fpath, $write = false)
 {
   $mode = ($write ? 'rb+' : 'rb');
   $this->fd = @fopen($fpath, $mode);
   if (!$this->fd)
   {
     trigger_error('AudioExif: `' . $fpath . '` can not be opened with mode `' . $mode . '`', E_USER_WARNING);
     return false;
   }
   $this->head = false;
   $this->head_off = 0;
   $this->head_buf = '';
   return true;
 }

 // read buffer from the head_buf & move the off pointer
 function _read_head_buf($len)
 {
   if ($len <= 0) return NULL;
   $buf = substr($this->head_buf, $this->head_off, $len);
   $this->head_off += strlen($buf);
   return $buf;
 }

 // read one short value
 function _read_head_short()
 {
   $ord1 = ord(substr($this->head_buf, $this->head_off, 1));
   $ord2 = ord(substr($this->head_buf, $this->head_off+1, 1));
   $this->head_off += 2;
   return ($ord1 + ($ord2<<8));
 }

 // save the file head
 function _file_save($head, $olen, $nlen = 0)
 {
   if ($nlen == 0) $nlen = strlen($head);
   if ($nlen == $olen)
   {
     // shorter
     flock($this->fd, LOCK_EX);
     fseek($this->fd, 0, SEEK_SET);
     fwrite($this->fd, $head, $nlen);
     flock($this->fd, LOCK_UN);
   }
   else
   {
     // longer, buffer required
     $stat = fstat($this->fd);
     $fsize = $stat['size'];

     // buf required (4096?) 应该不会 nlen - olen > 4096 吧
     $woff = 0;
     $roff = $olen;

     // read first buffer
     flock($this->fd, LOCK_EX);
     fseek($this->fd, $roff, SEEK_SET);
     $buf = fread($this->fd, 4096);

     // seek to start
     fseek($this->fd, $woff, SEEK_SET);
     fwrite($this->fd, $head, $nlen);
     $woff += $nlen;

     // seek to woff & write the data
     do
     {
       $buf2 = $buf;
       $roff += 4096;
       if ($roff < $fsize)
       {
         fseek($this->fd, $roff, SEEK_SET);
         $buf = fread($this->fd, 4096);          
       }

       // save last buffer
       $len2 = strlen($buf2);
       fseek($this->fd, $woff, SEEK_SET);
       fwrite($this->fd, $buf2, $len2);
       $woff += $len2;
     }
     while ($roff < $fsize);
     ftruncate($this->fd, $woff);
     flock($this->fd, LOCK_UN);
   }
 }

 // close the file
 function _file_deinit()
 {
   if ($this->fd)
   {
     fclose($this->fd);
     $this->fd = false;
   }    
 }
}

// wma class
class _WmaExif extends _AudioExif
{
 var $items1 = array('Title', 'Artist', 'Copyright', 'Description', 'Reserved');
 var $items2 = array('Year', 'Genre', 'AlbumTitle');

 // check file size (length) maybe invalid file
 function check_size($file)
 {
   $ret = false;
   if (!$this->_file_init($file)) return true;
   if ($this->_init_header())
   {
     $buf = fread($this->fd, 24);
     $tmp = unpack('H32id/Vlen/H8unused', $buf);  
     if ($tmp['id'] == '3626b2758e66cf11a6d900aa0062ce6c')
     {
       $stat = fstat($this->fd);
       $ret = ($stat['size'] == ($this->head['len'] + $tmp['len']));
     }
   }
   $this->_file_deinit();
   return $ret;
 }

 // set info (save the infos)
 function set_info($file, $pa)
 {
   // check the pa
   settype($pa, 'array');
   if (!$this->_file_init($file, true)) return false;
   if (!$this->_init_header())
   {
     $this->_file_deinit();
     return false;
   }
   
   // parse the old header & generate the new header
   $head_body = '';
   $st_found = $ex_found = false;
   $head_num = $this->head['num'];
   while (($tmp = $this->_get_head_frame()) && ($head_num > 0))
   {
     $head_num--;
     if ($tmp['id'] == '3326b2758e66cf11a6d900aa0062ce6c')
     {  // Standard Info
       // 1-4
       $st_found = true;
       $st_body1 = $st_body2 = '';        
       $lenx = unpack('v5', $this->_read_head_buf(10));
       $tmp['len'] -= 34;  // 10 + 24
       for ($i = 0; $i < count($this->items1); $i++)
       {
         $l = $lenx[$i+1];
         $k = $this->items1[$i];
         $tmp['len'] -= $l;

         $data = $this->_read_head_buf($l);
         if (isset($pa[$k])) $data = gbk_dbcs($pa[$k]);

         $st_body2 .= $data;
         $st_body1 .= pack('v', strlen($data));
       }
       // left length
       if ($tmp['len'] > 0) $st_body2 .= $this->_read_head_buf($tmp['len']);

       // save to head_body
       $head_body .= pack('H32VH8', $tmp['id'], strlen($st_body1 . $st_body2)+24, $tmp['unused']);
       $head_body .= $st_body1 . $st_body2;    
     }
     else if ($tmp['id'] == '40a4d0d207e3d21197f000a0c95ea850')
     {  // extended info
       $ex_found = true;
       
       $inum = $this->_read_head_short();
       $inum2 = $inum;
       $tmp['len'] -= 26;  // 24 + 2
       $et_body = '';
       while ($tmp['len'] > 0 && $inum > 0)
       {
         // attribute name
         $nlen = $this->_read_head_short();
         $nbuf = $this->_read_head_buf($nlen);

         // the flag & value  length
         $flag = $this->_read_head_short();
         $vlen = $this->_read_head_short();
         $vbuf = $this->_read_head_buf($vlen);

         // set the length
         $tmp['len'] -= (6 + $nlen + $vlen);
         $inum--;

         // save the data?
         $name = dbcs_gbk($nbuf);
         $k = substr($name, 3);
         if (in_array($k, $this->items2) && isset($pa[$k]))
         {
           $vbuf = gbk_dbcs($pa[$k]);
           $vlen = strlen($vbuf);
           unset($pa[$k]);
         }
         $et_body .= pack('v', $nlen) . $nbuf . pack('vv', $flag, $vlen) . $vbuf;
       }
       // new tag insert??
       foreach ($this->items2 as $k)
       {
         if (isset($pa[$k]))
         {
           $inum2++;
           $nbuf = gbk_dbcs('WM/' . $k);
           $nlen = strlen($nbuf);
           $vbuf = gbk_dbcs($pa[$k]);
           $vlen = strlen($vbuf);
           $et_body .= pack('v', $nlen) . $nbuf . pack('vv', 0, $vlen) . $vbuf;
         }
       }
       // left buf?
       if ($tmp['len'] > 0) $et_body .= $this->_read_head_buf($tmp['len']);

       // save to head_body
       $head_body .= pack('H32VH8v', $tmp['id'], strlen($et_body)+26, $tmp['unused'], $inum2);
       $head_body .= $et_body;    
     }
     else
     {
       // just keep other head frame
       $head_body .= pack('H32VH8', $tmp['id'], $tmp['len'], $tmp['unused']);
       if ($tmp['len'] > 24) $head_body .= $this->_read_head_buf($tmp['len']-24);
     }
   }

   // st not found?
   if (!$st_found)
   {
     $st_body1 = $st_body2 = '';
     foreach ($this->items1 as $k)
     {
       $data = (isset($pa[$k]) ? gbk_dbcs($pa[$k]) : "");
       $st_body1 .= pack('v', strlen($data));
       $st_body2 .= $data;
     }
     
     // save to head_body
     $head_body .= pack('H32Va4', '3326b2758e66cf11a6d900aa0062ce6c', strlen($st_body1 . $st_body2)+24, '');
     $head_body .= $st_body1 . $st_body2;
     $this->head['num']++;
   }
   // ex not found?
   if (!$ex_found)
   {
     $inum = 0;
     $et_body = '';
     foreach ($this->items2 as $k)
     {
       $nbuf = gbk_dbcs('WM/' . $k);
       $vbuf = (isset($pa[$k]) ? gbk_dbcs($pa[$k]) : "");
       $et_body .= pack('v', strlen($nbuf)) . $nbuf . pack('vv', 0, strlen($vbuf)) . $vbuf;
       $inum++;
     }
     $head_body .= pack('H32Va4v', '40a4d0d207e3d21197f000a0c95ea850', strlen($et_body)+26, '', $inum);
     $head_body .= $et_body;
     $this->head['num']++;
   }    

   // after save
   $new_len = strlen($head_body) + 30;
   $old_len = $this->head['len'];
   if ($new_len < $old_len)
   {
     $head_body .= str_repeat("\0", $old_len - $new_len);
     $new_len = $old_len;
   }
   $tmp = $this->head;
   $head_buf = pack('H32VVVH4', $tmp['id'], $new_len, $tmp['len2'], $tmp['num'], $tmp['unused']);
   $head_buf .= $head_body;
   $this->_file_save($head_buf, $old_len, $new_len);

   // close the file & return
   $this->_file_deinit();
   return true;
 }

 // get info
 function get_info($file)
 {
   $ret = array();
   if (!$this->_file_init($file)) return false;
   if (!$this->_init_header())
   {
     $this->_file_deinit();
     return false;
   }

   // get the data from head_buf
   $head_num = $this->head['num'];  // num of head_frame
   while (($tmp = $this->_get_head_frame()) && $head_num > 0)
   {
     $head_num--;
     if ($tmp['id'] == '3326b2758e66cf11a6d900aa0062ce6c')
     {  // Standard Info
       $lenx = unpack('v*', $this->_read_head_buf(10));
       for ($i = 1; $i <= count($this->items1); $i++)
       {
         $k = $this->items1[$i-1];
         $ret[$k] = dbcs_gbk($this->_read_head_buf($lenx[$i]));
       }
     }
     else if ($tmp['id'] == '40a4d0d207e3d21197f000a0c95ea850')
     {  // Extended Info
       $inum = $this->_read_head_short();
       $tmp['len'] -= 26;
       while ($inum > 0 && $tmp['len'] > 0)
       {
         // attribute name
         $nlen = $this->_read_head_short();
         $nbuf = $this->_read_head_buf($nlen);

         // the flag & value  length
         $flag = $this->_read_head_short();
         $vlen = $this->_read_head_short();
         $vbuf = $this->_read_head_buf($vlen);

         // update the XX
         $tmp['len'] -= (6 + $nlen + $vlen);
         $inum--;

         $name = dbcs_gbk($nbuf);
         $k = substr($name, 3);
         if (in_array($k, $this->items2))
         {  // all is string value (refer to falg for other tags)
           $ret[$k] = dbcs_gbk($vbuf);
         }
       }    
     }
     else
     {  // skip only
       if ($tmp['len'] > 24) $this->head_off += ($tmp['len'] - 24);
     }
   }
   $this->_file_deinit();
   return $ret;
 }

 // get the header?
 function _init_header()
 {
   fseek($this->fd, 0, SEEK_SET);
   $buf = fread($this->fd, 30);
   if (strlen($buf) != 30) return false;
   $tmp = unpack('H32id/Vlen/Vlen2/Vnum/H4unused', $buf);
   if ($tmp['id'] != '3026b2758e66cf11a6d900aa0062ce6c')
     return false;

   $this->head_buf = fread($this->fd, $tmp['len'] - 30);
   $this->head = $tmp;
   return true;
 }

 // _get_head_frame()
 function _get_head_frame()
 {
   $buf = $this->_read_head_buf(24);    
   if (strlen($buf) != 24) return false;
   $tmp = unpack('H32id/Vlen/H8unused', $buf);
   return $tmp;
 }
}

// mp3 class (if not IDv2 then select IDv1)
class _Mp3Exif extends _AudioExif
{
 var $head1;
 var $genres = array('Blues','Classic Rock','Country','Dance','Disco','Funk','Grunge','Hip-Hop','Jazz','Metal','New Age','Oldies','Other','Pop','R&B','Rap','Reggae','Rock','Techno','Industrial','Alternative','Ska','Death Metal','Pranks','Soundtrack','Euro-Techno','Ambient','Trip-Hop','Vocal','Jazz+Funk','Fusion','Trance','Classical','Instrumental','Acid','House','Game','Sound Clip','Gospel','Noise','AlternRock','Bass','Soul','Punk','Space','Meditative','Instrumental Pop','Instrumental Rock','Ethnic','Gothic','Darkwave','Techno-Industrial','Electronic','Pop-Folk','Eurodance','Dream','Southern Rock','Comedy','Cult','Gangsta','Top 40','Christian Rap','Pop/Funk','Jungle','Native American','Cabaret','New Wave','Psychadelic','Rave','Showtunes','Trailer','Lo-Fi','Tribal','Acid Punk','Acid Jazz','Polka','Retro','Musical','Rock & Roll','Hard Rock','Unknown');

 // MP3 always return true
 function check_size($file)
 {
   return true;
 }

 // get info
 function get_info($file)
 {
   if (!$this->_file_init($file)) return false;    
   $ret = false;
   if ($this->_init_header())
   {
     $ret = ($this->head ? $this->_get_v2_info() : $this->_get_v1_info());
     $ret['meta'] = $this->_get_meta_info();
   }
   $this->_file_deinit();
   return $ret;
 }

 // set info
 function set_info($file, $pa)
 {
   if (!$this->_file_init($file, true)) return false;
   if ($this->_init_header())
   {
     // always save v1 info
     $this->_set_v1_info($pa);      
     // set v2 first if need
     $this->_set_v2_info($pa);
   }
   $this->_file_deinit();
   return true;
 }

 // get the header information[v1+v2], call after file_init
 function _init_header()
 {
   $this->head1 = false;
   $this->head = false;

   // try to get ID3v1 first
   fseek($this->fd, -128, SEEK_END);
   $buf = fread($this->fd, 128);
   if (strlen($buf) == 128 && substr($buf, 0, 3) == 'TAG')
   {
     $tmp = unpack('a3id/a30Title/a30Artist/a30AlbumTitle/a4Year/a28Description/CReserved/CTrack/CGenre', $buf);
     $this->head1 = $tmp;      
   }

   // try to get ID3v2
   fseek($this->fd, 0, SEEK_SET);
   $buf = fread($this->fd, 10);
   if (strlen($buf) == 10 && substr($buf, 0, 3) == 'ID3')
   {
     $tmp = unpack('a3id/Cver/Crev/Cflag/C4size', $buf);
     $tmp['size'] = ($tmp['size1']<<21)|($tmp['size2']<<14)|($tmp['size3']<<7)|$tmp['size4'];
     unset($tmp['size1'], $tmp['size2'], $tmp['size3'], $tmp['size4']);

     $this->head = $tmp;
     $this->head_buf = fread($this->fd, $tmp['size']);
   }
   return ($this->head1 || $this->head);
 }

 // get v1 info
 function _get_v1_info()
 {
   $ret = array();
   $tmpa = array('Title', 'Artist', 'Copyright', 'Description', 'Year', 'AlbumTitle');
   foreach ($tmpa as $tmp)
   {      
     $ret[$tmp] = $this->head1[$tmp];
     if ($pos = strpos($ret[$tmp], "\0"))
       $ret[$tmp] = substr($ret[$tmp], 0, $pos);
   }

   // count the Genre, [Track]
   if ($this->head1['Reserved'] == 0) $ret['Track'] = $this->head1['Track'];
   else $ret['Description'] .= chr($ret['Reserved']) . chr($ret['Track']);

   // Genre_idx
   $g = $this->head1['Genre'];
   if (!isset($this->genres[$g])) $ret['Genre'] = 'Unknown';
   else $ret['Genre'] = $this->genres[$g];

   // return the value
   $ret['ID3v1'] = 'yes';
   return $ret;
 }

 // get v2 info
 function _get_v2_info()
 {
   $ret = array();
   $items = array(  'TCOP'=>'Copyright', 'TPE1'=>'Artist', 'TIT2'=>'Title', 'TRCK'=> 'Track',
           'TCON'=>'Genre', 'COMM'=>'Description', 'TYER'=>'Year', 'TALB'=>'AlbumTitle');
   while (true)
   {
     $buf = $this->_read_head_buf(10);
     if (strlen($buf) != 10) break;      
     $tmp = unpack('a4fid/Nsize/nflag', $buf);
     if ($tmp['size'] == 0) break;
     $tmp['dat'] = $this->_read_head_buf($tmp['size']);

     // 0x6000 (11000000 00000000)    
     if ($tmp['flag'] & 0x6000) continue;

     // mapping the data
     if ($k = $items[$tmp['fid']])
     {  // If first char is "\0", just skip
       if (substr($tmp['dat'], 0, 1) == "\0") $tmp['dat'] = substr($tmp['dat'], 1);
       $ret[$k] = $tmp['dat'];
     }
   }

   // reset the genre
   if ($g = $ret['Genre'])
   {
     if (substr($g,0,1) == '(' && substr($g,-1,1) == ')') $g = substr($g, 1, -1);
     if (is_numeric($g))
     {
       $g = intval($g);
       $ret['Genre'] = (isset($this->genres[$g]) ? $this->genres[$g] : 'Unknown');
     }
   }

   $ret['ID3v1'] = 'no';
   return $ret;
 }

 // get meta info of MP3
 function _get_meta_info()
 {
   // seek to the lead buf: 0xff
   $off = 0;
   if ($this->head) $off = $this->head['size'] + 10;
   fseek($this->fd, $off, SEEK_SET);
   while (!feof($this->fd))
   {
     $skip = ord(fread($this->fd, 1));
     if ($skip == 0xff) break;
   }
   if ($skip != 0xff) return false;
   $buf = fread($this->fd, 3);
   if (strlen($buf) != 3) return false;
   $tmp = unpack('C3', $buf);
   if (($tmp[1] & 0xf0) != 0xf0) return false;

   // get the meta info
   $meta = array();

   // get mpeg version
   $meta['mpeg']  = ($tmp[1] & 0x08 ? 1 : 2);
   $meta['layer']  = ($tmp[1] & 0x04) ? (($tmp[1] & 0x02) ? 1 : 2) : (($tmp[1] & 0x02) ? 3 : 0);
   $meta['epro']  = ($tmp[1] & 0x01) ? 'no' : 'yes';

   // bit rates
   $bit_rates = array(
     1 => array(
       1 => array(0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0),
       2 => array(0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0),
       3 => array(0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0)
     ),
     2 => array(
       1 => array(0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,0),
       2 => array(0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0),
       3 => array(0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0)
     )
   );
   $i = $meta['mpeg'];
   $j = $meta['layer'];
   $k = ($tmp[2]>>4);
   $meta['bitrate'] = $bit_rates[$i][$j][$k];

   // sample rates <采样率>
   $sam_rates = array(1=>array(44100,48000,32000,0), 2=>array(22050,24000,16000,0));
   $meta['samrate'] = $sam_rates[$i][$k];
   $meta["padding"] = ($tmp[2] & 0x02) ? 'on' : 'off';
   $meta["private"] = ($tmp[2] & 0x01) ? 'on' : 'off';

   // mode & mode_ext
   $k = ($tmp[3]>>6);
   $channel_modes = array('stereo', 'joint stereo', 'dual channel', 'single channel');
   $meta['mode'] = $channel_modes[$k];

   $k = (($tmp[3]>>4) & 0x03);
   $extend_modes = array('MPG_MD_LR_LR', 'MPG_MD_LR_I', 'MPG_MD_MS_LR', 'MPG_MD_MS_I');
   $meta['ext_mode'] = $extend_modes[$k];

   $meta['copyright'] = ($tmp[3] & 0x08) ? 'yes' : 'no';
   $meta['original'] = ($tmp[3] & 0x04) ? 'yes' : 'no';

   $emphasis = array('none', '50/15 microsecs', 'rreserved', 'CCITT J 17');
   $k = ($tmp[3] & 0x03);
   $meta['emphasis'] = $emphasis[$k];

   return $meta;
 }

 // set v1 info
 function _set_v1_info($pa)
 {
   // ID3v1 (simpled)
   $off = -128;
   if (!($tmp = $this->head1))
   {      
     $off = 0;
     $tmp['id'] = 'TAG';
     $tmp['Title'] = $tmp['Artist'] = $tmp['AlbumTitle'] = $tmp['Year'] = $tmp['Description'] = '';
     $tmp['Reserved'] = $tmp['Track'] = $tmp['Genre'] = 0;
   }
   
   // basic items
   $items = array('Title', 'Artist', 'Copyright', 'Description', 'Year', 'AlbumTitle');
   foreach ($items as $k)
   {
     if (isset($pa[$k])) $tmp[$k] = $pa[$k];
   }

   // genre index
   if (isset($pa['Genre']))
   {
     $g = 0;
     foreach ($this->genres as $gtmp)
     {
       if (!strcasecmp($gtmp, $pa['Genre']))
         break;
       $g++;
     }
     $tmp['Genre'] = $g;
   }
   if (isset($pa['Track'])) $tmp['Track'] = intval($pa['Track']);

   // pack the data
   $buf = pack('a3a30a30a30a4a28CCC',  $tmp['id'], $tmp['Title'], $tmp['Artist'], $tmp['AlbumTitle'],
           $tmp['Year'], $tmp['Description'], 0, $tmp['Track'], $tmp['Genre']);

   flock($this->fd, LOCK_EX);
   fseek($this->fd, $off, SEEK_END);
   fwrite($this->fd, $buf, 128);
   flock($this->fd, LOCK_UN);
 }

 // set v2 info
 function _set_v2_info($pa)
 {
   if (!$this->head)
   {  // insert ID3
     return;  // 没有就算了
     /**
     $tmp = array('id'=>'ID3','ver'=>3,'rev'=>0,'flag'=>0);
     $tmp['size'] = -10;  // +10 => 0
     $this->head = $tmp;
     $this->head_buf = '';
     $this->head_off = 0;
     **/
   }
   $items = array(  'TCOP'=>'Copyright', 'TPE1'=>'Artist', 'TIT2'=>'Title', 'TRAC'=>'Track',
           'TCON'=>'Genre', 'COMM'=>'Description', 'TYER'=>'Year', 'TALB'=>'AlbumTitle');

   $head_body = '';
   while (true)
   {
     $buf = $this->_read_head_buf(10);
     if (strlen($buf) != 10) break;
     $tmp = unpack('a4fid/Nsize/nflag', $buf);
     if ($tmp['size'] == 0) break;
     $data = $this->_read_head_buf($tmp['size']);

     if (($k = $items[$tmp['fid']]) && isset($pa[$k]))
     {
       // the data should prefix by "\0" [replace]
       $data = "\0" . $pa[$k];
       unset($pa[$k]);
     }
     $head_body .= pack('a4Nn', $tmp['fid'], strlen($data), $tmp['flag']) . $data;
   }
   // reverse the items & set the new tags
   $items = array_flip($items);
   foreach ($pa as $k => $v)
   {
     if ($fid = $items[$k])
     {
       $head_body .= pack('a4Nn', $fid, strlen($v) + 1, 0) . "\0" . $v;
     }
   }

   // new length
   $new_len = strlen($head_body) + 10;
   $old_len = $this->head['size'] + 10;
   if ($new_len < $old_len)
   {
     $head_body .= str_repeat("\0", $old_len - $new_len);
     $new_len = $old_len;      
   }

   // count the size1,2,3,4, no include the header
   // 较为变态的算法... :p (28bytes integer)
   $size = array();
   $nlen = $new_len - 10;
   for ($i = 4; $i > 0; $i--)
   {
     $size[$i] = ($nlen & 0x7f);
     $nlen >>= 7;
   }
   $tmp = $this->head;
   //echo "old_len : $old_len new_len: $new_len\n";
   $head_buf = pack('a3CCCCCCC', $tmp['id'], $tmp['ver'], $tmp['rev'], $tmp['flag'],
     $size[1], $size[2], $size[3], $size[4]);
   $head_buf .= $head_body;
   $this->_file_save($head_buf, $old_len, $new_len);
 }
}
?>

在许多应用软件运行时都带有命令行参数,其实这些命令行参数在C语言编写的程序中也可以实现,灵活地运用命令行参数进行处理可以有效地提高程序的运行效率,收到事半功倍的效果。

  C语言中有关命令行参数涉及到程序的主函数main(int argc,char *argv[]这样两个参数,其中,int argc表示命令行参数的个数(包括可执行程序名本身),char *argv[]表示每个参数的具体内容,argv[0]为命令行中可执行程序名本身,argv[1]为命令行中第二个参数的内容,依次类推。如下例输出命令行参数的个数及参数的内容:

main (int argc,char *argv[],
{int I;
 printf("\n命令行中可执行文件名为:%s",argv[0]);
 printf("\n总共有%d个参数:",argc);
 I=0;
 while(argc>=1)
 {printf(″%s  ",argv[I++]);
  argc--;}
}

  命令行参数用的最多还是在诸如DIR A:等之类带有盘符、路径或文件名这样的命令行中,所以说灵活处理这一类参数才能有效地提高程序的运行效果。譬如DIR命令,其后可以是盘符,可以是路径,也可以是文件名,如何区分这一参数呢?请看下例(此程序模拟DIR命令,程序要求在命令行输入一个参数:盘符或路径或文件名,若无参数或参数多于一个都将取默认的参数“*.*”)。

\*--------------------
功能:模拟DIR命令进行处理命令行参数
--------------------*/
#include
#include
#include
#inchlude
int j,num=0;
char ss[20],path[50],path2[50];
void main (int argc,char *argv[])
{
 struct ffblk f;
 int done;
 if(argc==2)  /*取命令行参数到数组中*/
  strcpy(ss,argv[1]);
 else
  strcpy(ss,″*.*″); /*给数组赋值缺省参数*/
  if (((ss[strlen(ss)-1]==′\\′||((ss[strlen(ss)-1]==':'))
   strcat(ss,″*.*″); /*若参数为路径或盘符,则加上″*.*″ */
  getcwd(path1,50); /*取当前路径*/
  if (chdir(ss)==0) /*判断参数是否为路径*/
    strcat(ss,"\\*.*"); /*若路径末没有带"\",则加上"*.*" */

 chdir(path1); /*恢复原来路径*/
 strcpy(path2,ss);
 for(j=strlen(path2);j>0;j--)/*提取参数中的路径到path2 */
  {if((path2[j]=='\\'))||(path2[j]==':')){
   path2[j+1]='\0';
   goto senull;}
  }
 path2[0]='\0';
 senull:
 if(strlen(path2)==0)  /* 若给出的参数中没带路径,则取当前路径*/
  strcpy(path2,path1);
 printf("\n**模拟DIR**\n 命令目录路径%s",path2);
 done=findfirst(ss,&f,55); /*查找第一个配匹的文件*/
 j=1;
 while(!done)
 {if (f.ff_attrib!=0x10) /* 若文件属性不是目录 */
   printf("\n %15s %20ld",f.ff_name,f.ff_fsize);
  else
   printf("\n &11s ",f.ff_name);
  num++;
  j++;
  if(j==23)
   printf("\n --------More (按任意键继续)----");
  getch();
  j=0;
  printf(″\n (目录路径%s)″,path2);}
  done=findnext(&f); /*查找下一个配匹的文件*/
 }
printf(″\n 当前目录中总共有%d个文件.\n″,num);
 今天上班发现phpmyadmin出现:出现空白页面或无法载入 mysql 扩展。
查了一下原来是php.ini配置有问题:
修改如下:
1. extension_dir = 和PHP实际的ext目录不一致。(默认当前目录)
2. 没有把PHP目录和ext目录添加到环境变量中。(修改path)
3. extension=php_mysql.dll等前的;注释没去掉。(去掉;)
4. Zend安装目录和php.ini中Zend指定的目录不一致。

把上面几种情况检查一下,若还不能解决,请使用其他方法
分页: 261/272 第一页 上页 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 下页 最后页 [ 显示模式: 摘要 | 列表 ]