Sipo Blog

宁静致远

MYSQL里面DATETIME列,写现在时间,与时间加法(分钟)的例子

" INSERT INTO cs (starttime,endtime) VALUES ( NOW() , DATE_ADD( NOW(), INTERVAL 120 MINUTE) ) "

SQLite的效率...嗯....研究中....

数据库中有20万条数据,批量插入500条。
数据结构完全一样,SQLite用7秒,MYSQL用0.5秒。

google了一下SQLite效率问题,居然看到“SQLite 效率太低,批量插入1000条记录,居然耗时 2 分钟!”

仔细往下看,用事务能显著提升性能。
嗯,仔细研究一下SQLite的性能问题好了。

于是我使用了事务,发现插入500条数据仅仅需要0.4秒了。
果然。。。

SQLite 提示database disk image is malformed

SQLite有一个很严重的缺点就是不提供Repair命令。
导致死亡提示database disk image is malformed
有很多种可能,比如,磁盘空间不足,还有就是写入数据过程中突然掉电。

刚才在操作一个26万行的数据表的时候,突然掉电
再次执行SELECT指令就出现了database disk image is malformed
由于不知道错误出在哪个地方,无从修复
运行
PRAGMA integrity_check
发现
*** in database main ***
On tree page 120611 cell 0: 3 of 4 pages missing from overflow list starting at 120617
On tree page 120616 cell 0: 3 of 4 pages missing from overflow list starting at 120621
On tree page 3309 cell 0: 3 of 4 pages missing from over
--------------------------------------------------------------------------------------
google了一下,从N多劳苦大众的经验获知,如果遇到这种情况基本宣告SQLite死亡
居然没办法修复。
可爱的MYSQL 可以用REPAIR TABLE 来修复,可是SQLite就没有REPAIR TABLE
MS SQL SERVER 也有Repair 方法,为什么SQLite就不来一个呢??
恩,有时候趋之若鹜并不一定是好事

Wxwidgets和C#的感悟

本来想开发一个跨平台的程序,一个跨平台的WebServer,Linux, MAC,Windows CE
用WxWidgets写了很久,用了WxSqlite来连接数据库,一切看上去都那么顺利。
我用的是Unicode的编译方式,开始没有预料到编码是个问题,但是慢慢编码问题开始显露
我发现,WxWidgets处理编码问题远没有C#牛逼。
举个例子,在C#里面我们可以这么写

string x = System.Web.HttpUtility.UrlEncode("刘", Encoding.GetEncoding(936));
%C1%F5
string x = System.Web.HttpUtility.UrlEncode("刘", Encoding.UTF8);
%E5%88%98
string x = System.Web.HttpUtility.UrlEncode("刘", Encoding.Unicode);
%18R

无论如何,这些带着百分号的编码,或者是经过Base64的编码,或者是javascript里面escape的编码,比如%u5218
我在Wxwidgets的Unicode模式下尝试了很多的方法,但是没有一种方法能够正确进行URLdecode展现出“刘”这个字。
然而,在ANSI方式下的Wxwidgets就可以轻松URLdecode展现“刘”字。
我承认不是widgets不好,只是我的技术水平不够,还不知道怎么转换。
在这里附上我尝试的一些代码段,纪念一下我使用过可爱的wxwidgets。以后慢慢研究怎么在unicode模式下正确urldecode好了。



#define SPC_BASE16_TO_10(x) (((x) >= '0' && (x) <= '9') ? ((x) - '0') : \
                             (toupper((x)) - 'A' + 10))

wxString UrlDecode(wxString &url) {
  size_t i=0;
  wxString dest;
  for (i = 0;  i<url.length();  i++) {
    if (url[i] == '+') dest += ' ';
  else if (url[i] != '%' || !isxdigit(url[i + 1]) || !isxdigit(url [i + 2])) dest += url[i];
    else {
      dest += (SPC_BASE16_TO_10(url[i + 1]) * 16) + (SPC_BASE16_TO_10(url [i + 2]));
      i += 2;
    }
  }
  return dest;
}

