Perl 为 Festival 编写的 Emacspeak speech server

下面是编程之家 jb51.cc 通过网络收集整理的代码片段。

编程之家小编现在分享给大家,也给大家做个参考。

#!/usr/bin/perl

# EmacSpeaks Festival
#
# A Emacspeak speech server for Festival written in Perl.
# Written by Mario Lang <[email protected]>
# Enhancements by Aaron Bingham <[email protected]>
# The skeleton was taken from speechd (and modified alot of course).

use strict;

# Configuration

my $USE_ESD = 1; 

    # If nonzero use the Enlightened Sound Daemon for managing the
    # Festival server,otherwise run Festival directly.  Overridden by
    # FESTIVAL_COMMAND

my $LOGFILE = '/tmp/festival.log'; 

    # File to use for logging debugging messages.

my $FESTIVAL_HOST = 'localhost'; 

    # Hostname where Festival server is running.  If FESTIVAL_HOST is
    # 'localhost',a Festival server process will be started
    # automatically if none is currently running.

my $FESTIVAL_PORT = '1314'; 

    # Port Festival server listens to.

my $FESTIVAL_BIN = '/usr/bin/festival'; 

    # Path to Festival executable.

my $FESTIVAL_ARGS = '--server \'(set! server_access_list (list "localhost\.localdomain"))\'';

    # Arguments for the Festival process.  The default starts a server
    # process accessible to any user on the local machine.

my $FESTIVAL_ASYNC = 1; 

    # Use Festival in asynchronous mode if nonzero,otherwise use
    # synchronous mode.  Asynchronous mode allows the client to stop
    # in-progress speech,so the result is generally more responsive
    # behavior.  However,some users have complained that asynchronous
    # mode causes too many utterances to be surpressed (e.g. letter
    # names while typing fast).  If this is a problem for you,set
    # $FESTIVAL_ASYNC = 0.

my $SPEAKER_1 = 'rab_diphone';
my $SPEAKER_2 = 'kal_diphone';

    # Name of the festival speakers to use.  Change this to voices you have
    # installed.

# Internal variables

my $FILE_STUFF_KEY = 'ft_StUfF_key'; # This indicates a new prompt from Festival
my $handle      = undef;                      # this is for the tcp connection...

my $queued_text = '';

my $FESTIVAL_COMMAND;
if ($USE_ESD) {
    $FESTIVAL_COMMAND = "esddsp $FESTIVAL_BIN $FESTIVAL_ARGS &";
} else {
    $FESTIVAL_COMMAND = "$FESTIVAL_BIN $FESTIVAL_ARGS &";
}

#includes libs for TCP socket connection to Festival
use IO::Socket;

my $err = 0;
my $pronounce_punctuation = 0;
my $emacs_in_braces = 0;
my @pq_queues = ([],[]);
my %sable_params = ('speaker'=>$SPEAKER_1,'rate'=>1,'base'=>150,'range'=>10,'mid'=>1);
my $festival_busy = 0;
my $emacs_lines = 0;
my $line_number = 0;

sub main {

    my $emacstext = '';
    my $festtext = '';

    &log("INIT: FESTIVAL_COMMAND = $FESTIVAL_COMMAND\n");
    # create a tcp connection to the festival server
    &connect_to_festival();
    &log("INIT: Starting loop.\n");

    # If Festival closes the connection,try to reconnect
    local $SIG{PIPE} = \&connect_to_festival;

    my $info;

    while (1) {
        my $rin;
        vec($rin,fileno(STDIN),1) = 1;
        vec($rin,fileno($handle),1) = 1;
        select($rin,undef,undef);
        if (vec($rin,1)) {
	   my $buf;
	   sysread STDIN,$buf,1024;
	   if (!$buf) {
	       &log("Unexpected EOF in STDIN\n");
	       exit 1;
	   }
	   $emacstext .= $buf;
	   $emacstext = &handle_emacs_input($emacstext);	
        }
        if (vec($rin,1)) {
	   my $buf;
	   sysread $handle,1024;
	   if (!$buf) {
	       &log("Unexpected EOF in Festival socket\n");
	       exit 1;
	   }
	   $festtext .= $buf;
	   $festtext = &handle_festival_input($festtext);
        }
        &log("\$festival_busy = $festival_busy\n");
        while (!$festival_busy && !&pq_empty()) {
	   &send_command;
        }
    }
}

