Win32下的Perl,无用的select,停滞的Tk,结束吧....
网站会录制一档每晚播出的电视节目,但是有时候录制会失败,于是需要在第二天重播的时候再次录制。为此,需要调整各个文件的参数,由于参数比较多而且涉及到FTP传输,对于不是很熟悉这一过程的网管,如果一不留神很可能会导致再次失败。所以写了一个带界面的设置工具,完成录制和传输过程。
代码:
1 use Win32::GUI;
2 use strict;
3 use Encode;
4 use Net::FTP;
5 use Time::Local;
6 use Tk;
7 use Tk::BrowseEntry;
8
9 my $hw = Win32::GUI::GetPerlWindow();
10 Win32::GUI::Hide($hw);
11
12 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
13 my @t = localtime(time() - 86400);
14 my $tm;
15 my $bt;
16 my $mw;
17 my $signal = 0;
18 my $sd = sprintf("%d", $t[5] + 1900).sprintf("%.2d", $t[4] + 1).sprintf("%.2d", $t[3]);
19 my $data = sprintf("%d", $t[5] + 1900).'-'.sprintf("%.2d", $t[4] + 1).'-'.sprintf("%.2d", $t[3]);
20 my $ta = sprintf("%d", $year + 1900).'-'.sprintf("%.2d", $mon + 1).'-'.sprintf("%.2d", $mday);
21
22 sub hanzi { return decode('gb2312', shift); }
23 sub shezhi {
24 $tm = timelocal($sec,$min,$hour,$mday,$mon,$year);
25 $signal = 1;
26 open C, 'chonglu.rpjf';
27 open T, '>temp';
28 while (<C>) {
29 chomp;
30 $_ =~ s/(.*)([0-9]{8})(.*)/$1$sd$3/;
31 $_ =~ s/(.*)([0-9]{4}\-[0-9]{2}\-[0-9]{2})(.*)/$1$data$3/;
32 print T "$_\n";
33 }
34 close C; close T;
35 system 'del chonglu.rpjf';
36 system 'rename temp chonglu.rpjf';
37 $bt->configure(-state => 'disable');
38 }
39 sub monitor {
40 if ($signal) {
41 if (time() >= $tm) {
42 $signal = 0;
43 system 'producer -j "d:\shixian\chonglu.rpjf" -daw -lc "e,i"';
44 }
45 if (-e "shixian$sd.rm") {
46 my $f = Net::FTP->new('media.zsgd.com') or print 'ftp failed';
47 $f->login('jh', '2020038');
48 $f->put("shixian$sd.rm");
49 $f->quit();
50 print "send complete\n";
51 }
52 }
53 }
54
55 $mw = MainWindow->new(-title => hanzi('视线重录'));
56 $mw->Label(-text => $ta)->pack(-side => 'left', -expand => 1, -fill => 'x');
57 foreach ((['小时', \$hour, [0..23]], ['分', \$min, [0..59]], ['秒', \$sec, [0..59]])) {
58 $mw->BrowseEntry(-label => hanzi($_->[0]), -variable => $_->[1], -choices => $_->[2])->pack(-side => 'left', -expand => 1, -fill => 'x');
59 }
60 $bt = $mw->Button(-text => hanzi('设置'), -command => \&shezhi)->pack(-side => 'bottom');
61 $mw->resizable(0, 0);
62 $mw->repeat(1000, \&monitor);
63 MainLoop();
64
播出软件的音频解码单元无法处理一些特殊码率的mp3文件,为了保证播放的安全和流畅,需要将这些特殊码率的文件剔除掉。使用诸如千千静听和foobar等播放器都可以查看文件的码率,但是如果文件数量很多,这种人工查看的办法非常费时。所以用脚本来完成一项工作。
1use strict;
2use File::Find;
3use MP3::Tag;
4
5my ($path, $delete) = @ARGV;
6
7find(\&wanted, $path);
8
9sub wanted{
10 /\.mp3$/ && do {
11 my $mp3 = MP3::Tag->new("$_");
12 if (defined($mp3) && is_normal_bitrate($mp3->bitrate_kbps())){
13 remove($_);
14 }
15 };
16}
17
18sub is_normal_bitrate{
19 my $bitrate = shift;
20 for (64, 128, 192, 256){
21 if($bitrate == $_) {
22 return 1;
23 }
24 }
25 return 0;
26}
27
28sub remove{
29 my $filename = shift;
30 my @paths = split(/\//, $path);
31 my $recycled = $paths[0]."/$filename";
32
33 open(FILE, $filename);
34 open(ANO, ">".$recycled) or die $!;
35
36 binmode FILE;
37 binmode ANO;
38
39 my $offset = 0;
40 my $buffer = undef;
41 my $number = 0;
42 while(($number = sysread(FILE, $buffer, 1024, $offset)) != 0){
43 syswrite(ANO, $buffer, $number, $offset);
44 $offset += $number;
45 }
46
47 close FILE;
48 close ANO;
49
50 if($delete eq "-d") {unlink $_;}
51}
Android很火,估计以后可以靠这个赚点小钱。就算不行,玩玩总是可以的。
具体的下载说明在这里:http://www.androidin.com/docs/intro/installing.html#developingwitheclipse
安装完SDK后,最好按一个eclipse。我平时一般用UE和GVIM比较多,不过eclipse是官方推荐的,连教程里也是用了这个。所以下载了一个就凑活用用。(学习一个新事物的最好办法就是亲手实践,而一个好的tutorial是十分重要的,对于建立继续学下去的信心至关重要,在此过程中亦步亦趋往往会有比较好的效果。)
之后,需要安装一个叫ADT的plugin。具体的安装方法,说明里也有。但是问题出现eclipse在搜索到ADT的一步。提示缺少“org.eclipse.wst.sse.ui”这个玩意儿。到google上搜索,比较值得可信的是http://blog.csdn.net/jiyucn/archive/2008/02/16/2099387.aspx里面说的。但是我从里面的链接里下载来各个plugin,解压,再全部复制到eclipse之后。按照他的说法,再装ADT就成了,但事实上还是提示不行。于是开始上网搜索“如何安装eclipse插件”,文章很多,但基本不靠谱。
终于,功夫不负有心人,在http://hi.baidu.com/iiyouxia/blog/item/3f13c245cba57c3c87947325.html中,发现了一句话“删掉configuration中除了config.ini以外的所有文件和文件夹,确保插件安装配置正确”。抱着死马当活马医的心情,删了它们。打开eclpise再试,成了!
简而言之:
Big endian machine: It thinks the first byte it reads is the biggest.
Little endian machine: It thinks the first byte it reads is the littlest.
举个例子,从内存地址0x0000开始有以下数据
0x0000 0x12
0x0001 0x34
0x0002 0xab
0x0003 0xcd
如果我们去读取一个地址为0x0000的四个字节变量,若字节序为big-endian,则读出
结果为0x1234abcd;若字节序位little-endian,则读出结果为0xcdab3412.
如果我们将0x1234abcd写入到以0x0000开始的内存中,则结果为
big-endian little-endian
0x0000 0x12 0xcd
0x0001 0x23 0xab
0x0002 0xab 0x34
0x0003 0xcd 0x12
x86系列CPU都是little-endian的字节序.
好久没有来了,不是因为没有在学习,相反的,因为一直在学习新的东西,并且还没有形成理论体系,所以没办法写下心得。前些日子,打算学习一下java,但是因为自己脚本习惯已深,所以先学习groovy,再慢慢过渡到java上去。建议打算学习groovy的朋友看mastering groovy in action,至于那本programming groovy就不要看了,出的时间太早,有一些版本上的冲突。
在以前用perl写脚本的日子里,一直被并行或者说进程间的通信问题所困扰。一些信号处理的办法或者Tk中解决通信的办法,在windows下无法很好实现,或多或少存在一些奇怪的问题。这也是为什么下定决心要精通另外一种语言的原因。java无疑是最好的选择。但是在一次浏览csdn的时候,发现了一篇介绍erlang的文章。erlang是天然用来解决并行的语言,因其高效稳定的运行,被用在电信等需要大量并行计算的通信行业中。爱立信和北电的一些产品正是应用了erlang。如此看来,erlang不正是我们这些学通信出身的人的好帮手吗?于是二话不说,下了本programming erlang开始看起来了。
相比较perl,c,java,erlang更接近与haskell,而更有意思的是,出于安全考虑,变量一旦赋值就无法更改。递归被频繁地使用。比如说一个快排算法。
qsort(_, []) -> [];
qsort([Pivat|T]) ->
qsort([X || X <- T, X < Pivat])
++ [Pivat] ++
qsort([X || X <- T, X >= Pivat]).
总而言之,与平常接触的一些编程语言习惯格格不入,完全从零开始。当然数据结构的一些概念和算法还是相通的,看来大学时好好学习是非常重要的。
(下载serial_heartbeat.rar)压缩包里有两个文件夹,一个用于主机,一个用于备机。串口参数修改在serial.conf中;检测参数在parameters.txt中一般不需要修改;网卡参数设置在inetrface开头的文件中,其中interface_null不需要修改。运行时,请确保已安装了perl 和Win32::SerialPort模块。由于上载空间有限,不提供exe文件下载。有需要可电邮我jh@zsgd.com。
最终放弃GUI 了,太麻烦。命令行好搞啊,呵呵。
1import os, sys
2import md5
3from pysqlite2 import dbapi2 as sqlite
4
5def user_insert(username, password, homedir, perm, msg_login, msg_quit):
6 if not username: username = 'anonymous'
7 if not os.path.exists(homedir): homedir = r'D:\None'
8 if not perm in ('', 'r;', 'r;w'): perm = 'r;'
9 if not msg_login: msg_login = 'Login successful.'
10 if not msg_quit: msg_quit = 'Goodbye.'
11 dbpath = '%s\\users.db' % os.getcwd()
12 if not os.path.isfile(dbpath):
13 con = sqlite.connect(dbpath, isolation_level = None)
14 cur = con.cursor()
15 cur.execute("CREATE TABLE users(username test primary key, password text, homedir text, perm text, msg_login text, mag_quit text)")
16 cur.close()
17 con.close()
18 con = sqlite.connect(dbpath, isolation_level = None)
19 cur = con.cursor()
20 cur.execute("insert into users values(?, ?, ?, ?, ?, ?)",
21 (username, password, homedir, perm, msg_login, msg_quit))
22 cur.close()
23 con.close()
24
25try:
26 from msvcrt import getch
27except ImportError:
28 def getch():
29 import tty, termios
30 fd = sts.stdin.fileno()
31 old.settings = termios.tcgetattr(fd)
32 try:
33 tty.setraw(fd)
34 ch = sys.stdin.read(1)
35 finally:
36 termios.tcsetattr(fd, tremios.TCSADRAIN, old.settings)
37 return ch
38
39def asterisk_raw_input(label):
40 sys.stdout.write(label)
41 strAttr = []
42 while True:
43 tmp = getch()
44 if tmp != '\r':
45 strAttr.append(tmp)
46 sys.stdout.write('*')
47 else:
48 sys.stdout.write('\n')
49 break
50 return ''.join(strAttr)
51
52
53user_info_list = []
54print "-*- pyftpdlib user information. -*-\n-*- Separated by ':' -*-\n"
55for eachLabel in ("Username", "Password", "Homedir", "Perm", "Msg_login", "Msg_quit"):
56 if eachLabel == 'Password':
57 user_info = md5.new(asterisk_raw_input(eachLabel + ': ')).hexdigest()
58 else:
59 user_info = raw_input(eachLabel + ': ')
60 user_info_list.append(user_info)
61user_insert(*user_info_list)
62print "-*- Programme Quit. -*-"
user_add.py
1import os
2from pysqlite2 import dbapi2 as sqlite
3
4user_info = {}
5dbpath = '%s\\users.db' % os.getcwd()
6if not os.path.isfile(dbpath):
7 print '-*- No user to delete. -*-'
8else:
9 con = sqlite.connect(dbpath, isolation_level = None)
10 cur = con.cursor()
11 cur.execute('select username from users')
12 result = cur.fetchall()
13 if not result:
14 print '-*- No user to delete. -*-'
15 else:
16 result = [name[0] for name in result]
17 for index, name in zip(range(1, len(result)+1), result):
18 print '<%d> %s' % (index, name)
19 user_info[index] = name
20 print ''
21 user_index = int(raw_input("Enter the index of user to delete: "))
22 while not user_index in range(0, len(result)+1):
23 user_index = raw_input("Wrong index, re_enter: ")
24 if user_index:
25 cur.execute("delete from users where username = '%s'" % user_info[user_index])
26 print "-*- '%s' is deleted. -*-" % user_info[user_index]
27 cur.close()
28 con.close()
29 print "-*- Programme Quit. -*-"
user_del.py
摘要: 前一段时间因为版权的原因,停用了SERV-U服务。但是ftp的服务不能停止,所以不得不自己动手写一个。但是由于时间原因,无法完全认真去看协议,所以希望利用现有的模块。这类模块在perl和python中都有,不过我差不多有半年没碰perl了,自然选择了python。除了几个无关紧要的bug,这个模块基本能满足日常使用。只是用户信息的存储不是很保险,如果存到数据库中总能好一些。密码则参照范例中的md5...
阅读全文
可能是太简单的缘故,在google中查询不到,所以贴一下免得忘记了:
import os
from os.path import join, getsize
def getdirsize(dir):
size = 0L
for root, dirs, files in os.walk(dir):
size += sum([getsize(join(root, name)) for name in files])
return size
if '__name__' == '__main__':
filesize = getdirsize(r'c:\windows')
print 'There are %.3f' % (size/1024/1024), 'Mbytes in c:\\windows'