学海无涯

记录我的程序人生...

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  72 随笔 :: 2 文章 :: 69 评论 :: 11 引用

2006年11月3日 #

http://www.blogjava.net/JaVaa/

1.使用URL:

URL url = new  URL( " ftp://javaa:javaa@172.168.2.222:21/test/javaa.txt " );
PrintWriter pw
= new  PrintWriter(url.openConnection().getOutputStream());
pw.write(
" this is a test " );
pw.flush();
pw.close();

上 面是代码的片断,其中URL构造函数的参数可以用不同的访问协议(比如http,ftp等),"//"后跟着的是用户名和密码,两者用":"隔开,紧跟着 是分隔符"@","@"以后的是IP地址和端口,然后是目录,最后才是我们要写入的文件名,其中目录是必须存在的,否则会抛出 FileNotFoundException,文件可以是不存在的,不存在的时候就会新建文件,否则就会用新的内容覆盖以前的内容;

2.使用FtpClient:

FtpClient ftpClient = new  FtpClient();
ftpClient.openServer(
" 172.168.2.222 " , 21 ); // IP地址和端口
ftpClient.login( " javaa " , " javaa " ); // 用户名和密码,匿名登陆的话用户名为anonymous,密码为非空字符串
ftpClient.cd( " test " ); // 切换到test目录
PrintWriter pw = new  PrintWriter(ftpClient.put( " javaa.txt " )); // 写入的文件名
pw.write( " this is a test " );
pw.flush();
pw.close();

3.用PASV模式传送数据的FtpClient
import sun.net.ftp.FtpClient;
import java.net.Socket;
import java.io.IOException;

public class PasvFtpClient
    
extends FtpClient{

  
/**
   * FTP服务器的地址
   
*/
  
private String serverAddr;
  
/**
   * 连接到FTP服务器的Socket
   
*/
  
private Socket socket;
  
/**
   * 仿造父类定义的静态变量
   
*/
  
protected final static int FTP_ERROR=3;
  
/**
   * 仿造父类定义的静态变量
   
*/
  
protected final static int FTP_SUCCESS=1;

  
public PasvFtpClient(String s) throws IOException{
    
super(s);
    serverAddr
=s;
    socket
=null;
  }

  
public PasvFtpClient(String s,int i) throws IOException{
    
super(s,i);
    serverAddr
=s;
    socket
=null;
  }

  
public PasvFtpClient(){
    
super();
    socket
=null;
  }

  
/**
   * 复写的主要部分,父类采用PORT模式,这里改为PASV模式
   * 
@param s 传入的FTP命令
   * 
@return 连接到FTP服务器的Socket
   * 
@throws IOException
   
*/
  
protected Socket openDataConnection(String s) throws IOException{
    
if (socket==null){
      String s1
="PASV";
      
if (issueCommand(s1)==FTP_ERROR){
        MyFtpProtocolException ftpprotocolexception
=new MyFtpProtocolException(
            
"PASV");
        
throw ftpprotocolexception;
      }
      String responseStr
=this.getResponseString();
      
int location=responseStr.lastIndexOf(",");
      
int n=Integer.parseInt(responseStr.substring(location+1,
          responseStr.indexOf(
")")));
      responseStr
=responseStr.substring(0,location);
      location
=responseStr.lastIndexOf(",");
      
int m=Integer.parseInt(responseStr.substring(location+1,
          responseStr.length()));
      socket
=new Socket(serverAddr,m*256+n);
    }
    
if (issueCommand(s)==FTP_ERROR){
      MyFtpProtocolException ftpprotocolexception1
=new MyFtpProtocolException(s);
      
throw ftpprotocolexception1;
    }
    
return socket;
  }

  
/**
   * 关闭与FTP服务器的连接
   * 
@throws IOException
   
*/
  
public void closeServer() throws IOException{
    socket.close();
    socket
=null;
    
super.closeServer();
  }

  
/**
   * 打开与FTP服务器的连接
   * 
@param s FTP服务器地址
   * 
@param i FTP服务器端口
   * 
@throws IOException
   
*/
  
public void openServer(String s,int i) throws IOException{
    
super.openServer(s,i);
    serverAddr
=s;
  }
}

/**
 * 自定义的FTP异常类
 
*/
class MyFtpProtocolException
    