wxString URLEncode(const wxString &str) 
{
    wxString ret;
    wxString t;
    for(unsigned int i = 0; i < str.length(); ++i)
    {
        wxChar c = str[i];
        if(   (c >= _T('A') && c <= _T('Z'))
           || (c >= _T('a') && c <= _T('z'))
           || (c >= _T('0') && c <= _T('9'))
           ||  c == _T('.') || c == _T('-') || c == _T('_') )

            ret.Append(c);
        else if(c == _T(' '))
            ret.Append(_T('+'));
        else
        {
            t.sprintf(_T("%%%02X"), (unsigned int) c);
            ret.Append(t);
        }
    }
    return ret;
}

static byte base16Chars[17] = "0123456789ABCDEF";

wxString URLEncode2(wxString sIn)
{
  wxString sOut;
  unsigned char curChar;

  for ( unsigned int i = 0; i < sIn.Length(); i ++ ) {
    curChar = sIn.GetChar( i );

    if ( isalnum( curChar ) ) {
          sOut += curChar;
      } else if( isspace ( curChar ) ) {
        sOut += wxT("+");
    } else {
      sOut += wxT("%");
      sOut += base16Chars[ curChar >> 4];
      sOut += base16Chars[ curChar & 0xf];
    }

  }

  return sOut;
}
inline bool shouldEncode(char c){
  if(c>='0' && c<='9') return false;
  if(c>='a' && c<='z') return false;
  if(c>='A' && c<='Z') return false;
  if(c=='(' || c==')' || c=='$' || c=='!' || c=='*' || c==',' || c=='-' || c=='.' || c=='/' || c=='=' || c==':' || c=='?' || c=='@') return false;
  return true;
}

wxString UrlEncode3(wxString source){
  static const char *hex = "0123456789abcdef";

  unsigned char ch;
  wxString dest;
  size_t source_index = 0;
  while(source.length()>source_index)
  {
    ch = (unsigned char)source[source_index];
    if(source[source_index] == ' ')
      dest += '+';
    else if( !shouldEncode(source[source_index])/* || source[source_index] == '/' || source[source_index] == '.'*/)
      dest += source[source_index];
    else
    {
      dest += '%';
      dest += hex[(ch >> 4)&0xF];
      dest += hex[ch % 16];
    }
    source_index++;
  }
  return dest;
}
wxString UrlDecode3(wxString &url) {
  size_t i=0;
  wxString dest;
  for (i = 0;  i<url.length();  i++) {
    if (url[i] == '+') dest += ' ';
  else if (url[i] != '%' || !isxdigit(url[i + 1]) || !isxdigit(url [i + 2])) dest += url[i];
    else {
      dest += (SPC_BASE16_TO_10(url[i + 1]) * 16) + (SPC_BASE16_TO_10(url [i + 2]));
      i += 2;
    }
  }
  return dest;
}


void URLEncode6(char*& data)
{
  static char* hdig = ("0123456789abcdef");

  char*  obuf = new char[strlen(data) * 3 + 1];
  char*  optr = obuf;

  char*  dptr = data;

  while (*dptr)
  {
    if (((*dptr >= 'a') && (*dptr <= 'z')) ||
      ((*dptr >= 'A') && (*dptr <= 'Z')) ||
      ((*dptr >= '0') && (*dptr <= '9')) ||
      (*dptr == '/') || (*dptr == '-') || (*dptr == ':') || (*dptr == '#'))
    {
      *optr++ = *dptr++;
    }
    else
    {
      *optr++ = '%';
      *optr++ = hdig[(*dptr >> 4) & 15];
      *optr++ = hdig[*dptr & 15];
      dptr++;
    }
  }
  *optr++ = '\0';
  delete[] data;
  data = obuf;
}




/*
  wxString xe= wxT("%C1%F5");
  wxString x= wxT("%E5%88%98");
  char* x3="%E5%88%98";
  wxString x2=UrlDecode(x);
  //wxString x4=wxHTTPBuilder::Base64Encode(wxT("刘"));
  //wxString x5=wxHTTPBuilder::Base64Decode(x4);
  wxString s=wxHTTPBuilder::URLDecode(xe);
  const wxCharBuffer xs=s.mb_str(wxConvUTF8);
  //const wxCharBuffer x7=wxConvUTF8.cMB2WX(((const wchar_t *)(s).c_str()));
  //wxString xx43=wxString(s, wxConvLocal);

  //const char* x21=x7.data();

  //wxConvUTF8.cMB2WX(x3);
  */
  //char * sc="刘";
  //URLEncode6(sc);
  wxString s=URLEncode(wxT("%R18"));
  // s=UrlDecode3(s);
  wxString tt=s;


