11/24/2007

Load A New File From Template In Notepad++

6 comments

What are needed:

  1. htmlTemplate.htm: Your html template
  2. nppNewHtml.bat: a .bat file looking like this:
copy  d:\html\htmlTemplate.htm  d:\html\new.htm
"C:\Program Files\Notepad++\notepad++.exe"  d:\html\new.htm

Save nppNewHtml.bat in, for example, d:\html.

In Notepad++, go to menu [Run], or hit [F5].

In the input box shown under the title [Type your program to run here], enter:

d:\html\nppNewHtml.bat


Hit [Save] to save it to a run menu item (give it a name like "new html").

From now on, you can go to the [Run] menu and find an item called "new html" that allows you to open a new html file based on your template.

10/17/2007

關於「中國製產品條碼」的錯誤資訊

3 comments

今天收到朋友轉寄來的有關「中國製造的產品條碼」的信件,指出如果產品條碼前三碼是「690」就代表是「中國製造」的,如果不是「690」則表示「非中國製造」,可以放心使用(如下圖)。

錯誤的產品條碼資訊


事實上這是一個錯誤的資訊

首先,中國產品的條碼,不止「690」開頭。除了「690」外,691~695 都屬於中國。請參考產品國條碼表列

更嚴重的錯誤是,產品條碼前三碼並不代表「產品生產國」這個網站指出:

系統碼,也就是前兩碼或前三碼,通常代表該產品的製造商在哪一國註冊,而不必然是該產品真正的生產國。
System code, the first two or three digits, usually identifying the country in which the manufacturer is registered (not necessarily where the product is actually made).

以幾個產品為例:

例一:同一家工廠的不同產品可能有不同的國碼:
同為紐西蘭一家工廠的兩種產品,左邊國碼(941)為紐西蘭,右邊國碼(400)為德國(因為是德國的廠商)。值得注意的是:右邊產品的國碼為德國,但白紙黑字寫得很清楚是在紐西蘭製造。

例二:中國製造,國碼為荷蘭:
中國製造,國碼為荷蘭

例三:中國製造,國碼為美國:
中國製造,國碼為美國

因此,光靠產品條碼上的國碼,並不能判斷是否為中國製造。如果一家廠商是在台灣註冊,但跑到中國去生產,那其產品的國碼就很可能是「471」,也就是台灣。

像此文中提到的這項錯誤資訊已經傳遍網路,將使大眾反而誤購了中國製產品還堅信是台灣製造的,誤導社會大眾甚深,希望以後讀者不要再散播這樣的錯誤訊息。

8/10/2007

How KNN Twists A Report

6 comments