extends IOException{
  MyFtpProtocolException(String s){
    
super(s);
  }
}
posted @ 2006-11-03 14:47 josson 阅读(990) 评论(0) 编辑

2006年11月1日 #

A.修改linux系统默认的1024个文件上限。
在/root/.bash_profile文件中加入:ulimit -n 4096

B.察看某个进程打开的文件数:
先用ps -aux找到pid,然后运行lsof -p %pid% | wc -l

C.察看80端口的连接数
netstat -nat|grep -i “80″|wc -l

posted @ 2006-11-01 11:29 josson 阅读(329) 评论(0) 编辑

1、查看当前所有连接的详细资料:
./mysqladmin -uadmin -p -h10.140.1.1 processlist


2、只查看当前连接数(Threads就是连接数.):
./mysqladmin  -uadmin -p -h10.140.1.1 status
posted @ 2006-11-01 10:07 josson 阅读(14033) 评论(0) 编辑

2006年9月8日 #

一、对象函数的扩充和代码

扩充函数的对象包括ArrayStringDateNumberBoolean

Array对象扩充函数

函数名

参数

说明

indexOf

_value

返回数组中值等于参数_value的元素索引位置,如果没有返回-1

lastIndexOf

_value

返回数组中值等于参数_value的元素反向索引位置,如果没有返回-1

contains

_value

返回数组中是否存在值等于参数_value的元素,true为存在,false不存在

copy

 

拷贝数组到一个新数组中

insertAt

_value, i

插入参数值_value到参数i指定索引的位置上

insertBefore

_value, _invalue

插入参数值_value到数组中值等于参数_inValue的元素前

removeAt

i

删除索引位置为i的元素

remove

_value

删除值为_value的元素

 

String对象扩充函数

函数名

参数

说明

trim

 

返回去掉前后空白字符的字符串

lTrim

 

返回去掉左边的空白字符的字符串

rTrim

 

返回去掉右边的空白字符的字符串

lTrimZero

 

返回去掉左边的”0”字符的字符串

left

_leftNum

返回左边_leftNum个字符

right

_rightNum

返回右边_rightNum个字符

hasAlpha

 