最后,我想说的是,C#的功劳就是把人们从繁重的基础工作中解脱出来,使人们专注于最关键的架构以及功能。
于是在这个意义上说,C#有着一定的优势,尤其是你很在乎你的开发时间的情况下。

顺便说一些心得,用vs2008生成的代码要比code::blocks生成的代码小。

还有就是wxPack真的很好用

还有就是,自己编译wxwidgets不用wxpack也是可以的,你想好了你用什么模式unicode static debug,你就编译那一种就好了,挺快的,5分钟!wiki上说什么要3个小时,那个是吓唬人的,他说的只是全部都编译了才那么多时间呢。不过确实很耗硬盘空间,即使你之编译一点。恩

wxsqlite3这个很好用,但是sqlite3.lib不好弄,要手动生成,生成方法是copy mspdb80.dll到lib.exe和link.exe的目录下,然后写一个bat,LIB /MACHINE:IX86 /DEF:sqlite.def
其实也很简单的,但是还是很麻烦!

另外不建议用mingw里面的编译器去编译wx,这个会很大,还是建议你用vs的,但是 vs的编译器在codeblock里面经常出问题,于是你直接用vs好了。

说实话,我讨厌unicode,更喜欢utf8

哦,还有,wxformbuilder在vs下好用,在codeblocks下不好用,建议你在codeblocks下面用wxsmith做GUI
另外wxformbuilder在vs下面生成的代码是不能改的,要继承,然后重写方法,这个好麻烦。也许有插件?不知道。

我讨厌wxConvUTF8,一点不人性化。

做服务器的一些心得:
如果你想返回404,你不能光写一个什么404 not found,你还要加上Headder和相关数据,才行。要不然IE就在那里不动了。
hr.SetRC(wxT("404 Not Found"));
hr.AddHeader(wxT("Content-Type: text/html; charset=UTF8") );
hr.AddDataLine( wxT( "Not Found") );




还有content_type也是很有意思的。

if (url_ext==wxT(".htm"))
                 return wxT("text/html");
  if (url_ext==wxT(".html"))
                 return wxT("text/html");
  if (url_ext==wxT(".gif"))
                 return wxT("image/gif");
  if (url_ext==wxT(".jpg")||url_ext==wxT(".jpeg"))
                 return wxT("image/jpeg");
  if (url_ext==wxT(".bmp"))
                 return wxT("image/bitmap");
  if (url_ext==wxT(".png"))
                 return wxT("image/png");
  if (url_ext==wxT(".gz") || url_ext==wxT(".zip")  || url_ext==wxT(".rar") || url_ext==wxT(".bz2") )
                 return wxT("application/binary");
  if (url_ext==wxT(".css"))
                 return wxT("text/css");
  if (url_ext==wxT(".js"))
                 return wxT("application/x-javascript");
  if (url_ext==wxT(".xml"))
                 return wxT("text/xml");
  if (url_ext==wxT(".pdf"))
                 return wxT("application/pdf");

    return wxT("text/plain");

SQLite不支持Right Join的临时解决办法..GROUP BY..

我想用这个,很不幸SQLite没有。。
http://www.sqlite.org/omitted.html
被omitted了!!!!!!!!!!!!!

SELECT 
  * 
FROM 
  A RIGHT JOIN 
  B
WHERE 
A.id =  B.id ;


于是用这个先暂时代替好了。。。

SELECT 
  * 
FROM 
  A INNER JOIN 
  B
WHERE 
A.id =  B.id GROUP BY A.id;


~~~~~

SQLite真的不错~~~~~

JUMPER的RMVB视频声音不同步用MYMPC解决凑合看