sub log {
    # Write a message to the logfile
    my $msg = shift;
    open(LOG,">>$LOGFILE") or die "Cant open logfile\n";
    print LOG $msg;
    close LOG;
}

sub handle_emacs_input {
    my $emacstext = shift;
    while (1) {
	my ($line,$eol,$remainder) = split /(\n)/,$emacstext,2;
	last if !$eol;
	$emacstext = $remainder;
	&handle_emacs_line($line . $eol);
    }
    return $emacstext;
}


sub handle_emacs_line {
    my $line = shift;
    &log("emacspeak: $line");
    $emacs_lines .= $line;
    if ($line =~ /{[^}]*\n/) {
	$emacs_in_braces = 1;
    } elsif ($line =~ /}/) {
        $emacs_in_braces = 0;
    }
    if (!$emacs_in_braces) {
        handle_emacs_command($emacs_lines);
	$emacs_lines = '';
    }
}

sub handle_festival_input {
    my $festtext = shift;
    while (1) {
	my ($line,$festtext,2;
	last if !$eol;
	$festtext = $remainder;
	&handle_festival_line($line . $eol);
    }
    return $festtext;
}

sub handle_festival_line {
    my $text = shift;
    &log("festival: $text");

    if ($text =~ /^$FILE_STUFF_KEY/) {
	$festival_busy = 0;
    } elsif ($text =~ /^(OK|ER)/) {
	# the festival session is in a wierd state.  reconnect.
	&log("the festival is in a wierd state.  reconnect.\n");
	&send_to_festival("(quit)");
	&connect_to_festival();
    }
}

sub handle_emacs_command {
    my $text = shift;
    if ($text =~ /^\s*exit\n/) {
        &quit();
    } elsif ($text =~ /^\s*q\s+\{(.*)}/s) {
        &queue_speech($1);
    } elsif ($text =~ /^\s*t\s+(\d+)\s(\d+)/) {
	&tone($1,$2);
    } elsif ($text =~ /^\s*p\s+(.*)\n/) {
	&play_sound($1);
    } elsif ($text =~ /^\s*d/) {
        &flush_speech();
    } elsif ($text =~ /^\s*tts_say \{(.*)\}/) {
	&say($1);
    } elsif ($text =~ /^\s*l \{([^}])\}/) {
	&letter($1);
    } elsif ($text =~ /^\s*s/) {
	&stop();
    } elsif ($text =~ /^\s*tts_set_punctuations (\w+)/) {
	&set_punctuation($1);
    } elsif ($text =~ /^\s*tts_set_speech_rate (\d+)/) {
	&set_speech_rate($1)
    } elsif ($text =~ /^\s*tts_sync_state (\w+) (\d+) (\d+) (\d+) (\d+)/) {
	&set_punctuation($1);
	&set_speech_rate($5);
    } else {
       $err++;
       &log("$line_number: err$err: $text\n");
    }
    return 1;
}

# Actions

sub quit {
    &pq_clear();
    &stop();
    &send_to_festival("(quit)");
    exit 0;
}

sub tone {
    my $pitch = shift; # pitch in Hz
    my $duration = shift; # duration in ms

    # Run asynchronously for better responsiveness
    system("beep -f $pitch -l $duration &");
}

sub play_sound {
    my $filename = shift;
    my $url = "file://" . &url_quote($filename);
    &send_sable("<SABLE><AUDIO SRC=\"$url\"/></SABLE>");
}

sub flush_speech {
    # Flush all queued speech to the speech generator.
    if ($queued_text ne '') {
        speak($queued_text);
    }
    $queued_text = '';
}

sub letter {
    my $char = shift;
    my $content = &sgml_quote($char);
    &send_sable("<SABLE><SAYAS MODE=\"literal\">$content</SAYAS></SABLE>");
}

sub set_punctuation {
    my $mode = shift;
    if ($1 eq "all") {
	$pronounce_punctuation = 1;
    } else {
	$pronounce_punctuation = 0;
    }
}

sub set_speech_rate {
    my $dtk_rate = shift;
    # 225.0 was picked as it gives reasonable behavior.  I do not
    # know if the result is slower or faster than the DECTalk.
    $sable_params{'rate'} = $dtk_rate/225.0;
}

sub stop {
    # The queue must be cleared immediately so that any queued
    # commands recieved before the stop do not get run afterwards.    
    &pq_clear(); 
    $queued_text = '';
    if ($FESTIVAL_ASYNC) {
	&send_to_festival("(audio_mode 'shutup)");
    }
}