判断字符串是否有Alpha字符(@#$等非数字字母字符)

isAlpha

 

判断字符串是否完全是Alpha字符

isLetter

 

判断字符串是否完全是字母字符

isFigure

 

判断字符串是否完全是数字字符

isDomainName

 

判断字符串是否是一个合法的域名字符串

isEmail

 

判断字符串是否是一个电子邮件地址

isHex

 

判断字符串是否是十六进制字符

isGuid

 

判断字符串是否是Guid

isInteger

_bitType

判断字符串是否可为指定_bitType类型的整型数(“64bit”||”32bit”||”16bit”)

isInt8

 

判断字符串是否可为int8的整型数

isInt16

 

判断字符串是否可为int16的整型数

isInt32

 

判断字符串是否可为int32的整型数

isInt64

 

判断字符串是否可为int64的整型数

toDate

 

将字符串转换成时间类型数值,能够转成合法Date的字符形如:yyyy-mm-dd or yyyy/mm/dd

toNumber

 

将字符串转换成为数字类型数值

 

Date对象扩充函数

函数名

参数

说明

getQuarter

 

返回时间的季度值

dateAdd

_timeInterval, _number

返回间隔_number量的时间,_timerInterval为间隔类型,分别有年(yyyy),月(mm),日(dd),时(h),分(m),秒(s),星期(ww)

formatDateTime

_nameFormate

返回时间的格式化字符串,_nameFormate为格式类型,此函数可参考vbs同名函数

isNaN

 

时间变量是否是合法的,true为非法变量,false为合法的。

 

Number对象扩充函数

函数名

参数

说明

abs

 

返回值的绝对值

acos

 

返回值以弧度为单位的反余弦

asin

 

返回值以弧度为单位的反正弦

atan

 

返回值以弧度为单位的反正切

atan2

_value

返回值与_value的商的反正切

ceil

 

返回大于等于值的下一个整数

cos

 

返回值的余弦

exp

 

返回值的欧拉常量

floor

 

返回小于值等于值的整数

log

 

返回值以e为底的自然对数

round

 

返回值四舍五入后的数

sin

 

返回值以弧度为单位的正弦

sqrt

 

返回值的平方根

isNaN

 

判断是否是一个合法的数值

tan

 

返回值以弧度为单位的正切

 

浏览器中上述对象扩充了两个消息提示函数alertcofirm,可以直接使用对象引用函数来弹出消息框。

 

 

 

 

代码部分:

-----------------------------------------------------------------------------------------------------------------------

Array.prototype.indexOf = function(_value){

         for(var i=0;i<this.length;i++)if(this[i]==_value)return i;

         return -1;

};

Array.prototype.lastIndexOf = function(_value){

         for(var i=this.length-1;i>=0;i--)if(this[i]==_value)return i;

         return -1;

};

Array.prototype.contains = function(_value){return this.indexOf(_value)!= -1;};

Array.prototype.copy = function(){return this.concat();};

Array.prototype.insertAt = function(_value,i){this.splice(i,0,_value);};

Array.prototype.insertBefore = function(_value,_inValue){

         var i=this.indexOf(_inValue);

         if(i== -1)this.push(_value);

         else this.splice(i,0,_value);

};

Array.prototype.removeAt = function(i){this.splice(i,1);};

Array.prototype.remove = function(_value){

         var i=this.indexOf(_value);

         if(i!= -1)this.splice(i,1);

};

 

String.prototype.trim = function(){return this.replace(/(^\s+)|\s+$/g,"");};

String.prototype.lTrim = function(){return this.replace(/(^\s+)/g,"")};

String.prototype.rTrim = function(){return this.replace(/(\s+$)/g,"")};

String.prototype.lTrimZero = function(){return this.replace(/(^0+)/g,"")};

String.prototype.left = function(_leftNum){return this.substr(0,_leftNum)};

String.prototype.right = function(_rightNum){return this.substr(this.length - _rightNum)};

String.prototype.hasAlpha = function(){

         var _checkAlpha = /[\/\\\.\*\+\?\|\(\)\{\}\[\]\-~`!@#$%^&_=:;"'<>,.]/;

         return(_checkAlpha.test(this));

};

String.prototype.isAlpha = function(){

         var _checkAlpha = /[^\/\\\.\*\+\?\|\(\)\{\}\[\]\-~`!@#$%^&_=:;"'<>,.]/;

         return(!_checkAlpha.test(this));

};

String.prototype.isLetter = function(){return(!(/\W/.test(this)||/\d/.test(this)));};

String.prototype.isFigure = function(){return(!/\D/.test(this));};

String.prototype.isDomainName = function(){return(!/[^\w-_\.]|^\.|\.$/.test(this));};

String.prototype.isEmail = function(){

         var _emailList = this.split("@");

         if(_emailList.length != 2)return false;

         return((!/[^\w-_]/.test(_emailList[0]))&&_emailList[1].isDomainName());

};

String.prototype.isHex = function(){return(!/[^\dABCDEFabcdef]/.test(this));};

String.prototype.isGuid = function(){

         if(this.left(1)!="{"||this.right(1)!="}")return false;

         var _hexNumberList = this.replace(/(^\{)|(\}$)/g,"").split("-");

         if(_hexNumberList.length!=5)return false;

         if(_hexNumberList[0].length!=8||!_hexNumberList[0].isHex())return false;

         if(_hexNumberList[1].length!=4||!_hexNumberList[1].isHex())return false;

         if(_hexNumberList[2].length!=4||!_hexNumberList[2].isHex())return false;

         if(_hexNumberList[3].length!=4||!_hexNumberList[3].isHex())return false;

         if(_hexNumberList[4].length!=12||!_hexNumberList[4].isHex())return false;

         return true;

};

String.prototype.isInteger = function(_bitType){

         var _limitValue = [];

         _limitValue["Upper"] = [];

         _limitValue["Lower"] = [];

         _limitValue["Upper"]["64bit"] = "9223372036854775807";

         _limitValue["Upper"]["32bit"] = "2147483647";

         _limitValue["Upper"]["16bit"] = "32767";

         _limitValue["Lower"]["64bit"] = "9223372036854775808";

         _limitValue["Lower"]["32bit"] = "2147483648";

         _limitValue["Lower"]["16bit"] = "32768";

         var _plus = "Upper";

         var _theValue = new String(this);

         if(_theValue.indexOf("-")==0){

                   _theValue = _theValue.substr(1,_theValue.length-1);

                   _plus = "Lower";

         }      

         if(!_theValue.isFigure())return false;

         if(_limitValue[_plus][_bitType].length < _theValue.length)return false;

         if(_limitValue[_plus][_bitType].length == _theValue.length){

                   for(var i=0;i<_limitValue[_plus][_bitType].length;i++){

                            if(_theValue.charAt(i) < _limitValue[_plus][_bitType].charAt(i))return true;

                   }

                   if(_limitValue[_plus][_bitType] != _theValue)return false;

         }

         return true;

};

String.prototype.isInt8 = function(){

         var _theValue = this.toNumber();

         if(_theValue.isNaN())return false;

         if(_theValue < 0 || _theValue > 255)return false;

         if(_theValue.toString() != this)return false;

         return true;

};

String.prototype.isInt16 = function(){return this.isInteger("16bit");};

String.prototype.isInt32 = function(){return this.isInteger("32bit");};

String.prototype.isInt64 = function(){return this.isInteger("64bit");};

String.prototype.toDate = function(){

         var _dateStr = this.trim().split(/\s/)[0];

         var _timeStr = (this.trim().split(/\s/)[1]?this.trim().split(/\s/)[1]:"1:1:1");

         var _dateSplitSymbol = /[\/\-,]/;

         var _timeSplitSymbol = /[:,]/;

 

         if(!_dateSplitSymbol.test(_dateStr))return new Date("x");

         var _SplitSymbol = _dateSplitSymbol.exec(_dateStr);

         var _dateList = [];

         if(_SplitSymbol == ""){

                   if(!(_dateStr.indexOf("") > _dateStr.indexOf("") && _dateStr.indexOf("") > _dateStr.indexOf("") && _dateStr.indexOf("")> 1))return new Date("x");

                   _dateList = _dateStr.split(/[年月日]/);

         }else _dateList = _dateStr.split(_SplitSymbol);

         if(_dateList.length < 2)return new Date("x");

 

         var _timeList = [1,1,1];

         if(_timeSplitSymbol.test(_timeStr)){

                   _SplitSymbol = _timeSplitSymbol.exec(_timeStr);

                   if(_SplitSymbol == ""){

                            if(!(_timeStr.indexOf("") > _timeStr.indexOf("") && _timeStr.indexOf("") > _timeStr.indexOf("") && _timeStr.indexOf("")> 1))return new Date("x");

                            _timeList = _timeStr.split(/[时分秒]/);

                   }else _timeList = _timeStr.split(_SplitSymbol);

         }

         return new Date(_dateList[0],_dateList[1],_dateList[2],_timeList[0],_timeList[1],_timeList[2]);

};

String.prototype.toNumber = function(){return new Number(this)};

 

 

Date.prototype.getQuarter = function(){return ((this.getMonth()+1)/3).ceil();};

Date.prototype.dateAdd = function(_timeInterval,_number){

         switch(_timeInterval.toUpperCase()){

                   case "YYYY":

                            return new Date(this.getFullYear() + _number,this.getMonth(),this.getDate(),this.getHours(),this.getMinutes(),this.getSeconds());

                            break;

                   case "MM":

                            return new Date(this.getFullYear(),this.getMonth() + _number,this.getDate(),this.getHours(),this.getMinutes(),this.getSeconds());

                            break;

                   case "DD":

                            return new Date(this.getFullYear(),this.getMonth(),this.getDate() + _number,this.getHours(),this.getMinutes(),this.getSeconds());

                            break;

                   case "H":

                            return new Date(this.getFullYear(),this.getMonth(),this.getDate(),this.getHours() + _number,this.getMinutes(),this.getSeconds());

                            break;

                   case "M":

                            return new Date(this.getFullYear(),this.getMonth(),this.getDate(),this.getHours(),this.getMinutes() + _number,this.getSeconds());

                            break;

                   case "S":

                            return new Date(this.getFullYear(),this.getMonth(),this.getDate(),this.getHours(),this.getMinutes(),this.getSeconds() + _number);

                            break;

                   case "WW":

                            return new Date(this.getFullYear(),this.getMonth(),this.getDate() + _number*7,this.getHours(),this.getMinutes(),this.getSeconds());

                            break;

                   default:return this;

         }

};

Date.prototype.formatDateTime = function(_nameFormate){

         switch(_nameFormate){

                   case 0:

                            return this.getFullYear().toString().right(2) + "/" + (this.getMonth() + 1).toString() + "/" + this.getDate().toString() + " " + this.getHours().toString() + ":" + this.getMinutes().toString() + ":" + this.getSeconds().toString();

                            break;

                   case 1:

                            return this.getFullYear().toString() + "" + (this.getMonth() + 1).toString() + "" + this.getDate().toString() + "";

                            break;

                   case 2:

                            return this.getFullYear().toString().right(2) + "/" + (this.getMonth() + 1).toString() + "/" + this.getDate().toString();

                            break;

                   case 3:

                            return this.getHours().toString() + ":" + this.getMinutes().toString() + ":" + this.getSeconds().toString();

                            break;

                   case 4:

                            return this.getHours().toString() + ":" + this.getMinutes().toString();

                            break;

                   default:

                            return this.getFullYear().toString().right(2) + "/" + (this.getMonth() + 1).toString() + "/" + this.getDate().toString() + " " + this.getHours().toString() + ":" + this.getMinutes().toString() + ":" + this.getSeconds().toString();

         }

};

Date.prototype.isNaN = function(){return isNaN(this);};

 

Number.prototype.abs = function(){return Math.abs(this)};

Number.prototype.acos = function(){return Math.acos(this)};

Number.prototype.asin = function(){return Math.asin(this)};

Number.prototype.atan = function(){return Math.atan(this)};

Number.prototype.atan2 = function(){return Math.atan2(this)};

Number.prototype.ceil = function(){return Math.ceil(this)};

Number.prototype.cos = function(){return Math.cos(this)};

Number.prototype.exp = function(){return Math.exp(this)};

Number.prototype.floor = function(){return Math.floor(this)};

Number.prototype.log = function(){return Math.log(this)};

Number.prototype.round = function(){return Math.round(this)};

Number.prototype.sin = function(){return Math.sin(this)};

Number.prototype.sqrt = function(){return Math.sqrt(this)};

Number.prototype.isNaN = function(){return isNaN(this)};

Number.prototype.tan = function(){return Math.tan(this)};

 

 

if(window){

         Array.prototype.alert = function(){window.alert(this);}

         Array.prototype.confirm = function(){return window.confirm(this);}

         String.prototype.alert = function(){window.alert(this)};

         String.prototype.confirm = function(){return window.confirm(this)};

         Date.prototype.alert = function(){window.alert(this.toLocaleDateString());};

         Date.prototype.confirm = function(){return window.confirm(this.toLocaleDateString());};

         Number.prototype.alert = function(){window.alert(this)};

         Number.prototype.confirm = function(){return window.confirm(this)};

         Boolean.prototype.alert = function(){window.alert(this);};

         Boolean.prototype.confirm = function(){return window.confirm(this);};

}

-----------------------------------------------------------------------------------------------------------------------

 

 

二、关于prototype属性

 

JavaScript1.1中,几个基本对象StringRegExpArrayDateNumberBooleanFunction增加了一个原型(prototype)属性,该属性容许程序员向已有对象原型添加新的属性和函数。其用法如下:

function obj(){

         this.id = “”;

}

obj.prototype.set_id = function(_value){

         this.id = _value;

}

var obj1 = new obj();

obj1.set_id(“test”);

通过prototype属性给obj类(事实上不是类,而是一个函数,这里只是为了方便表述)创建了一个函数(给set_id赋值为一个函数)。

prototype对于自定义的伪类意义不是很大,因为自定义的伪类也完全可以在构造函数中创建。

但是它对于已有的JavaScript对象类型的函数扩充有着比较重要的意义,通过prototype,可以给JS基本对象扩充新的函数。例如在js中没有类似于vbs中的trim函数,倘若单独把trim函数以及其他有用的函数写成一个独立的函数库,又失去了js脚本的那种语言简洁的特点。最理想的情况是将它扩充到已有的对象原型中去。

看看一些有趣的例子:

(“ 1234 ”).trim().alert(); //弹出一个对话框提示为1234

 

if(text1.value.toDate().isNaN())alert(“date input error!”); //在一个文本框中输入时间,格式不正确提示错误!

 

 

扩充的函数中比较有实用的是String的函数,trimleftrightisXXX等函数在表单的验证当中是比较常用的。

posted @ 2006-09-08 16:32 josson 阅读(638) 评论(0) 编辑

2006年8月3日 #

摘要: 字母A开头函数函数名: abort功 能: 异常终止一个进程用 法: void abort(void);程序例:#include <stdio.h>#include <stdlib.h>int main(void){printf("Calling abort()\n");abort();return 0; /* This is never reached */}函数名: a...阅读全文
posted @ 2006-08-03 13:18 josson 阅读(873) 评论(0) 编辑

摘要: 原文: http://blog.csdn.net/shaohui/archive/2004/11/05/167969.aspx分类函数,所在函数库为ctype.hint isalpha(int ch) 若ch是字母('A'-'Z','a'-'z')返回非0值,否则返回0int isalnum(int ch) 若ch是字母('A'-'Z','a'-'z')或数字('0'-'9') 返回非0值,否则返...阅读全文
posted @ 2006-08-03 13:16 josson 阅读(453) 评论(0) 编辑

2006年6月27日 #

在 MySQL 中,数据库和表对就于那些目录下的目录和文件。因而,操作系统的敏感性决定数据库和表命名的大小写敏感。这就意味着数据库和表名在 Windows 中是大小写不敏感的,而在大多数类型的 Unix 系统中是大小写敏感的。

奇怪的是列名与列的别名在所有的情况下均是忽略大小写的,而表的别名又是区分大小写的。

要避免这个问题,你最好在定义数据库命名规则的时候就全部采用小写字母加下划线的组合,而不使用任何的大写字母。

或者也可以强制以 -O lower_case_table_names=1 参数启动 mysqld(如果使用 --defaults-file=...\my.cnf 参数来读取指定的配置文件启动 mysqld 的话,你需要在配置文件的 [mysqld] 区段下增加一行 lower_case_table_names=1)。这样MySQL 将在创建与查找时将所有的表名自动转换为小写字符(这个选项缺省地在 Windows 中为 1 ,在 Unix 中为 0。从 MySQL 4.0.2 开始,这个选项同样适用于数据库名)。

当你更改这个选项时,你必须在启动 mysqld 前首先将老的表名转换为小写字母。

换句话说,如果你希望在数据库里面创建表的时候保留大小写字符状态,则应该把这个参数置0: lower_case_table_names=1 。否则的话你会发现同样的sqldump脚本在不同的操作系统下最终导入的结果不一样(在Windows下所有的大写字符都变成小写了)。

posted @ 2006-06-27 14:06 josson 阅读(523) 评论(0) 编辑

2006年4月19日 #

摘要: 建立表空间CREATE TABLESPACE data01DATAFILE '/oracle/oradata/db/DATA01.dbf' SIZE 500MUNIFORM SIZE 128k; #指定区尺寸为128k,如不指定,区尺寸默认为64k删除表空间DROP TABLESPACE data01 INCLUDING CONTENTS AND DATAFILES;一、建立表空间CREATE T...阅读全文
posted @ 2006-04-19 13:59 josson 阅读(730) 评论(0) 编辑

2006年4月6日 #

摘要: 在Linux中通过locale来设置程序运行的不同语言环境,locale由ANSI C提供支持。locale的命名规则为<语言>_<地区>.<字符集编码>,如zh_CN.UTF-8,zh代表中文,CN代表大陆地区,UTF-8表示字符集。在locale环境中,有一组变量,代表国际化环境中的不同设置:1. LC_COLLATE定义该环境的排序和比较规则2. LC_C...阅读全文
posted @ 2006-04-06 16:36 josson 阅读(1890) 评论(0) 编辑

摘要: 经常有同事咨询oracle数据库字符集相关的问题,如在不同数据库做数据迁移、同其它系统交换数据等,常常因为字符集不同而导致迁移失败或数据库内数据变成乱码。现在我将oracle字符集相关的一些知识做个简单总结,希望对大家今后的工作有所帮助。  一、什么是oracle字符集  Oracle字符集是一个字节数据的解释的符号集合,有大小之分,有相互的包容关系。ORACLE 支持国家语言的体系结构允许你使用...阅读全文
posted @ 2006-04-06 14:49 josson 阅读(516) 评论(0) 编辑