也不知道谁压缩的RMVB那么不负责任。
竟然音频与视频严重不同步。说明他的压缩设备之烂、
本来认为暴风影音可以解决音频视频不同步,后来发现暴风影音只支持10秒的调整。
其实我一直不喜欢暴风影音。有广告不说,功能还少的可怜,操作也不方便。比较喜欢kmplayer功能多。但是有点杂乱。
最喜欢原来的mympc现在叫做影音风暴。
MYMPC比暴风影音强多了。我一直用这个。后来有一天我发现暴风影音,就改用新的。发现真不好用,才用的KMPLayer.
现在还是回MYMPC吧。
同步之烂害得我需要每3分钟同步一次视频音频流。
开始延迟声音12秒。然后15,19,22,24,33,45,55,62最后延迟了一分多才把整个片子看完。
真影响效果。好在片子本身就很烂。也就无所谓了。
以后还是用MYMPC吧。姜,还是老的辣。

在.NET中SQLite2.x用phpguru的SQLite.NET wrapper不用System.Data.SQLite

System.Data.SQLite只能支持SQLite3
SQLite.NET wrapper就仅仅支持SQLite2
简直相得益彰:
http://www.dc9.cn

            SQLiteClient db = new SQLiteClient(@"C:\xampp\htdocs\x2.db");
            SQLiteResultSet srs=db.Execute("INSERT INTO Table01 (Field02) VALUES ('xxx')");
          
            ArrayList x = db.GetAll("SELECT rowid,Field02 FROM Table01");   
   
            foreach (string r in x)   
            {   
                Console.WriteLine("\t" + r);   
            } 

删掉这个迅雷绝不偷偷上传了c:\windows\system32\cid_store.dat

我狂晕,今天晚上手机上cnbeta不知道文章被谁投递到cnbeta了。狂晕。狂狂晕。我这个万年cb潜水员竟然也被人转了...
---------------
还是一年前那句话,我支持上传,反对偷偷上传,请在悬浮窗中光明正大显示上传速率,让我们知道你在传什么,多少速率。这样就不会有人骂你了。
---------------

c:\windows\system32\cid_store.dat

不用删除迅雷文件列表,不用清空迅雷垃圾箱,迅雷也不会扫描整个磁盘。
只不过迅雷很阴险地把所有的你以前下载过的文件都存储到了c:\windows\system32\cid_store.dat里面
这样你每一次启动迅雷之后,立刻他就会从这个数据库里面读取内容,然后展开上传攻势。
你只需要在桌面建立一个批处理
d.bat(建立方法是用记事本另存为)
里面写上一句话,

del c:\windows\system32\cid_store.dat

记得每一次用完迅雷,运行一下这个就可以了。
尽管如此,我发现迅雷在没有
c:\windows\system32\cid_store.dat
的时候仍然每1秒钟疯狂下载一次广告,我不明白他为什么每隔一秒下一次!!
所以用完关了最好。

【教程】教你怒看迅雷在偷偷上传你盘上什么文件?占多少带宽?

我狂晕,今天晚上手机上cnbeta不知道被谁投递到cnbeta了。狂晕。狂狂晕。我这个万年cb潜水员竟然也被人转了...
---------------
还是一年前那句话,我支持上传,反对偷偷上传,请在悬浮窗中光明正大显示上传速率,让我们知道你在传什么,多少速率。这样就不会有人骂你了。
---------------


前几个礼拜我看到Cnbeta上有一个迅雷盗窃文件的文章,我开始看的时候对这个文章的看法并不认同,首先我觉得他并不可能扫描全盘,一定是在偷偷上传你曾经下载过的文件。你如果把文件删除就不会上传了。
并且我觉得那片文章里面好多地方说的也不是很对。
刚才找到了原文,http://www.cnbeta.com/articles/48566.htm
直到我写了下面的文章,我才对部分观点采取了认同。


注意了,你开着迅雷,不管已下载列表框是否有文件(是否已经被你删除),迅雷都会自动发现可以上传的文件,并且上传。
开始我认为是由于迅雷自己偷偷保留历史下载文件列表(C:\Program Files\Thunder Network\Thunder\Profiles\history.dat),所以从中发现可以上传的文件,后来我发现根本不是这样!!!history.dat这里面有你的下载记录,开始我估计是他上传的根据。后来我证实了我的估计是错误的。我把这文件删除了。重新启动。
再开迅雷做监视,发现他仍然在偷偷上传我硬盘上的文件。我愤怒了!我真的愤怒了!!!我不知道他怎么知道我的硬盘里面有那些可以上传的文件。我估计还有什么临时文件没有删除干净!!但是我不知道是什么临时文件。这个我查明白了再写出来。我估计他并不是扫描我的整个硬盘。