sub queue_speech {
    # Save speech to be sent later.
    my $text = shift;
    $queued_text .= $text;
}

sub say {
    my $text = shift;
    &speak($text);
}

sub speak {
    my $text = shift;
    if ($text =~ /\S+/) {
        foreach my $sable (&dtk_to_sable($text)) {
  	    &send_sable($sable);
        }
    } else { 
        &log("$line_number: Empty queue,nothing sent. \n"); 
    }
}

sub send_sable {
    my $sable = shift;
    $sable =~ s/"/\\"/g;
    &send_to_festival("(tts_text \"$sable\" 'sable)");
}

sub dtk_to_sable {
    my $dtk = shift;
    my @items = &dtk_parse($dtk);

    # '[*]' seems to be used as an alternative (perhaps shorter) to 
    # a space character.

    $dtk =~ s/\[\*\]/ /;

    my @sable_docs = ();
    foreach my $item (@items) {
        my $type = $item->[0];
        my $value = $item->[1];
	&log("($type,$value)\n");
        if ($type eq 'TEXT') {
            push @sable_docs,&text_to_sable($value);
        } elsif ($type eq 'COMMAND') {
	    $value =~ s/\s+//; # trim leading whitespace
            &handle_dtk_command(split /\s+/,$value);
        }
    }
    return @sable_docs;
}