Michael over the "The view from Taiwan" has an article "Media Management (in)Eptitude" in which he cited an article on Taipei Times KMT starts English, Japanese `news service' regarding the new Kuomintang News Network (KNN) launched by KMT. According to Stephen Chen (陳錫蕃), a KMT think tank member and former (KMT government) representative to the US, one of the main functions of KNN is:

help to counter the biased reports of pro-green English [language] newspapers

and with KNN they will :

provide recent poll results, news analysis from the KMT think tank and selected party news every day

and
take a more aggressive approach to promote itself internationally through the sites

It's interesting to see such an action from KMT. For a long time some Taiwan-based English bloggers (see Michael's blog and the blogs he links to) have been commenting heavily about how major foreign media like CNN, BBC, etc play the role of Chinese propaganda trumpet by reporting biased Taiwan news in favor of pro-china pan-blue (like KMT). Now KMT is saying that they are the victim?

Knowing that twisting the fact is not something new in KMT culture, I am curious to see how "their" recent poll results would say. It didn't take me too long before I spot a twisting fact on their site. On the second poll I checked, regarding an identity poll conducted by Eva TV, on July 19, 2007, KNN puts up a link to a Word file containing the poll results.

Obviously that's what KNN did on all the poll results showing on their site. But on that particular identity poll mentioned above, they added an extra remark:

Preposterous remark made by KNN. Click to see the full page. (original link)
Can anyone tell me what exactly they are saying? I read it back and forth couple of times but still unable to follow its logic. Not only does it contradict itself in such a short paragraph (in the first half it says no “Both Taiwanese and Chinese” option was given but in the second half it says some respondents were able to choose “Both Taiwanese and Chinese”), but also the logic is completely preposterous -- how come an omission of the "Both" option naturally shows a high percentage of “Taiwanese Only” ? If that is "naturally shown," doesn't it already mean that in deed more people in Taiwan identify themselves as Taiwanese?

Even worse, what it says about the wording is not the fact at all ! Simply bringing out the word file of that identity poll, you will be able to find this table:

Poll result. KMT says the poll didn't offer "Both Taiwanese and Chinese" as an option. Do they think all readers are blind ? (click for larger image, or click here to download the original word file)
Not only does KNN lie about the "Both" option, but also, they attached "only" to "Taiwanese" and "Chinese" options shown in the original poll, such that the original 3 options "Taiwanese, Chinese, Both" was twisted into a 2-option "Taiwanese Only, Chinese Only" in their remark.

You must be amazed by such an desperate, low-wit trick KNN pulled up. The fact is there, right under their nose, yet they try to put up a twisted facade to cheat on people who don't have time for details. Whoever is willing to spend just two more minutes to dig into the Word file will be able to tear their lies apart right on their own page.

Talking about the "wording," who is the real genius here ? Is this what they called "more aggressive approach" ? I feel sympathetic for these poor souls ...

8/09/2007

Has Taiwan Never Been A Country In History?

0 comments

David Lu of the Taipei Economic and Cultural Office (TECRO) in San Francisco, a branch of Taiwan's officially unofficial representative office in the US, post an article in San Jose Mercury News regarding the issue of Taiwan entering UN (United Nations' exclusion of Taiwan is unjust). Some readers commented and claimed that "Taiwan has never been a country in the history".

In rebuttal, I post an article:

1) raventhorn: "Fact is, Taiwan NEVER represented itself in any treaty negotiations or signed any treaties. It was always considered as a part of some other country's territorial administration."

2) Alvin Ding: '"Taiwan" was never be a country in history'

----

These are incorrect statements. In her history, Taiwan established herself as an independent country at least twice, and exercised her sovereignty right through treaties numerous times.

In 1664, Cheng Jing (鄭經), son of Cheng cheng-gong (鄭成功), founded Tong-Ning Kingdom (東寧王國) in Taiwan. The kingdom has her own government, own army, own social system, and own business interactions with surrounding countries. It also has other own diplomatic relationships with other powers, in which Cheng was called "The King of Tyawan." (Taiwan was sometimes spelled as Tyawan at that time)

In 1895, Republic of Taiwan was established in Taiwan by Liu Jing-Song (劉景崧). It is the first republic country in Asia.

Aside from the above 2 official establishments, Taiwanese had exercised their sovereignty right independently as a country. For example, by signing treaties with other countries, as what Michael mentioned in his earlier post:

"the Qing denied controlling Taiwan on several occasions, and foreign powers negotiated directly with local aborigine leaders."


The countries who signed treaties with Taiwanese include USA, after USA marine was defeated (and one of USA Civil War Generals killed) by Taiwan aborigine (in around 1780, I believe).

Following raventhorn's own words: 'Treaties largely make up the foundation of "de jure" sovereignty,' then Taiwan has been an independent sovereignty many times in her history.

These are historical facts that shouldn't be withheld from the readers. I have to agree with Michael: "Raventhorn's 'rebuttal' sounds credible only because he withholds key facts from the reader."


Btw, David Lu's article is full of errors, not only in facts but also in English grammar.

7/23/2007

Javascript string replacing function (2)

0 comments

Previously I mentioned a string replacing function that, instead of building a string this way:

tag= '<' + tagname + ' style="background-color:'
+ bgcolor + ';color:' + color + '">' + text + '</' + tagname +'>'

allows for doing it this way:

tag0= '<___ style="background-color:___;color:___">___</___>'
tag1 = tag0._(tagname, bgcolor, color, text, tagname)

or this way :

tag00= '<[.tagname.] style="background-color:[.bgcolor.];'+
'color:[.color.]">[.txt.]</[.tagname.]>'

data = {tagname:'span', bgcolor:'#EEFFBB',color:'red',txt:'tag2'}
tag2 = tag00._(data)


After playing with the regular expression for a while, I come up with a short version :

String.prototype._=function(){
var i=-1, a= arguments
var t= typeof(a[0])=='string'
var rx = t?(/___/g):(/\[\.[A-Za-z0-9_]*\.\]/g)
var f = t?function(x){i++;return a[i]}
:function(x){return a[0][x.slice(2, -2)]||''}
return this.replace(rx,f)
}


To me it's amazing to see how such a task can be accomplished with such a neat code.

7/21/2007

Problems in Javascript Subclassing

0 comments

In javascript, the subclassing is done this way:

[1] function Person(name, sex){    # Define the superclass
[2] this.name = name
[3] this.sex = sex
[4] this.prn = function(){ return this.name + ', '+ this.sex }
[5] }

[6] function Man(name){ this.sex = 'M' } # Define the subclass
[7] Man.prototype = new Person() # Connect Person and Man

And the instantiation:
[8]  p = new Person('Jane','F')
[9] m = new Man('John')

Checking the function prn (defined in [4]):
p.prn() ==> Jane, F
m.prn() ==> undefined, M


As shown, the name John given to Man when instantiating m ([9]) is NOT transferred to m. It is obvious 'cos we didn't instruct it to do so when defining Man in [6].

Problem.1: Subclass Arguments Are Not Automatically Transferred To Subclass Instances



So, unless explicitly instructed, the arguments of a subclass will not be assigned to the instance of that subclass. That means, [6] needs to be re-defined as:
function Man(name){ 
this.sex = 'M'
this.name= name # <== new line
}

Note that the above highlighted line already exists in the superclass (line [2]). Why does it have to be re-done again in the subclass ? Didn't we already instruct Person to be the super class ?

Problem.2: An Instance of Subclass Is an Instance of the Superclass too ?


Lets investigate the instanceof operator in javascript:
[10] (p instanceof Person)  ==> true
[11] (m instanceof Man) ==> true
[12] (m instanceof Person) ==> true


Line [10] and [11] are what we expect. But [12]? How come m is an instance of Person ? This doesn't sound right.

Problem.3: The Constructor of A Subclass' Instance Is The Superclass But Not the Subclass ?


Check the constructor of the instances of subclass and of superclass:
[13] getConstructor(p) ==> Person
[14] getConstructor(m) ==> Person

Shouldn't the constructor of m be Man?

Solution Proposal



Lets try a new way of defining a subclass. Instead of
function Man(name){ 
this.sex = 'M'
this.name= name # <== new line
}

We try this:
function Woman(name){ update(this, new Person(name, 'F'))}
w= new Woman("Jan")

See the following table for comparison:

ClassesInstanceinstanceof
Person
constructor
function Person(name, sex){
this.name = name
this.sex = sex
this.prn = function(){
return this.name +','+this.sex}
}
ptruePerson
function Man(name){
this.sex = 'M'
this.name= name }
Man.prototype = new Person
mtruePerson
function Woman(name){
update(this, new Person(name,'F'))
}
wfalseWoman

7/20/2007

中國的食品污染

0 comments

今天讀到大紀元的一篇報導:毒牙膏再演鬧劇 質檢總局大變臉
http://epochtimes.com/b5/7/7/20/n1778129.htm

該文提到因中國外銷的含毒牙膏所引發的一連串新聞。文中提到的「二甘醇」是一種抗凝劑,若水中含有二甘醇,則在低溫時會防止水分子結成冰。二甘醇的含量越高,越不易結冰,可能在零下二、三十度時都還保持液體狀態不會變成冰塊。中國製的牙膏,就是利用二甘醇的這種特性,使其即使保存很久也不會硬化。這是對人體有害的有毒物質,因此像牙膏這種不小心會吃進人體的東西不應該含有二甘醇。

其他重點:

  1. 中國生產的幾種牙膏含有0.21%至7.5%的二甘醇。
  2. 中國衛生部不久公佈了該部「專家」的評估結論:「長期使用二甘醇含量低於15.6%的牙膏不會對人體健康產生不良影響」,但報告未顯示專家姓名,也沒說明該試驗的具體方法。
  3. 7月16日,中國質檢總局局長公開批評境外媒體對中國出口產品質量問題的報導是"顛倒黑白",他表示,中國食品合格率要高於美國。
  4. 中國工廠即使自己想要合法生產也很困難,因為他們購買的材料本身就是非法的有毒物(可能買不到無毒的)。譬如說,生產用的水,前幾年由於污染的加劇,中國政府不是採取措施防治並減少污染,反而降低水質標準,把以前的污染水當成合格水賣給企業
  5. 今年七月,據中國質檢總局對食品、化肥和農用機械等眾多消費品質量抽查,結果發現19.1%的產品達不到標準。其中最嚴重的是食品問題,特別是罐裝食品、乾果和果汁飲料。
  6. 中國常用油鹽醬醋米麵的合格率平均低於40%,特別是低價食品,其衛生質量根本無法保障。
  7. 中國進口到美國的食品只有 0.9% 有被抽查。即使在如此低的抽樣率下,中國裝船的食品每個月有 200 次在港口被拒收,排名世界第一。
  8. 中國食品藥品質量監測管理局2005年批准了1113個新藥,這數目等於美國近十年來新藥的「受理」總量(看清楚,不是批准量)。

About Subclassing in Javascript

0 comments

Let the superclass be:

function Person(sex){alert('I am Person')}

and subclasses:

function Man(){this.sex='M'}
function Woman(){this.sex='F'}

The following two subclassing approaches don't seem to make any difference:

Man.prototype = new Person
Woman.prototype = new Person()
m = new Man()
w = new Woman()

In both cases:
  • The function Person will be executed
  • The constructor of both m and w are Person


4/04/2007

IE's TextRange.compareEndPoints()

0 comments

TextRange object

The other day I was coding a web page that needs to make use of some javascript functions of textarea element. I did a little dig-out and ran into this compareEndPoints function. It is a function attached to a TextRange object. The IE-specific TextRange object serves as a mediator for the text input element (<input> with type="text", <textarea>...) to manupilate text-related operations (search, replace, copy, paste, insert ...).

Now assuming we have a <textarea> element object called oTextArea, a TextRange object can be created in one of the following ways:
  1. var oTR1 = oTextArea.createTextRange()
  2. var oTR2 = document.selection.createRange()
These code should appear inside an eventhandler, for example:

  oTextArea.onselect = function(){
...
var oTR1= this.createTextRange()
var oTR2= document.selection.createRange()
...
}

Both oTR1 and oTR2 are a TextRange object that has the following properties:

PropertiesoTR1oTR2
boundingHeight1616
boundingLeft15141
boundingTop124124
boundingWidth25256
offsetLeft15141
offsetTop124124
textThis is the test
<textarea> element
textarea
htmlTextThis is the test
&lt;textarea&gt; element.
textarea

Note that:
  1. What createTextRange returns (=oTR1) covers the entire value range of <textarea> while createRange covers only the range of text that is selected;
  2. All the numerical property values in TextRange object are in pixel. No information of index (the start and end point for the selected text range) is available;

compareEndPoints (type, textRange)

I won't go through all the methods of the TextRange object but this one compareEndPoints(type, textRange). This function checks the relationship between two TextRange objects by comparing the starting and ending indices of textRange.text :

  textRange1.compareEndPoints("StartToStart", textRange2)

The argument type can be one of the fillowing 4 : "StartToStart", "StartToEnd", "EndToStart" and "EndToEnd". When it is "StartToStart", it compares the starting index of textRange1.text with the that of textRange2.text. The return is either -1, 0 or 1.

Now, the reason that I talk about this compareEndPoints specifically. Since it is used upon two TextRange objects, and as we saw earlier that both createRange() and createTextRange() return a TextRange object, instinctly it would work like this:

   var oTR1= oTextArea.createTextRange()
var oTR2= document.selection.createRange()
var x = oTR1.compareEndPoints("StartToStart", oTR2)

However, it won't work. IE rejects this usage by showing "illegal argument" error. It took me a while of searching and code digging to figure out a way to do this:

   var oTR1 = document.body.createTextRange(); // Create TextRange on entire body 
oTR1.moveToElementText(oTextArea) // Use moreToElementText to move
// the TextRange to the textarea

var oTR2= document.selection.createRange();
var x = oTR1.compareEndPoints("StartToStart", oTR2)

Only when the createTextRange( ) is used in this way can the resulting TextRange object be used together in compareEndPoints( ) with that generated by createRange( ).

3/31/2007

My javascript addEvent

1 comments

In the end of 2005 several web programming gurus, Peter-Paul Koch (ppk), Dean Edward and Scott Andrew LePera host a "javascript recoding contest" in which they asked participants to submit their code for adding and removing events in javascript. A template page was designed to test the code. The winner was John Resig, whose original code is here. The final code was slightly modified version:

function addEvent( obj, type, fn )
{
if (obj.addEventListener)
obj.addEventListener( type, fn, false );
else if (obj.attachEvent)
{
obj["e"+type+fn] = fn;
obj[type+fn] = function() { obj["e"+type+fn]( window.event ); }
obj.attachEvent( "on"+type, obj[type+fn] );
}
}
function removeEvent( obj, type, fn )
{
if (obj.removeEventListener)
obj.removeEventListener( type, fn, false );
else if (obj.detachEvent)
{
obj.detachEvent( "on"+type, obj[type+fn] );
obj[type+fn] = null;
obj["e"+type+fn] = null;
}
}

I personally don't feel comfortable with these code. First of all, as one of the comments mentioned (#2 Posted by Tino Zijdel on 18 October 2005) that in cases of multiple-eventhandlers in IE, the eventhandler added last will be executed first:

... since this is for IE a wrapper around attachEvent, the execution order of the events is different ('random' according to Microsofts documentation, but LIFO in practice against FIFO using the W3C event model)

A simple test reveals this problem:

function init(){
var btn=document.createElement('input')
btn.value = 'Click me'
btn.type = 'button'
document.body.appendChild( btn )
addEvent( btn, "click", function(){alert("#1")} )
addEvent( btn, "click", function(){alert("#2")} )
}

Run the init() function as the onload eventhandler (<body onload="init()">) and load with browser. Firefox alerts "#1" then "#2". But IE alerts "#2" first then "#1", which is not what it should be.

Another part making me uncomfortable is that it uses the entire function content as the key name of a hash:

   obj["e"+type+fn] = fn;
obj[type+fn] = function() { obj["e"+type+fn]( window.event ); }

Although none obvioiusly problem is mentioned or discussed, it could result in extremely long and complex key name, which, IMHO, is not what a hash is supposed to be.

I therefore came up with my own version:

function addEvent( obj, type, fn ) 
{
obj.eventHooks = obj.eventHooks || {} // set .eventHooks for obj if not exists
var evs = obj.eventHooks[type] || [] // set .eventHooks[type] if not exists
obj.eventHooks[type] = evs.concat( fn.concat? fn:[fn]) // this allows for multiple fns added
obj['on'+type] = function (e) // like addEvent(obj,"click",[f1,f2])
{
for (var i=0;i<this.eventHooks[type].length;i++)
{
this.tmp = this.eventHooks[type][i] // attach to the obj such that the this
this.tmp(e) // inside the function points to the obj correctly
this.tmp = undefined
}
}
obj = null
}
function removeEvent( obj, type, fn )
{
if (obj.eventHooks && obj.eventHooks[type])
{
var evs = obj.eventHooks[type]
for (var i=0; i<evs.length;i++)
{
if (evs[i]==fn)
{
obj.eventHooks[type] = evs.slice(0,i).concat(evs.slice(i+1))
break
}
}
}
obj = null
}

Unlike most addEvent inventions, in which either addEventListener or attachEvent is used, the above code simply stores eventhandlers into a buffer that has the following structure:

  obj.eventHooks = { click    : [f1, f2]
, keyup : []
, mouseover: [f3]
....
}

For each event, say, click, a function is assigned to the .onclick. This function carries out the following steps:
  1. Check if obj.eventHooks exists. If not, create one
  2. Check if obj.eventHooks.click exists. If not, create one
  3. Loop through each functions in obj.eventHooks.click
  4. For each function, attaches it to obj as a temporary obj.tmp, then executes obj.tmp(e). This makes sure that any this keyword inside that function point to the obj correctly.
A test page, using the contest template, is here. I am sure that there will be some downside along with this code, but at least at this moment it seems to solve the problems came with the winning code.

3/20/2007

Javascript string replacing function

0 comments

In python there's a very convinient string replacing function that comes with every string. The following example show how it works:

To construct a string:   "firstname:Runsun, lastname:Pan, project:wysiwyc"

firstname='Runsun'
lastname ='Pan'
project ='wysiwyc'
s= 'firstname:<b>%s</b>, lastname:<b>%s</b>, project:<b>%s</b>'%(firstname, lastname, project)

The symbol % attaching to the end of a string is a function to insert a series of strings (firstname, lastname, project) into the original string. This not only makes it easier to read but also easier to type, as compared to:

'firstname:<b>'+ firstname +'</b>, lastname:<b>'+ lastname+ '</b>, project:<b>'+ project + '</b>'

In javascript you don't have that luxury. I came up with a tiny function that does just that:

function ___(s)
{
var ss = arguments[0].split('___')
var out= [ss[0]]
for (var i=1;i<ss.length;i++){
out.push(arguments[i])
out.push(ss[i])
}
return out.join('')
}

So now you can do this:

s= ___('firstname:<b>___</b>, lastname:<b>___</b>, project:<b>___</b>',firstname, lastname, project)

I found that this syntax is actually better than its python cousin, because the symbol "___" implies that there's something to be filled, just like what we used to do when filling up a form with a pen.

It would look even more clear if we attach this "___()" function to the string prototype:

String.prototype._= function()
{

var ss = this.valueOf().split('___')
var out= [ss.shift()]
for (var i=0;i<ss.length;i++){
out.push(arguments[i])
out.push(ss[i])
}
return out.join('')
}

which allows this:

s= 'firstname:<b>___</b>, lastname:<b>___</b>, project:<b>___</b>'._(firstname, lastname, project)

Some other uses of this function:

Example-1:

alert('myArray=[___]'._(myArray))

Example-2:

tag = '<___ style="___">___</___>'
DIV = tag._('div','___','___','div')
SPAN = tag._('span','___','___','span')
adiv = DIV._("border:1px dashed blue; color:blue", "div example")
aspan= SPAN._("color:red;background-color:yellow", "span example")

The 2nd example gives:

div example
span example

Replace with a data in a hash


The above ___() function is already very helpful. But the original python % has one other feature:

data= {'fname':'Runsun'
,'lname':'Pan'
,'proj' :'wysiwyc'}
s= 'firstname:<b>%(fname)s</b>, lastname:<b>%(lname)s</b>, project:<b>%(proj)s</b>'%(data)

By inserting a (fname) into %s, you allow the data be in hash form. Now lets put this feature into the ___() function.

Stand-alone ___() function:

function ___(s)
{
var isObj=false
try {
isObj = arguments[1].constructor.toString().split('(')[0].split(' ')[1]=='Object'
}catch(e) {}

if (isObj)
{
var args = arguments[1]
for (var k in args) { s=s.split( '_'+k+'_').join( args[k] ) }
return s

}else{

var ss = arguments[0].split('___')
var out= [ss[0]]
for (var i=1;i<ss.length;i++){
out.push(arguments[i])
out.push(ss[i])
}
return out.join("")
}
}

Attached to string prototype:

String.prototype._= function()
{
var ss= this.valueOf()
var isObj=false
try {
isObj = arguments[0].constructor.toString().split('(')[0].split(' ')[1]=='Object'
}catch(e) {}

if (isObj)
{
var args = arguments[0]
for (var k in args) { ss=ss.split( '_'+k+'_').join( args[k] ) }
return ss

}else{

var ss = ss.split('___')
var out= [ss.shift()]
for (var i=0;i<ss.length;i++){
out.push(arguments[i])
out.push(ss[i])
}
return out.join("")
}
}

Now we can do this in javascript:

data= {fname:'Runsun'
,lname:'Pan'
,proj :'wysiwyc'}
s= 'firstname:<b>_fname_</b>, lastname:<b>_lname_</b>, project:<b>_proj_</b>'._(data)

Again, IMO, this looks better than its python cousin does.

UPDATE(7/23/07): See a regular expression version of the same function.

3/15/2007

HTML tablizer

0 comments

Introducing a html tablizer -- an online utilite to make simple html table.

The program has an Input Section and Output Section:


Enter your table data in the Input Section and either hit [Submit] button or simply move the cursor away from the input box. Then the resulting table will be shown immediately in the Demonstration in the Output Section. Also, the corresponding HTML code will be displayed in HTML code for copy and paste.

After the HTML code and the demo result are shown, you can modify the HTML code and see the result immediately:



If the resulting table is too wide:



You can hit the button [demo on top] to bring the table up:



Enjoy tablizer here.

3/11/2007

△ Recovering CHK files

0 comments

I have an old One-Touch external hard drive from Maxtor. It went crazy and generated 10,000 FILE????.CHK files about a year ago. My wife and I were worried about that the entire hard drive has gone unstable so we simply gave up using it. Recently I found some spare time trying to search for some tools to recover those CHK files.

RecognizeImageFiles.py


One of the most important file types to recover is our photos. The first step I tried was to find some python script that can recognize image files by file content but not by file extensions. There is indeed such a nice little script imghdr.py in python repository. I modified it a little to have it specifically useful in CHK image file recovery (RecognizeImageFiles).
Screenshot of RecognizeImageFiles.py execution

It was quite successful and about 500 image files were recovered. But then, what about other types of files? I went online to search for third-party tools.

UnCHK and FileCHK


Surprisingly there isn't too many tools online. The most popular tools seem to be UnCHK (by Eric Phelps) and FileCHK (by Martin Kratz). They seem to be neat and useful. However, UnCHK (version UnCHK3) froze at the very beginning:



and FileCHK gave an error that reads:

Runtime error "9":
Subscript out of range

It's possible that they couldn't recognize my One-Touch in drive F. Whatever, they don't work in my case.

MediaHeal


I then found a MediaHeal from officerecovery. The description reads:

Recovers files from corrupted hard disks. Supported are all common file systems, including NTFS, FAT12, VFAT12, FAT16, and FAT32.

I downloaded the MediaHeal for Hard Drives and gave it a try. Unfortunately, this program only aims at the entire hard drives but doesn't allow users to check folder(s):

MediaHeal doesn't allow you to choose a folder (image shrunk to fit screen)

Much worse, it froze at the very beginning on this screen:

The excution of MediaHeal demo version froze at the very beginning
(image shrunk to fit screen)


RecoverMyFiles


Finally, I found RecoverMyFiles from GetData. According to their website, this program allows users to recover deleted files even after the hard disk is reformatted (I didn't even know that it's possible):

Recover deleted files even if emptied from the Recycle Bin
Recover formatted hard drives, even if you have reinstalled Windows!
Recover your files after a hard disk crash
Get back files after a partitioning error
Recover documents, photos, video music and email.
Recover from hard drive, camera card, USB, Zip, floppy disk or other media

and it's able to recover 200 types of files. I downloaded the trial version and was amazed how efficient it was:

The screenshot of RecoverMyFile excution.

It ran smoothly and took less than 4 minutes to complete checking my 250GB One-Touch. You can check the content of each file to decide what file is valuable. Since this is a trial vresion so it doesn't allow real rescuing. But it already impressed me.

Other links


FILExt.com
http://filext.com/detaillist.php?extdetail=chk&Search=Search

Look for info about a file ext
http://shell.windows.com/fileassoc/0409/xml/redir.asp?Ext=jpg

A list of common file extensions
http://safari.oreilly.com/0596002491/winxpnut-APP-F

OfficeRecovery.com (data recovery software for corrupted files)
http://www.officerecovery.com/mediaheal/index.htm

3/02/2007

■ 228 六十週年

0 comments

228 整整六十週年了。就如過去一樣,台灣藍綠雙方政治人物與支持者都有一大堆活動與討論。我們看看六十週年的今年,跟過去有什麼不同。

● 法律制裁


去年此時,我寫了一篇有關於 228 責任追究與法律制裁的文章(註一),裡頭提到:

在二次大戰後的「紐倫堡大審」中,有很多納粹的一級戰犯被審判、定罪並處死。但是,有很多德國納粹軍官化名逃亡而逃過審判。西方社會對這些人的做法是:不管你用什麼方式逃到什麼天涯海角,即使化成灰也要把你抓出來將你定罪。

反觀台灣人對二二八事件的態度,恐怕任何一個西方人也會為之傻眼 ── 在那樣一個「系統性屠殺」之後,竟然到今天沒有任何審判與定罪。不但如此,當初有系統殺害台灣菁英的那些劊子手,不但沒有任何人接受任何法律制裁,而且接承該殘暴法統的外來勢力至今還在繼續掌握、享有社會資源,甚至還能囂張地利用新聞的編造與扭曲唱衰台灣、撕裂台灣。

並批判泛綠政客對 228 法律追究的漠視:

為什麼那麼多泛綠人士對二二八事件的探討中,竟也很少很少看到二二八事件法律責任的追究?陳水扁總統本身還是律師出身,為什麼竟不懂得強調二二八的「法律層面」,而一再地落入泛藍「將二二八政治化」的圈套裡?

一年過去了,也許時機也漸漸成熟了,台灣人似乎已經從「要求道歉賠償」醒過來,開始有了法律追訴的聲音。日前,美國228大屠殺遺族代表在總統府受陳總統接見時提出法律制裁的請求(註二註三):

台灣應設特別法庭審理已故總統蔣介石當年下令鎮壓導致數千名台灣人喪生的悲劇。

「我們不要求血債血償,但希望獲得公平正義的處理」,代表王文宏說道。

家屬團共計提出五點訴求,包括對蔣介石與其他幫兇進行缺席審判、將228事件列入教科書、把「中正紀念堂」更名為「台灣忠烈祠」、撤走看守蔣介石陵寢的警衛兵、以及撤銷每年將蔣介石逝世日當作國定假日的做法。

而這項請求也得到陳總統的正面回應。在新成立的228國家紀念館的揭幕儀式中,陳總統公開指稱蔣中正為 228 的元兇,並承諾政府將對 228 的犯行採取法律追溯(註四):

總統說,過去為了內部團結,政府以撫平傷痛取代責任追究,卻讓228成為有受害者卻沒加害者的無頭公案:『更讓部分政治人物有機會基於政治的需要,任意捏造歪曲歷史,不論是早年將228抹紅成由台共所主導的叛亂事件,到近日所謂「官逼民反」的最新詮釋,本質上都是一樣的,都在掩飾,並淡化當時獨裁統治者打壓民主、迫害人權的國際罪行。』

未來政府將透過責任追究和法律追訴等方式,加速還原歷史真相,因為只有這樣才能進一步尋求真正的寬恕與和解。

另外,在泛綠的『與媒體對抗』網站,一個專門探討 228 法律追溯的討論欄已經進行了好一段時間(註五),可見,國人已經漸漸瞭解,「法律制裁」才是解決 228 爭議的唯一方式。這實在是 228 六十週年最令人欣慰的事。

● 官逼民反


同一個時間,幾週前才因貪污罪被起訴的泛藍明星馬英九,再一次地重複去年他發明的「標籤」,指稱 228 屠殺是 『官逼民反』(註六):

國民黨前主席馬英九昨天重申,二二八事件不是族群衝突,是查緝私煙導致「官逼民反」

我在去年的文章裡,已經強烈批判了馬英九這種言論是在替 228 的元兇脫罪,並污衊在 228 中犧牲的台灣人:

通常,在這種官民對抗的事件上,如果你是站在人民的一邊,你會以「起義」或「革命」來形容該事件。只有站在官方或者「同情官方」的立場,才會說那是「造反」。

很顯然,馬英九雖然表面上將責任歸在官方,看起來好像是站在人民的立場講話,但是,這句話的前提卻是「人民造反」,也就是他其實完全是站在官方的立場來看待二二八。利用這句精巧包裝的政治語言,馬英九在事件的歸屬上,很巧妙地將當年台灣人為了活下去而做的掙扎定了「造反」的罪,而那些為了爭民主而犧牲的台灣人,就這樣被馬英九的陰招鎖成「暴民」。

今年,阿扁總統也在公開場合做了同樣的批判(註七):

陳水扁總統上午反駁表示,將「228事件」定位為所謂的「官逼民反」或「警民衝突」,這是為過去的獨裁者粉飾太平,完全是以施暴者與加害者的史觀來詮釋歷史,這是絕大多數台灣人民不能夠接受與理解的。

顯然,馬英九欲以「官逼民反」將 228 事件定位為「人民造反」的陰謀,已經被國人所識破。

● 日本是 228 元兇?


還有更離譜的事。前幾日中研院幾個院士發表了一篇完全背離歷史事實的文章,指稱日本與美國才是 228 的元凶,企圖將 228 的責任歸屬轉嫁到日本與美國(註八):

中央研究院院士黃彰健、研究員朱宏源、民間史學學者武之璋戚嘉林27日上午聯合發表研究新發現。他們發現,日本人蓄意放棄對糧食配給管制,造成光復後台灣糧食大災難是228事件的原兇;美國人則為自身利益,企圖掌控、佔據台灣,屬於幫兇。228事件,其實是「民逼官反」。


雲林228紀念碑
啊??? 蓄意放棄對糧食配給管制,造成光復後台灣糧食大災難,所以是228事件的原兇?

首先,日本人已經要撤離台灣,已經沒有對台灣的控制權,即使他們沒放棄,也不可能有權力去維持該管制,何來「蓄意放棄」之說?

甚且,「沒有糧食管制」造成糧食大災難而導致 228?228 這種涉及整個社會的屠殺事件的原因複雜,怎可能因為單一的「沒有糧食管制」而死那麼多人?這種荒謬的邏輯,這幾個所謂的大學者竟然說得出口?

最後,殺人不眨眼的大魔頭與中國軍隊屠殺台灣人無罪,「已無權力管制台灣」的日本人反倒成為元兇?

這幾個飽讀「屍書」的學者,試圖利用學者身份替屠殺者粉飾罪惡,真是令人可悲。

可喜的是,這幾個無恥的蛋頭學者昧著良心所羅織的偽證,並沒有得到廣大讀者的支持。在該報導所附的討論區裡,絕大部分讀者的回應是在罵這些學者(註九)。舉幾個例子:

2007-02-27 14:18
systemzero:狗黨拿了多少錢給他們這些老頭捏造假歷史
當時基隆港屠殺 可是國民政府軍隊直接用機槍對岸上無辜人民掃射
此事豈可推給美日兩國!!!
2007-02-27 14:23
juliebarbie:如此「學者」!講痟話!
扯太遠啦!
日本人要離台了,當然要解除糧食管制,讓台灣人吃自己的糧食,難道還要繼續把糧食運往日本。
不過,據了解,終戰(「光復」)後台灣糧食大量運往中國去餵「豬」,支應國共內戰所需。
2007-02-27 15:45
haghland1:我在中研院~我也覺得很奇怪
他們雖然是中研院院士,可是是因為自己的興趣與政治傾向去進行自己的研究,他們憑什麼代表中研院發言呢?就我所知,中研院研究人員跟他們意見相左的人,大有人在,為什麼這些人的聲音不被重視?
而且,拿槍殺人的人沒罪?那請問納粹大屠殺的受害者,是不是要怪當年把希特勒給甩了的女性,才讓希特勒變得有偏激傾向?這些所謂學者,真的是讓自己的意識形態掌控一切了!
2007-02-27 16:52
hongshan:錯了!元兇是蒙古人,幫兇是英國人
按照所謂「中央研究院院士黃彰健、研究員朱宏源、民間史學學者武之璋、戚嘉林」等視野獨到鑽家的邏輯,那我們也可以衍論228元兇是蒙古人,因為元朝時蒙古人渡海東征未果,所以才有後來『日本人蓄意放棄對糧食配給管制』造成228民心動盪。而幫兇當然是英國人,因為他們當年放任北美獨立,所以才有後來的『美國人則為自身利益,企圖掌控、佔據台灣』。
當然,我們也可以按照這個邏輯推論其實元兇是亞當,而幫兇是夏娃。
2007-02-27 17:12
allweiout:是壓是壓/ 幕後大元兇 倒底是誰
一直往前推,全部都有責任,共產黨,滿清,發明槍的人。
繼續愚弄人民壓~幹的好,水喔。記住這些名字!
中央研究院院士黃彰健、研究員朱宏源、民間史學學者武之璋、戚嘉林。

這些回應似乎顯示出:這年頭要以學者之名為中國人在 228 事件中屠殺台灣人的劣跡脫罪的努力,已然不能得逞了。

● 可期待的未來


幾週前,陳總統曾說過,現在距離 2008 總統大選還有一段時間,依照台灣意識的發展速度,到了 2008 選總統投票時,台灣人覺醒的程度,將使得那些「支持統一」的候選人完全沒有機會被選上。日前,國民黨的立法院院長王金平也說過類似的話 (註十):

二00八大選時的外省籍問題,將非常嚴重 ... 台灣族群的主體議意識已經發酵了,看看正名問題發酵了沒?中南部已經強烈反映不會投給外省人了

以最近台灣政府大刀闊斧的正名運動,以及民間將 228 事件由「政治層面」回歸到「法治層面」的舉動,似乎顯示,局勢是在台灣人這邊,2008 總統大選,不管親中的泛藍泛橘泛紅抬出什麼人選,以逆著台灣意識的姿態,要贏得政權恐怕很難了。

● 參考資料



註一:被遺忘的法律制裁
http://aztecpassage.blogspot.com/2006/02/blog-post.html

註二:台灣人籲審判已故總統蔣介石屠殺罪
http://www.anti-media.tw/phpBB/post_468620.html#468620

註三:Taiwanese demand trial of late president Chiang for massacre
http://news.monstersandcritics.com/asiapacific/news/article_1269827.php/Taiwanese_demand_trial_of_late_president_Chiang_for_massacre

註四:扁:轉型正義新階段 追訴元兇
http://news.yam.com/bcc/politics/200702/20070228984357.html

註五:從艾斯曼案(The Eichman Case)來探討228集體大屠殺罪責如何追究
http://www.anti-media.tw/phpBB/topic_15469.html

註六:馬:228事件是官逼民反
http://news.chinatimes.com/2007Cti/2007Cti-News/2007Cti-News-Content/0,4521,110501+112007022500006,00.html

註七:馬稱228「官逼民反」 扁反駁
http://news.yam.com/udn/politics/200702/20070226978869.html

註八:228事件60週年/中研院:日本是元兇 美國是幫兇
http://news.yam.com/ettoday/politics/200702/20070227981228.html

註九:「228事件60週年/中研院:日本是元兇 美國是幫兇」討論區
http://forum.news.yam.com/disingle.php?newsid=20070227981228

註十:王金平:2008大選 外省籍問題將非常嚴重
http://udn.com/NEWS/NATIONAL/NATS5/3744920.shtml

2/14/2007

【牽手】

0 comments

想到 Madeci 外的寒意
到如今困境不知凡幾
而我們依然手牽手在一起
真心相惜始終如一

於是我心中充滿無盡的感激
如妳說下輩子還要找在一起
到時也許換我給妳一棵腎臟
也好讓欠疚的人不只我自己

想到結婚兩年半裡
衫污了有妳洗好衣
肚子夭有妳煮了米
郎睏了妳先備好蓆
到月底妳早把財理

這就是我的家妻
家裡大小一手理
閑閑的我只能專心地
愛妳疼妳惜妳


給小豬豬
2007 年 情人節前夕
大牛即興作於德州休士頓
The Methodist Hospital
Rm D423