好了,下面教你如何怒看。
1,首先去微软官方网站去下载Process Monitor这个进程监视器:
[URL=http://technet.microsoft.com/zh-cn/sysinternals/bb896645(en-us).aspx]http://technet.microsoft.com/zh-cn/sysinternals/bb896645(en-us).aspx[/URL]
下载这个软件。
我用的是汉化版。
2,下载网络流量检测软件ByteOmeter
http://www.byteometer.com/
或者在gg上搜索盗版的。ByteOmeter汉化。

3,打开迅雷5,打开ByteOmeter,打开Process Monitor(我用的汉化版),点击“过滤器”->"过滤器"->选择"进程名"->“是”->thunder5.exe->增加
然后就等着吧,你可以选择自动滚动。

4,1分钟后,你就会看到下面的图的内容:
第一个图你能看到他在上传我d盘下的风色幻想游戏,和一个电影,还有vs2008
第二个图你能看到他每秒钟打开关闭你的文件多次,为什么这么做?因为他怕锁定文件句柄然后被用户发现。这样做的结果就是毁你的硬盘!没别的。不多说了。




2008/2/15后记

迅雷很阴险地把所有的你以前下载过的文件都存储到了c:\windows\system32\cid_store.dat里面
这样你每一次启动迅雷之后,立刻他就会从这个数据库里面读取内容,然后上传。
你只需要在桌面建立一个批处理
d.bat(建立方法是用记事本另存为)
里面写上一句话,

del c:\windows\system32\cid_store.dat

记得每一次用完迅雷,运行一下这个就可以了。目的就是自动删除该数据库。记住,删除这个没有性能影响。
尽管如此,我发现迅雷在没有
c:\windows\system32\cid_store.dat
的时候仍然每1秒钟疯狂下载一次广告,我不明白他为什么每隔一秒下一次!!
所以用完关了最好。

IIS上面安装PHP+MYSQL的经验回忆

1)不要下载www.php.net上面那个Windows Installer装完了之后不能用MYSQL都不知道问题出在哪。永远修不好,没错的。EXTention永远无法载入。于是php_mysql.dll永远进入不了内存。MYSQL_CONNET()函数永远找不到。永远设置不好。你根本不知道他做了什么!于是很多在PDO出现之前的程序都用不了。
2)所以一定要手动。手动是王道。因为我们知道我们要做什么。不要懒。
3)下这个# PHP 5.2.5 zip package [9,713Kb] - 08 November 2007
md5: a1e31c0d872ab030a2256b1cd6d3b7d1
手动开始了
4)解压缩。到D:\php,把php.ini-recommand改成php.ini.然后把extenstion=php_mysql.dll前面的分号删除,再把open_short_tag=On(为了运行Discuz!),然后呢把extension_dir设置为D:\php\ext\
5)我的电脑单击鼠标右边的按钮,属性,环境变量,在下面的Path里面加入D:\PHP,貌似仿佛也许可能是为了运行PHP.exe
6)打开IIS6新建一个WEB扩展,把d:\php\php5isapi.dll加入进去
7)建立一个站点,在主目录选项卡上面的下面有一个配置,进去以后增加一个php的扩展dll,还是d:\php\php5isapi
8)然后重启windows 2003.
这个时候测试一下mysql_connect终于能用了。不说什么Call undefined function了
好了,我要说得就这些。上面写了这么多完全是一口气写下来的,也没有看对不对,也许有遗漏的,也许有不妥比如变量名称。大概就是这样了。
貌似让我的回忆能力还是可以的。恩。
顺便提及。前两天服务器内存坏掉,因此造成服务器蓝屏大修。数据基本没有丢失。在这里给西部数据的企业级SATA2硬盘做广告。质量不错。真得不错。在这里批评金士顿1G内存,坏的太快。
«1234567»

Powered By Z-Blog 1.8 Walle Build 100427
Copyright Sipo.