sub dtk_parse {
    my $dtk = shift;

    # Return a list of (type,value) tuples,where type is either
    # COMMAND or TEXT.

    my $in_command = 0;
    my @items = ();
    my $value = '';
    for (my $i = 0; $i <= length $dtk; $i++) {
        my $ch = substr $dtk,$i,1;
	if ($ch eq '[') {
            if (!$in_command) {
  	        if ($value ne '') {
		    my @item = ('TEXT',$value);
		    push @items,\@item;
  	        }
            } else {
                &log("ERROR: [ found while looking for ]\n");
            }
	    $in_command = 1;
   	    $value = '';
        } elsif ($ch eq ']') {
            if ($in_command) {
  	        if ($value ne '') {
		    my @item = ('COMMAND',\@item;
	        }
            } else {
                &log("ERROR: ] found while looking for [\n");
            }
	    $in_command = 0;
   	    $value = '';
        } else {
            $value .= $ch;
	}
    }
    if ($value ne '' && !$in_command) {
	my @item = ('TEXT',$value);
        push @items,\@item;
    }
    if ($in_command) {
        &log("ERROR: ] expected\n");
    }

    return @items;
}
	    

sub handle_dtk_command {
    my @cmdlist = @_;
    &log ("cmdlist: @cmdlist\n");
    &log ("cmdlist[0]: $cmdlist[0]\n");
    if ($cmdlist[0] =~ /:np/) {
	$sable_params{'speaker'} = $SPEAKER_1;
	$sable_params{'base'} = 100;
        $sable_params{'range'} = 10;
    } elsif ($cmdlist[0] =~ /:nh/) {
	$sable_params{'speaker'} = $SPEAKER_2;
	$sable_params{'base'} = 100;
        $sable_params{'range'} = 10;
    } elsif ($cmdlist[0] =~ /:nd/) {
	$sable_params{'speaker'} = $SPEAKER_1;
	$sable_params{'base'} = 150;
        $sable_params{'range'} = 10;
    } elsif ($cmdlist[0] =~ /:nf/) {
	$sable_params{'speaker'} = $SPEAKER_2;
	$sable_params{'base'} = 150;
        $sable_params{'range'} = 10;
    } elsif ($cmdlist[0] =~ /:nb/) {
	$sable_params{'speaker'} = $SPEAKER_1;
	$sable_params{'base'} = 200;
        $sable_params{'range'} = 10;
    } elsif ($cmdlist[0] =~ /:nu/) {
	$sable_params{'speaker'} = $SPEAKER_2;
	$sable_params{'base'} = 200;
        $sable_params{'range'} = 10;
    } elsif ($cmdlist[0] =~ /:nr/) {
	$sable_params{'speaker'} = $SPEAKER_1;
	$sable_params{'base'} = 300;
        $sable_params{'range'} = 10;
    } elsif ($cmdlist[0] =~ /:nw/) {
	$sable_params{'speaker'} = $SPEAKER_2;
	$sable_params{'base'} = 300;
        $sable_params{'range'} = 10;
    } elsif ($cmdlist[0] =~ /:nk/) {
	$sable_params{'speaker'} = $SPEAKER_1;
	$sable_params{'base'} = 400;
        $sable_params{'range'} = 10;
    } elsif ($cmdlist[0] =~ /:dv/) {
	&log ("cmdlist (dv): @cmdlist\n");
	for (my $j = 1; $j <= $#cmdlist; $j+=2) {
	    print "param: $cmdlist[$j] $cmdlist[$j+1]\n";
	    if ($cmdlist[$j] =~ /ap/) {
                # Average pitch (Hz)
		$sable_params{'base'} = $cmdlist[$j+1];
	    }
	    if ($cmdlist[$j] =~ /pr/) {
                # Pitch range.  The Dectalk parameter ranges between 0
                # -- a flat monnotone -- and 250 -- a highly animated
                # voice.
		$sable_params{'range'} = 2.0*sqrt(5.0*$cmdlist[$j+1]);
	    }
	}
    }
}

sub text_to_sable {
    my $text = shift;

    # Convert a string of plain text to a SABLE document,using the current
    # parameters.

    if ($pronounce_punctuation) {
	$text =~ s/[`]/ backquote /g;
	$text =~ s/[!]/ bang /g;
	$text =~ s/[(]/ left paren /g;
	$text =~ s/[)]/ right paren /g;
	$text =~ s/[-]/ dash /g;
	$text =~ s/[{]/ left brace /g;
	$text =~ s/[}]/ right brace /g;
	$text =~ s/[:]/ colon /g;
	$text =~ s/[;]/ semi /g;
	$text =~ s/["]/ quotes /g;
	$text =~ s/[']/ apostrophe /g;
	$text =~ s/[,]/ comma /g;
	$text =~ s/[.]/ dot /g;
	$text =~ s/[?]/ question /g;
    }
    # escape SGML-unsafe characters
    $text = sgml_quote($text);

    return <<HERE
<SABLE>
 <SPEAKER NAME="$sable_params{'speaker'}">
  <RATE SPEED="$sable_params{'rate'}">
   <PITCH BASE="$sable_params{'base'}" 
          RANGE="$sable_params{'range'}" 
          MID="$sable_params{'mid'}">
    $text
   </PITCH>
  </RATE>
 </SPEAKER>
</SABLE>
HERE
}

sub sgml_quote {
    my $text = shift;
    $text =~ s/&/&amp;/g;
    $text =~ s/</&lt;/g;
    $text =~ s/>/&gt;/g;
    return $text;
}

sub url_quote {
    # XXX: incomplete!
    my $text = shift;
    $text =~ s/ /%20/;
    return $text;
}

sub send_to_festival {
    my $command = shift;
    # queue $command for sending to Festival
    &pq_push($command,1);
}

sub send_command {
    # send a single queued command
    if ($handle) {   # Sanity checks are always nice...
	&send_direct(&pq_pop());
    } else {
	&connect_to_festival;
    }
}

sub send_direct {
    my $command = shift;
    # send $command to festival immediately,without affecting the queue
    &log("$line_number: festival> " . $command . "\n");
    print($handle $command . "\n") or die "Could not write to Festival ($!)\n";
    $festival_busy = 1;
}


sub connect_to_festival
{
  my $tries = 0;
  my $MAX_RECONNECT_TRIES = 10;
  $handle = '';
  while ($handle eq '' and $tries < $MAX_RECONNECT_TRIES)
  {
    &log("($tries) Attempting to connect to the Festival server.\n");
    if ($handle = IO::Socket::INET->new(Proto     => 'tcp',PeerAddr  => $FESTIVAL_HOST,PeerPort  => $FESTIVAL_PORT))
    {
      &log("Successfully opened connection to Festival.\n");
    } else
    {
      if ($tries)
      {
        &log("Waiting for Festival server to load -- Can't connect to port $FESTIVAL_PORT on $FESTIVAL_HOST yet ($!).\n");
      } else
      {
        if ($FESTIVAL_HOST eq 'localhost') {
          &log("Failed to connect to Festival server,attempting to load it myself.\n");
          system ($FESTIVAL_COMMAND);
        }
      }
      sleep 1;
    }
    $tries++;
  }

  if ($handle eq '') {
      die "ERROR: can't connect to Festival server!";
  }

  $handle->autoflush(1);     # so output gets there right away

  $festival_busy = 0;

  if ($FESTIVAL_ASYNC) {
      # Set festival to async mode.  We have to call send_direct here to
      # ensure that no commands from emacspeak hava a chance to get
      # executed before this one.

      &send_direct("(audio_mode 'async)");
  }

}

#
# priority queue implementation
#

sub pq_push {
    my $item = shift;
    my $pri = shift;
    push @{$pq_queues[$pri]},$item;
}

sub pq_pop {
    for (my $i = 0; $i <= $#pq_queues; $i++) {
	if ($#{$pq_queues[$i]} >= 0) {
	    my $item = shift @{$pq_queues[$i]};
	    return $item;
        }
    }
}

sub pq_clear {
    for (my $i = 0; $i <= $#pq_queues; $i++) {
	$pq_queues[$i] = [];
    }
}

sub pq_empty {
    for (my $i = 0; $i <= $#pq_queues; $i++) {
	if ($#{$pq_queues[$i]} >= 0) {
	    return 0;
        }
    }
    return 1;
}

&main();

__END__

=head1 NAME

festival-server - Emacspeak server for the Festival speech synthesizer

=head1 SYNOPSIS

speechd 

=head1 DESCRIPTION

festival-server is a perl script doing Emacspeak server syntax
to festival conversion.
This method makes use of the SABLE markup mode of festival.

Tones are supported if you have beep installed.

=head1 OPTIONS

=head1 FILES

=over 4

=item
/usr/share/emacs/site-lisp/emacspeak/festival-server

以上是编程之家(jb51.cc)为你收集整理的全部代码内容,希望文章能够帮你解决所遇到的程序开发问题。

如果觉得编程之家网站内容还不错,欢迎将编程之家网站推荐给程序员好友。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


1. 如何去重 #!/usr/bin/perl use strict; my %hash; while(&lt;&gt;){ chomp; print &quot;$_n&quot; unless
最近写了一个perl脚本,实现的功能是将表格中其中两列的数据进行拼凑,然后将拼凑后的数据用“|”连接在一起。表格内容如下: 员工号码员工姓名职位入职日期1001张三销售1980/12/17 0:00:
表的数据字典格式如下:如果手动写MySQL建表语句,确认麻烦,还不能保证书写一定正确。写了个Perl脚本,可快速构造MySQL脚本语句。脚本如下:#!/usr/bin/perluse strict;m
巡检类工作经常会出具日报,最近在原有日报的基础上又新增了一个表的数据量统计日报,主要是针对数据库中使用较频繁,数据量又较大的31张表。该日报有两个sheet组成,第一个sheet是数据填写,第二个sh
在实际生产环境中,常常需要从后台日志中截取报文,报文的形式类似于.........一个后台日志有多个报文,每个报文可由操作流水唯一确定。以前用AWK写过一个,程序如下:beginline=`awk &
最近写的一个perl程序,通过关键词匹配统计其出现的频率,让人领略到perl正则表达式的强大,程序如下:#!/usr/bin/perluse strict;my (%hash,%hash1,@arra
忍不住在 PerlChina 邮件列表中盘点了一下 Perl 里的 Web 应用框架(巧的是 PerlBuzz 最近也有一篇相关的讨论帖),于是乎,决定在我自己的 blog 上也贴一下 :) 原生 CGI/FastCGI 的 web app 对于较小的应用非常合适,但稍复杂一些就有些痛苦,但运行效率是最高的 ;) 如果是自己用 Perl 开发高性能的站,多推荐之。 Catalyst, CGI::A
bless有两个参数:对象的引用、类的名称。 类的名称是一个字符串,代表了类的类型信息,这是理解bless的关键。 所谓bless就是把 类型信息 赋予 实例变量。 程序包括5个文件: person.pm :实现了person类 dog.pm :实现了dog类 bless.pl : 正确的使用bless bless.wrong.pl : 错误的使用bless bless.cc : 使用C++语言实
gb2312转Utf的方法: use Encode; my $str = "中文"; $str_cnsoftware = encode("utf-8", decode("gb2312", $str));   Utf转 gb2312的方法: use Encode; my $str = "utf8中文"; $str_cnsoftware = encode("gb2312", decode("utf-8
  perl 计算硬盘利用率, 以%来查看硬盘资源是否存在IO消耗cpu资源情况; 部份代码参考了iostat源码;     #!/usr/bin/perl use Time::HiRes qw(gettimeofday); use POSIX; $SLEEPTIME=3; sub getDiskUtl() { $clock_ticks = POSIX::sysconf( &POSIX::_SC_
1 简单变量 Perl 的 Hello World 是怎么写的呢?请看下面的程序: #!/usr/bin/perl print "Hello World" 这个程序和前面 BASH 的 Hello World 程序几乎相同,只是第一行换成了 #!/usr/bin/perl ,还有显示的时候用的是 print,而不是 echo。有了前面 BASH 基础和 C 语言的基础,许多 Perl 的知识可以很
本文介绍Perl的Perl的简单语法,包括基本输入输出、分支循环控制结构、函数、常用系统调用和文件操作,以及进程管理几部分。 1 基本输入输出 在 BASH 脚本程序中,我们用 read var 来实现从键盘的输入,用 echo $var 来实现输出。那么在 Perl 中将有一点变化。Perl 中将标准输入用关键词 表示;标准输出用 表示,标准错误输出用 表示。故而从标准输入读取数据可以写成: $
正则表达式是 Perl 语言的一大特色,也是 Perl 程序中的一点难点,不过如果大家能够很好的掌握他,就可以轻易地用正则表达式来完成字符串处理的任务,当然在 CGI 程序设计中就更能得心应手了。下面我们列出一些正则表达式书写时的一些基本语法规则。 1 正则表达式的三种形式 首先我们应该知道 Perl 程序中,正则表达式有三种存在形式,他们分别是: 匹配:m/<regexp>/ (还可以简写为 /
在学习Perl和Shell时,有很多人可能会问这样一个问题,到底先学习哪个或者学习哪个更好! 每个人都有自己的想法,以下是个人愚见,请多多指教! Perl是larry wall为解决日常工作中的一个编程问题而产生的,它最初的主要功能是用于分析基于文本的数据和生成这些数据的统计和结果;尽管初衷很简单,但是后来发展了很多特点: 1、Perl是一种借鉴了awk、C、sed、shell、C++、Java等
Perl 有很多命令行参数. 通过它, 我们有机会写出更简单的程序. 在这篇文章里我们来了解一些常用的参数. (重点提示:在window下执行命令行程序的方式为 : perl -e "some code", 注意:是双引号啊,不是单引号,linux下执行时单引号) Safety Net Options 在使用 Perl 尝试一些聪明( 或 stupid) 的想法时, 错误难免会发生. 有经验的 P
转自: http://bbs.chinaunix.net/thread-1191868-1-1.html# 让你的perl代码看起来更像perl代码,而不是像C或者BASIC代码,最好的办法就是去了解perl的内置变量。perl可以通过这些内置变量可以控制程序运行时的诸多方面。 本文中,我们一起领略一下众多内置变量在文件的输入输出控制上的出色表现。 行计数 我决定写这篇文章的一个原因就是,当我发现
2009-02-02 13:07 #!/usr/bin/perl # D.O.M TEAM - 2007 # anonyph; arp; ka0x; xarnuz # 2005 - 2007 # BackConnectShell + Rootlab t00l # priv8! # 3sk0rbut0@gmail.com # # Backconnect by data cha0s (modifica
转自: http://bbs.chinaunix.net/thread-1191868-1-1.html# 让你的perl代码看起来更像perl代码,而不是像C或者BASIC代码,最好的办法就是去了解perl的内置变量。perl可以通过这些内置变量可以控制程序运行时的诸多方面。 本文中,我们一起领略一下众多内置变量在文件的输入输出控制上的出色表现。 行计数 我决定写这篇文章的一个原因就是,当我发现
黑莓 手机 屏幕发展历程对比 blackberry 各型号屏幕大小   黑莓手 机 一直在不断发展且新机型 也在不断上市. 因此,不同黑莓机型的屏幕分辨率也在不断变化着. 总的来说,屏幕分辨率一直在提高并且越来越清晰.我们对所有的黑莓 机型的屏幕分辨率做了个对比.~51blackberry ~com     可能大家特别感兴趣是新发布的黑莓机型,它的分辨率也是黑莓 机型中前所未有的.   黑莓 b
      公司里没有我用惯的UltraEdit的lisence了, 只能无奈转向开源的Notepad++, 找了半天才知道配置运行Perl的办法。         1,用Notepad++打开.pl文件,         2, F5或者Run->Run,打开运行窗口,在下面的框框里输入:Perl -w "$(FULL_CURRENT_PATH)", 然后Save,保存成一个命令就行,名字比如叫R