About neohope

一直在努力,还没想过要放弃...

Linux kernel management style


Linux kernel management style
by Linus Torvalds

This is a short document describing the preferred (or made up, depending on who you ask) management style for the linux kernel. It’s meant to mirror the CodingStyle document to some degree, and mainly written to avoid answering (*) the same (or similar) questions over and over again.

Management style is very personal and much harder to quantify than simple coding style rules, so this document may or may not have anything to do with reality. It started as a lark, but that doesn’t mean that it might not actually be true. You’ll have to decide for yourself.
Btw, when talking about “kernel manager”, it’s all about the technical lead persons, not the people who do traditional management inside companies. If you sign purchase orders or you have any clue about the budget of your group, you’re almost certainly not a kernel manager. These suggestions may or may not apply to you.

First off, I’d suggest buying “Seven Habits of Highly Successful People”, and NOT read it. Burn it, it’s a great symbolic gesture.

(*) This document does so not so much by answering the question, but by making it painfully obvious to the questioner that we don’t have a clue to what the answer is.

Anyway, here goes:

Chapter 1: Decisions

Everybody thinks managers make decisions, and that decision-making is important. The bigger and more painful the decision, the bigger the manager must be to make it. That’s very deep and obvious, but it’s not actually true.

The name of the game is to _avoid_ having to make a decision. In particular, if somebody tells you “choose (a) or (b), we really need you to decide on this”, you’re in trouble as a manager. The people you manage had better know the details better than you, so if they come to you for a technical decision, you’re screwed. You’re clearly not competent to make that decision for them.
(Corollary:if the people you manage don’t know the details better than you, you’re also screwed, although for a totally different reason. Namely that you are in the wrong job, and that _they_ should be managing your brilliance instead).

So the name of the game is to _avoid_ decisions, at least the big and painful ones. Making small and non-consequential decisions is fine, and makes you look like you know what you’re doing, so what a kernel manager needs to do is to turn the big and painful ones into small things where nobody really cares.

It helps to realize that the key difference between a big decision and a small one is whether you can fix your decision afterwards. Any decision can be made small by just always making sure that if you were wrong (and you _will_ be wrong), you can always undo the damage later by backtracking. Suddenly, you get to be doubly managerial for making _two_ inconsequential decisions – the wrong one _and_ the right one.

And people will even see that as true leadership (*cough* bullshit *cough*).
Thus the key to avoiding big decisions becomes to just avoiding to do things that can’t be undone. Don’t get ushered into a corner from which you cannot escape. A cornered rat may be dangerous – a cornered manager is just pitiful.

It turns out that since nobody would be stupid enough to ever really let a kernel manager have huge fiscal responsibility _anyway_, it’s usually fairly easy to backtrack. Since you’re not going to be able to waste huge amounts of money that you might not be able to repay, the only thing you can backtrack on is a technical decision, and there back-tracking is very easy: just tell everybody that you were an incompetent nincompoop, say you’re sorry, and undo all the worthless work you had people work on for the last year. Suddenly the decision you made a year ago wasn’t a big decision after all, since it could be easily undone.

It turns out that some people have trouble with this approach, for two reasons:

– admitting you were an idiot is harder than it looks. We all like to maintain appearances, and coming out in public to say that you were wrong is sometimes very hard indeed.

– having somebody tell you that what you worked on for the last year wasn’t worthwhile after all can be hard on the poor lowly engineers too, and while the actual _work_ was easy enough to undo by just deleting it, you may have irrevocably lost the trust of that engineer. And remember: “irrevocable” was what we tried to avoid in the first place, and your decision ended up being a big one after all.

Happily, both of these reasons can be mitigated effectively by just admitting up-front that you don’t have a friggin’ clue, and telling people ahead of the fact that your decision is purely preliminary, and might be the wrong thing. You should always reserve the right to change your mind, and make people very _aware_ of that. And it’s much easier to admit that you are stupid when you haven’t _yet_ done the really stupid thing.

Then, when it really does turn out to be stupid, people just roll their eyes and say “Oops, he did it again”.

This preemptive admission of incompetence might also make the people who actually do the work also think twice about whether it’s worth doing or not. After all, if _they_ aren’t certain whether it’s a good idea, you sure as hell shouldn’t encourage them by promising them that what they work on will be included. Make them at least think twice before they embark on a big endeavor.
Remember: they’d better know more about the details than you do, and they usually already think they have the answer to everything. The best thing you can do as a manager is not to instill confidence, but rather a healthy dose of critical thinking on what they do.

Btw, another way to avoid a decision is to plaintively just whine “can’t we just do both?” and look pitiful. Trust me, it works. If it’s not clear which approach is better, they’ll eventually figure it out. The answer may end up being that both teams get so frustrated by the situation that they just give up.

That may sound like a failure, but it’s usually a sign that there was something wrong with both projects, and the reason the people involved couldn’t decide was that they were both wrong. You end up coming up smelling like roses, and you avoided yet another decision that you could have screwed up on.

Chapter 2: People

Most people are idiots, and being a manager means you’ll have to deal with it, and perhaps more importantly, that _they_ have to deal with _you_.

It turns out that while it’s easy to undo technical mistakes, it’s not as easy to undo personality disorders. You just have to live with theirs – and yours.

However, in order to prepare yourself as a kernel manager, it’s best to remember not to burn any bridges, bomb any innocent villagers, or alienate too many kernel developers. It turns out that alienating people is fairly easy, and un-alienating them is hard. Thus “alienating” immediately falls under the heading of “not reversible”, and becomes a no-no according to Chapter 1.

There’s just a few simple rules here:

(1) don’t call people d*ckheads (at least not in public)
(2) learn how to apologize when you forgot rule (1)

The problem with #1 is that it’s very easy to do, since you can say “you’re a d*ckhead” in millions of different ways (*), sometimes without even realizing it, and almost always with a white-hot conviction that you are right.

And the more convinced you are that you are right (and let’s face it, you can call just about _anybody_ a d*ckhead, and you often _will_ be right), the harder it ends up being to apologize afterwards.

To solve this problem, you really only have two options:
– get really good at apologies
– spread the “love” out so evenly that nobody really ends up feeling like they get unfairly targeted. Make it inventive enough, and they might even be amused.

The option of being unfailingly polite really doesn’t exist. Nobody will trust somebody who is so clearly hiding his true character.

(*) Paul Simon sang “Fifty Ways to Lose Your Lover”, because quite frankly, “A Million Ways to Tell a Developer He Is a D*ckhead” doesn’t scan nearly as well. But I’m sure he thought about it.

Chapter 3: People II – the Good Kind

While it turns out that most people are idiots, the corollary to that is sadly that you are one too, and that while we can all bask in the secure knowledge that we’re better than the average person (let’s face it, nobody ever believes that they’re average or below-average), we should also admit that we’re not the sharpest knife around, and there will be other people that are less of an idiot that you are.

Some people react badly to smart people. Others take advantage of them.
Make sure that you, as a kernel maintainer, are in the second group. Suck up to them, because they are the people who will make your job easier. In particular, they’ll be able to make your decisions for you, which is what the game is all about.

So when you find somebody smarter than you are, just coast along. Your management responsibilities largely become ones of saying “Sounds like a good idea – go wild”, or “That sounds good, but what about xxx?”. The second version in particular is a great way to either learn something new about “xxx” or seem _extra_ managerial by pointing out something the smarter person hadn’t thought about. In either case, you win.

One thing to look out for is to realize that greatness in one area does not necessarily translate to other areas. So you might prod people in specific directions, but let’s face it, they might be good at what they do, and suck at everything else. The good news is that people tend to naturally gravitate back to what they are good at, so it’s not like you are doing something irreversible when you _do_ prod them in some direction, just don’t push too hard.

Chapter 4: Placing blame

Things will go wrong, and people want somebody to blame. Tag, you’re it.
It’s not actually that hard to accept the blame, especially if people kind of realize that it wasn’t _all_ your fault. Which brings us to the best way of taking the blame: do it for another guy. You’ll feel good for taking the fall, he’ll feel good about not getting blamed, and the guy who lost his whole 36GB porn-collection because of your incompetence will grudgingly admit that you at least didn’t try to weasel out of it.

Then make the developer who really screwed up (if you can find him) know _in_private_ that he screwed up. Not just so he can avoid it in the future, but so that he knows he owes you one. And, perhaps even more importantly, he’s also likely the person who can fix it. Because, let’s face it, it sure ain’t you.

Taking the blame is also why you get to be manager in the first place. It’s part of what makes people trust you, and allow you the potential glory, because you’re the one who gets to say “I screwed up”. And if you’ve followed the previous rules, you’ll be pretty good at saying that by now.

Chapter 5: Things to avoid

There’s one thing people hate even more than being called “d*ckhead”, and that is being called a “d*ckhead” in a sanctimonious voice. The first you can apologize for, the second one you won’t really get the chance. They likely will no longer be listening even if you otherwise do a good job.

We all think we’re better than anybody else, which means that when somebody else puts on airs, it _really_ rubs us the wrong way. You may be morally and intellectually superior to everybody around you, but don’t try to make it too obvious unless you really _intend_ to irritate somebody (*).
Similarly, don’t be too polite or subtle about things. Politeness easily ends up going overboard and hiding the problem, and as they say, “On the internet, nobody can hear you being subtle”. Use a big blunt object to hammer the point in, because you can’t really depend on people getting your point otherwise.

Some humor can help pad both the bluntness and the moralizing. Going overboard to the point of being ridiculous can drive a point home without making it painful to the recipient, who just thinks you’re being silly. It can thus help get through the personal mental block we all have about criticism.

(*) Hint: internet newsgroups that are not directly related to your work are great ways to take out your frustrations at other people. Write insulting posts with a sneer just to get into a good flame every once in a while, and you’ll feel cleansed. Just don’t crap too close to home.

Chapter 6: Why me?

Since your main responsibility seems to be to take the blame for other peoples mistakes, and make it painfully obvious to everybody else that you’re incompetent, the obvious question becomes one of why do it in the first place?

First off, while you may or may not get screaming teenage girls (or boys, let’s not be judgmental or sexist here) knocking on your dressing room door, you _will_ get an immense feeling of personal accomplishment for being “in charge”. Never mind the fact that you’re really leading by trying to keep up with everybody else and running after them as fast as you can. Everybody will still think you’re the person in charge.

It’s a great job if you can hack it.

参考:原文地址

Linux内核管理风范


Linux内核的管理风格
Linus Torvalds

这个简单文档描述Linux内核偏爱的(或编造的,取决于你问谁)管理模式。它在一定程度上是编码风格文档的影子,主要写来避免一遍又一遍回答同一类问题*。

管理风格是很个人化的,比起简单的编码风格条例更难量化,所以这个文档跟现实可能沾边也可能不沾边。它开始于游戏,但是不见得就不作数。你只有自个儿决定。
顺便说一下,我们说到”内核管理者”的时候,完全是说技术带头人,不是公司里那些作传统管理工作的人。如果你是在订单上签名的人或者对你们组的预算知道一丁半点,你几乎一定不是个”内核管理者”。这些建议对你可能适用也可能不适用。
首先,我建议你买一本《高度成功人士的七个习惯》,不-要读它,烧了。表一下决心。
(*) 这个文档不见得”回答”多少问题,更大程度上是展示我们的无知,让提问者死了这条心。

不管怎样,开讲了:

第一章:决定

每个人都觉得管理者是作决定的,作决定是很重要的。决定越大、越艰难,管理者就越伟大。这一点很深刻、很明显,但不见得正确。

事情的要义是避免-作决定的必要性。特别是,当有人告诉你”是甲还是乙,我们需要你来作决定”,你作管理的麻烦就来了。你手下的人一般比你更懂具体问题,所以要是他们找你作一个技术性的决定,你死定了。要替他们作决定,你显然水平不够。

(推论:如果你手下的人不比你更懂具体问题,你还是死定了,尽管出于完全不同的原因。说白了就是你站错了岗位,应该他们-来管理你的才华才对。)

所以要义是避免-决定,至少避免大的和艰难的决定。作小的、不重要的决定还好了,而且让你挺挺板板、面上有光。所以一个内核管理者需要的是把大的艰难的决定变成没人在乎的小事情。
帮你点拨一下,大决定和小决定的区别在于你能否事后修补得了。如果你犯错了的时候(而且你会-犯错),你能返回来弥补损失,那么你可以把任何的决定变成”小决定”。一下子,你的表现机会多了一倍:你要作两-个不重要的决定,错误决定”加上”正确决定。
而且大家甚至会认为这是领导才能(咳咳,狗屁,咳咳)。因此避免作重大决定的要点成了仅仅避免做不可逆反的事情。不要被牵引到一个无路可逃的角落里。困在角落里的耗子或许是危险的,困在角落里的管理者不过是个可怜虫。
事实上,不管怎样-,没有人会愚蠢到让一个内核管理者承担太大的财政责任,所以纠正错误一般不是多难。既然你没有机会浪费掉你倾家荡产也还不清的巨额经费,你要纠正的不过是一个技术性的决定。那就好办了:告诉每个人你是个不称职的白痴,说对不起,把你让大家上一年作的无用功都扔掉。一下子,你一年前作的决定也不见得是什么重大决定,既然能简单的撤销掉。
然而事实上,有些人搞不来这个办法。有两个原因:
(一)承认自己是傻瓜做起来蛮难的。我们都喜欢保持形象,公开认错有时候是很困难。
(二)对下级的工程师来说,被人告知自己上一年的工作落得一文不值,也是很恼火的。实际的工作结果-可以删除了事,但你可能就永久性的失去了这个工程师的信任。记住,”永久性”是我们要避免的第一件事,这样你的决定最终还是一个重大决定。
所幸的是,你对两个原因都可以棋高一着,未雨绸缪,防患未然。办法是:事先就承认你狗屁不懂,告诉大家你的决定不过是摸着石头过河,说不定就掉河里了。
你应该永远保留改变决定的权利,而且要让大家明白-这一点。而且在你做了真正的傻事之前承认你是个傻瓜要容易的多。
这样,当事情真的到了傻冒的地步,人们不过是翻下眼皮,说:”唉……真是灵验啊……”
这种事先承认不足的做法可能还会让下面真正做事的人三思而后行,想一下值不值。说回来,如果他们-都不确定是个好主意,你铁定了不应该给他们开绿灯,煽风点火。至少要让他们在开始大动作之前好好想一下。

记住:他们在细节上应该知道的比你多,而且他们一般觉得一切已在掌握之中。作为管理者,你能做的最好的事情不是给他们填充信心,而是给他们适量的批判理性。
顺便说一下,另外一个避免决定的办法是装可怜,简单地问”我们为什么不能两个都做呢?” 相信我,这个有用。如果不清楚哪条路子更好一些,他们最终会整明白的。答案或许是两帮人都挫败灰心,双双放弃。
这听起来像是个失败,但它一般是两个项目都有问题的迹象,大家无法决定的原因是双方都错了。结果是你成了智慧的舵手,而且你又避免了一个本来会死得很难看的决定。

第二章:人

大多数人都是傻瓜,当管理者就意味着你不得不和这一点打交道。或许更重要的是,他们-不得不和你-打交道。

事实证明,消除技术性问题还是容易的,消除人脑筋里的问题就没那么容易了。你就不得不忍受这些问题,他们的还有你自个儿的问题。

然而,为了做好内核管理者,最好记住不要自绝后路,伤及无辜,或树敌过众。现实是,疏远人们是蛮容易的,把他们拉拢回来就难了。因此”疏远”直接归类到”不可逆反”的事情里,就是第一章里说的大忌。

这里只有两条简单的规则:
(一)不要骂人猪头(至少不要在公开场合下)
(二)要是你忘了第一条,学会怎样道歉
第一条的问题是太容易违反,因为你有一万种骂人猪头的办法*,有时不自觉就骂了,而且几乎总是义愤填膺、义正严词。
而且你越是骂的热血沸腾(让我们来面对事实,你可以骂几乎任何-人猪头,你往往不-会骂错),事后你越难道歉。
要解决这个问题,你其实只有两条路子:
(一)成为道歉专家
(二)”遍洒博爱,处处留情”,这样没有人会觉得受到了特殊待遇。骂出新意,骂出水准,他们没准会找到艺术的享受。
第三条路子,始终如一的作谦谦君子,是行不通的。没有人会信任城府太深的人。
*保罗西蒙的歌唱道”失恋五十种”,是因为老实说,”骂一个程序员猪头一万种”没有那么押韵。不过我相信他肯定考虑过这个。

第三章:能人

尽管现实是大多数人都是傻瓜,不幸的推论包括你也是傻瓜之一,尽管我们都心安理得的自认比傻瓜高明(让我们来面对事实,没有人自认傻瓜或不如傻瓜),我们还是应该承认我们不是独步江湖,总会有一些人不像我们一样的傻瓜。一些人嫉贤妒能,另一些人从善如流。

确定你,作为一个内核管理者,属于第二种。贴紧了高手能人,因为他们会使你的工作变容易。特别是,他们将能够替你作决定,这正是事情的要义。
所以你要是发现了比你聪明的人,顺水推舟好了。你的管理职责很大程度上就成了说一下”听起来是个好主意,放手去干吧”,或者”这个不错,那个XXX怎么样呢?”。第二个版本尤其有效:你要么学到一些关于”XXX”的新东西,要么指出了聪明人都没想到的东西,表现得胸有-韬略。随便那种情况,你都是赢家。
另外一件要小心的事情是,一个人在一方面厉害不见得在其他方面也厉害。你或许煽动谁做什么,但是让我们来面对事实,他或许精通自己的一亩三分地却其他什么都做不来。好的消息是,人们自然而然的倾向于选择自己擅长的事情来做。所以你真的-煽动一下,一般不见得会造成什么不可逆反的后果,只是不要用铁扇公主的芭蕉扇来煽。

第四章:担当

事情总会出错的,大家会找人来责怪。哈,就是你了。

担当责任其实不是那么难的,尤其是当大家心里也有数,不全-是你的错的时候。这带来了担当责任的最好的方式:代人受过。你会因为挑起了担子而心安,那个真正搞砸了的家伙不会成为众矢之的而颓废,至于那个因为你的失职而丢失了半个硬盘的A片的家伙,也会嘟嘟囔囔的承认你至少没有猥猥琐琐的推卸责任。
然后,私下-告诉那个搞砸了的家伙是他搞砸了(如果你能发现他的话)。这样不仅让他以后避免重犯,而且让他知道他欠你一个人情。而且,或许更重要的是,他可能就是那个能修补事故的人。因为,让我们来面对事实,你肯定不行。
担当责任也是最初你来作管理者的原因。这是领导者的本分。大家能信任你,给你荣誉,是因为你在必要的时候能说”是我不好”。而且如果你已经遵循了前面的规则,你现在说这个应该很在行了。

第五章:禁区

比骂人”猪头”更招人恨的是用挖苦的语调骂人”猪头”。你可以为前一个道歉,后一个你都不会有道歉的机会。即使你其他方面都做的很好,他们可能也不会再听你的了。

我们都自我感觉良好,就是说当别人指手划脚的时候,真的-是可忍孰不可忍。你可能在才智品行上超出你周围所有的人,但是你要不是真的想-招惹谁的话*,不要”表现”得太明显。类似的,处理问题不要太客气或微妙。客气往往会隔靴搔痒,不得要害。就像人家说的,”在互联网上,没有人听得到你微妙”。大张旗鼓、锣鼓喧天的把你的意见摆出来,不然你没法指望大家领悟到。
一点幽默可以帮助润滑你的蛮横和说教。过分夸张到荒诞的地步,既能充分表达你的观点,又不至于让对方难堪,因为他只会认为你在发疯。这样就可以绕过我们每个人都有的、抵制批评的心理盲区。
*支一招:和你的工作不直接相关的网络论坛(译者按:Linus是说新闻组。没看到西方国家的论坛事业有中国这么发达。)是发泄的好地方。隔三岔五的,狞笑着写点侮辱人的帖子来点燃战火,会让你再次焕发青春。只是不要把战火烧到自己的老巢。

第六章:为什么是我?

既然你的主要职责好像就是代人受过,赤裸裸的展示自己如何不称职,显然的问题是:那你为什么还要做呢?
首要的是,可能有也可能没有尖叫着的小女生(或者小男生,我们不要作道学家或性别岐视)来敲你更衣室的门,作”负责人”会-给你带来巨大的个人成就感。不用说你的”领导”其实是拼命从后面追赶大家、努力跟上大家的步伐。每个人还是会认为你是”负责人”。

如果你能驾驭得了,这是一项伟大的工作。

参考:原文地址

汉字繁简体互换

1、chs2cht.h

#pragma once
char* UnicodeToBIG5(const wchar_t* szUnicodeString);
char* UnicodeToGB2312(const wchar_t* szUnicodeString);
wchar_t* GB2312ToUnicode(const char* szGBString);
char* GB2312ToBIG5(const char* szGBString);

2、chs2cht.cpp

#include "chs2cht.h"
#include <atlstr.h>
//GB2312 转 Unicode:
wchar_t* GB2312ToUnicode(const char* szGBString)  
{  
	UINT nCodePage = 936; //GB2312  
	int nLength=MultiByteToWideChar(nCodePage,0,szGBString,-1,NULL,0);  
	wchar_t* pBuffer = new wchar_t[nLength+1];  
	MultiByteToWideChar(nCodePage,0,szGBString,-1,pBuffer,nLength);  
	pBuffer[nLength]=0;  
	return pBuffer;  
}

//BIG5 转 Unicode:  
wchar_t* BIG5ToUnicode(const char* szBIG5String)  
{  
	UINT nCodePage = 950; //BIG5  
	int nLength=MultiByteToWideChar(nCodePage,0,szBIG5String,-1,NULL,0);  
	wchar_t* pBuffer = new wchar_t[nLength+1];  
	MultiByteToWideChar(nCodePage,0,szBIG5String,-1,pBuffer,nLength);  
	pBuffer[nLength]=0;  
	return pBuffer;  
}

//Unicode 转 GB2312:  
char* UnicodeToGB2312(const wchar_t* szUnicodeString)  
{  
	UINT nCodePage = 936; //GB2312  
	int nLength=WideCharToMultiByte(nCodePage,0,szUnicodeString,-1,NULL,0,NULL,NULL);  
	char* pBuffer=new char[nLength+1];  
	WideCharToMultiByte(nCodePage,0,szUnicodeString,-1,pBuffer,nLength,NULL,NULL);  
	pBuffer[nLength]=0;  
	return pBuffer;  
}

//Unicode 转 BIG5:  
char* UnicodeToBIG5(const wchar_t* szUnicodeString)  
{  
	UINT nCodePage = 950; //BIG5  
	int nLength=WideCharToMultiByte(nCodePage,0,szUnicodeString,-1,NULL,0,NULL,NULL);  
	char* pBuffer=new char[nLength+1];  
	WideCharToMultiByte(nCodePage,0,szUnicodeString,-1,pBuffer,nLength,NULL,NULL);  
	pBuffer[nLength]=0;  
	return pBuffer;  
}

//繁体中文BIG5 转 简体中文GB2312  
char* BIG5ToGB2312(const char* szBIG5String)  
{  
	LCID lcid = MAKELCID(MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED),SORT_CHINESE_PRC);  
	wchar_t* szUnicodeBuff = BIG5ToUnicode(szBIG5String);  
	char* szGB2312Buff = UnicodeToGB2312(szUnicodeBuff);  
	int nLength = LCMapStringA(lcid,LCMAP_SIMPLIFIED_CHINESE, (LPCSTR)szGB2312Buff,-1,NULL,0);  
	char* pBuffer = new char[nLength + 1];  
	LCMapStringA(0x0804,LCMAP_SIMPLIFIED_CHINESE,(LPCSTR)szGB2312Buff,-1,pBuffer,nLength);  
	pBuffer[nLength] = 0;  

	delete[] szUnicodeBuff;  
	delete[] szGB2312Buff;  
	return pBuffer;  
}

//简体中文GB2312 转 繁体中文BIG5  
char* GB2312ToBIG5(const char* szGBString)  
{  
	LCID lcid = MAKELCID(MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED),SORT_CHINESE_PRC);  
	int nLength = LCMapStringA(lcid,LCMAP_TRADITIONAL_CHINESE,szGBString,-1,NULL,0);  
	char* pBuffer=new char[nLength+1];  
	LCMapStringA(lcid,LCMAP_TRADITIONAL_CHINESE,szGBString,-1,pBuffer,nLength);  
	pBuffer[nLength]=0;  
	wchar_t* pUnicodeBuff = GB2312ToUnicode(pBuffer);  
	char* pBIG5Buff = UnicodeToBIG5(pUnicodeBuff);  
	delete[] pBuffer;  
	delete[] pUnicodeBuff;  
	return pBIG5Buff;  
}

3、test.cpp

#include "chs2cht.h"
#include <iostream> 
#include <locale.h>
#include <atlstr.h>  

using namespace std;

int main(int argc, char** argv)
{
    //“区域设置”为简体中文 
    locale loc( "chs" ); 
    char str[100];  
    cin>>str;  
    
    char * rlt=GB2312ToBIG5(str);  
    CString cStr1;   
    cStr1.Format( TEXT("%s"),rlt); 

    //“区域设置”为繁体中文 
    setlocale(LC_ALL, ".950");  
    cout<<rlt<<endl; 

    return 0;
}

关于汉字编码

关于汉字编码

  为进行信息交换,各汉字使用地区都制订了一系列汉字字符集标准。

  1、 GB2313字符集,收入汉字6763个,符号715个,总计7478个字符,这是大陆普遍使用的简体字符集。楷体-GB2313、仿宋-GB2313、华文行楷等市面上绝大多数字体支持显示这个字符集,亦是大多数输入法所采用的字符集。市面上绝大多数所谓的繁体字体,其实采用的是GB-2313字符集简体字的编码,用字体显示为繁体字,而不是直接用GBK字符集中繁体字的编码,错误百出。

  2、 BIG-5字符集,收入13060个繁体汉字,808个符号,总计13868个字符,目前普遍使用于台湾、香港等地区。台湾教育部标准宋体楷体等港台大多数字体支持这个字符集的显示。

  3、 GBK字符集,又称大字符集(GB=GuóBiāo国标,K=扩展),包含以上两种字符集汉字,收入21003个汉字,882个符号,共计21885个字符,包括了中日韩(CJK)统一汉字20902个、扩展A集(CJK Ext-A) 中的汉字52个。Windows 95\98简体中文版就带有这个GBK.txt文件。宋体、隶书、黑体、幼圆、华文中宋、华文细黑、华文楷体、标楷体(DFKai-SB)、Arial Unicode MS、MingLiU、PMingLiU等字体支持显示这个字符集。微软拼音输入法2003、全拼、紫光拼音等输入法,能够录入如镕镕炁夬喆嚞姤赟赟龑昳堃慜靕臹等GBK简繁体汉字。

  4、BIG-5 (繁体中文)与GB-2313 (简体中文),编码不相兼容,字符在不同的操作系统中便产生乱码。文本文字的简体与繁体(文字及编码)之间的转换,可用BabelPad、TextPro或Convertz之类的转码软件来解决。若是程序,Windows XP操作系统,可用Microsoft AppLocale Utility 1.0解决;Windows 2000的操作系统,大概只有用:中文之星、四通利方、南极星、金山快译之类的转码软件方能解决了。

  5、 GB18030字符集,包含GBK字符集、CJK Ext-A 全部6582个汉字,共计27533个汉字。宋体-18030、方正楷体(FZKai-Z03)、书同文楷体(MS Song)宋体(ht_cjk+)、香港华康标准宋体(DFSongStd)、华康香港标准楷体、CERG Chinese Font、韩国New Gulim,以及微软Windows Vista操作系统提供的宋黑楷仿宋等字体亦支持这个字符集的显示。Windows 98支持这个字符集,以下的字符集则不支持。手写输入法逍遥笔4.0版支持GB18030字符集及方正超大字符集汉字的录入。

  6、 方正超大字符集,包含GB18030字符集、CJK Ext-B中的36862个汉字,共计64395个汉字。宋体-方正超大字符集支持这个字符集的显示。Microsoft Office XP或2003简体中文版就自带有这个字体。Windows 2000的操作系统需安装超大字符集支持包“Surrogate更新”。

  7、 ISO/IEC 10646 / Unicode字符集,这是全球可以共享的编码字符集,两者相互兼融,涵盖了世界上主要语文的字符,其中包括简繁体汉字,计有:CJK统一汉字20902个,CJK Ext-A 6582个,Ext-B 42711个,共计70195个汉字。SimSun-ExtB(宋体)、MingLiU-ExtB(细明体)能显示全部Ext-B汉字。至今尚无单独一款字体能够显示全部70195个汉字,但可用海峰五笔、新概念五笔、仓颉输入法世纪版、新版的微软新注音、仓颉输入法 6.0 版(单码功能)等输入法录入。Ext-C还有2万多个汉字。详情请参阅香港中文大学网站、马来西亚仓颉之友网站、福建陈清钰个人网站。

  8、 汉字构形数据库2.3版,内含楷书字形60082个、小篆11100个、楚系简帛文字2627个、金文3459个、甲骨文177个、异体字12768组。可以安装该程序,亦可以解压后使用其中的字体文件,对于整理某些古代文献十分有用。

  如果超出了输入法所支持的字符集,就不能录入计算机。如果没有相应字体的支持,则显示为黑框、方框或空白。如果操作系统或应用软件不支持该字符集,则显示为问号(一个或两个)。在网页上亦存在同样的情况。

关于Unicode

  由于各国国家标准字集所收的汉字字数、常用字的差异,虽然象中国两岸GB/BIG5字集常用字基本类似,转换后阅读并不成问题,但是这种编码转换的混乱关系,对文字交流始终是一种障碍。因此相关国家的标准化组织和文字工作者经过共同努力,终于在93年完成了包含中日韩(CJK)汉字的Unicode 汉字标准ISO 10646.1。 Unicode是完全双字节表示的多国文字编码体系,编码空间0x0000-0xFFFF。 ISO 10646.1汉字标准使用编码0x4E00-9FA5,共包含20902个汉字。其中: 大陆(S)提出的汉字17124个,台湾(T)提出的汉字17258个; S与T的并集,即中国(C)提出的汉字为20158个。 日本(J)提出的汉字为12157个,中国未提出的690个(Ja); 韩国(K)提出的汉字为7477个,其中中国未提出的90个(Ka); Ja与Ka并集共744字。 支持Unicode编码的相关电脑系统软件,如Unix, Win95已有推出,但是由于Unicode的ASCII码是用双字节编码(即一般电脑系统中的单字节ASCII码前加 0x00),同时其汉字编码与各国的现有编码也不兼容,造成现有的软件和数据不能直接使用,所以目前完全使用Unicode软件系统的用户并不多,大多数只将它此作为一个国际语言编码标准来使用。

原文:汉字简介

我和Google Play Music的悲惨故事2

小米2S刷原生后,使用Google Play Music有个比较烦的问题,就是其默认存储路径在第一存储上(只有4G),第二存储(存储卡)上几十G都是空的。

终于,某一天第一存储爆了,但我不想删程序啊。

回头一想,nnd,Android不就是linux吗,这个简单了

1、将/data/data/com.google.android.music/files/music整个文件夹移
动到存储卡上/storage/sdcard0/googleplay/.hide/music上
2、用ln命令,在原位置创建一个连接
3、打开Google Play Music,一切正常,哈哈哈哈哈

第二天发现,Google Play Music把/storage/sdcard0/googleplay/.hide/music的音乐又加了一般,
而且没有Tag,整个一悲剧啊。

那就Google一下,发现在文件夹下创建.nomedia文件后,可以防止Google Play Music进行扫描。

很Happy的到music文件夹下去看看,发现.nomedia已经躺在那里好久了,这~~

死马当活马医了,那就在googleplay和.hide都增加一下.nomedia,然后重启

居然好了~~

好吧~~

就这么先用着吧~~

我和Google Play Music的悲惨故事1

去年入手了一款小米2S,回来第一时间刷成了原生Android4.1.1,取得Root权限。

后来慢慢发现Google Play Music这款工具不错,操作简便,还能同步Google音乐,于是就开始Happy的使用了。

出于尊重正版的单纯想法,买了200多首歌曲,除了没有歌词,感觉还不错。

但有个问题,Google Play Music没有IOS版本啊,这个坑爹啊。

我把音乐从手机拷贝出来,发现MP3的Tag一个都没有,这不是坑爹吗。

于是开始分析Google Play Music的存储方式:
1、mp3音频文件存在/data/data/com.google.android.music/files/music下面
2、mp3的封面文件存在/data/data/com.google.android.music/files/artwork下面
3、mp3的Tag信息,及存储路径存在/data/data/com.google.android.music/databases/music.db下面

好吧那就分析下music.db文件吧:
只有一张表是我关心的,就是MUSIC表

然后,当然是写程序搞定啊,用Java ID3 Tag Library 0.5.4(org.farng.mp3) + sqlite-jdbc-3.7.2两个包,
从MUSIC表读出Tag,然后将Tag和封面图片写入到新的.mp3文件中。

经过2小时奋战,处理了JDBC无法连接和TAG乱码两个问题,搞定。

然后放到iTunes中,同步。

然后带封面的mp3就可以用了。

哈哈哈哈哈,开心了好几天。

后来发现,Google可以在线下载,但只能下两次。

再后来发现,Google出了Music Manager,虽然上传下载的都会经常中断,但有一个好处,
那就是我自己捣腾的mp3,用第三方软件无法找到歌词,但用Music Manager导出的软件,用第三方软件可以找到歌词。

悲剧啊,浪费了好几个小时~~

JS编辑器研究

最近项目需要用到JS编辑器,找了一些开源项目看了下(由于客户浏览器版本不高,HTML5版本几乎无法使用),
就找到了下面三个比较靠谱一点的编辑器:

nicEdit 无jQuery 小巧,易于集成,功能有限
elrte 有jQuery 功能强大,易于集成,但很久没更新了
ckeditor 有jQuery 功能强大,更新给力,易集成性貌似差一些

回头找找看,还有没有其他靠谱的工具。

修改Thunderbird Mbox文件,找回丢失邮件

今天周六,起了个早,吃了早饭,沏上茶,一边洗衣服,一遍happy的看邮件。
邮件积攒的太多,于是操作就太快,结果,不知道为什么,一片邮件就消失了。

重要提示:
以下所有操作的前提是:进行完全备份

于是,尝试了重建所在文件夹的.msf索引文件,有两种方式:
1、在文件夹上,右击-》属性-》修复文件夹
2、关闭thunderbird,到邮箱路径下,删掉文件夹的.msf文件,重新打开Thunderbird
然后发现,只找回一部分邮件来。

这可不行,好多邮件很重要,于是,进行了大还原:
关闭Thunderbird,将global-messages-db.sqlite命名为global-messages-db.sqlite.bak,重启Thunderbird。
还是不行~~
哭的心都有了

好吧,找工具~~
尝试了ZMail和Advanced Media Recovery,测试证明,根本不好用~~

那只好找资料,自己开搞了。
Thunderbird的一个最底层邮件文件夹,由两部分组成,
没有后缀的MBox文件,和有后缀的.msf索引文件。

MBox就是邮件和附件的全部了,经过摸索,发现有以下规律
1、MBox可以用靠谱的文本编辑工具进行编辑,用notepad的同学们,您就省省吧
2、每一封邮件都是一段MIME格式的文本,每封邮件以如下格式开始,直到下一个”From – “结束

From - Thu Dec 19 01:26:18 2013
X-Account-Key: account4
X-UIDL: ZC0418-TJAs6xVgg1PigBtJ_pc_a3c
X-Mozilla-Status: 0001
X-Mozilla-Status2: 00000000
X-Mozilla-Keys:                                                                                 
X-QQ-SSF: 00410000000000F0
X-QQ-BUSINESS-ORIGIN: 2
X-Originating-IP: 112.65.5.74
X-QQ-STYLE: 
X-QQ-mid: bizmail35t1387361723t6111701
From: "=?utf-8?B?5pyx6I6J6Imz?=" <xxx@xxx.com>
To: "=?utf-8?B?6auY5pmX?=" <xxx@xxx.com>

3、邮件根据编码不同,主要有gb2312,utf-8和BASE64编码三种
4、附件以MIME方式存储在邮件下面,如:

MIME-Version: 1.0
Content-Type: multipart/related;
	boundary="----=_NextPart_000_0007_01CE78E0.0A87C340"
...

5、两份邮件之间,没有关联关系,可以随便修改顺序,可以随便剪切复制粘贴,但要保证每一封邮件的完整性
6、邮件的状态,由以下两个标志位指定

module Mbox
  #X-Mozilla-Status
  #Message has been read.
  MSG_FLAG_READ=0x0001
  #A reply has been successfully sent.
  MSG_FLAG_REPLIED=0x0002
  #The user has flagged this message.
  MSG_FLAG_MARKED=0x0004
  #Already gone (when folder not compacted). Since actually removing a message from a folder is a semi-expensive operation, we tend to delay it; messages with this bit set will be removed the next time folder compaction is done. Once this bit is set, it never gets un-set.
  MSG_FLAG_EXPUNGED=0x0008
  #Whether subject has “Re:” on the front. The folder summary uniquifies all of the strings in it, and to help this, any string which begins with “Re:” has that stripped first. This bit is then set, so that when presenting the message, we know to put it back (since the “Re:” is not itself stored in the file).
  MSG_FLAG_HAS_RE=0x0010
  #Whether the children of this sub-thread are folded in the display.
  MSG_FLAG_ELIDED=0x0020
  #DB has offline news or imap article.
  MSG_FLAG_OFFLINE=0x0080
  #If set, this thread is watched.
  MSG_FLAG_WATCHED=0x0100
  #If set, then this message's sender has been authenticated when sending this msg. This means the POP3 server gave a positive answer to the XSENDER command. Since this command is no standard and only known by few servers, this flag is unmeaning in most cases.
  MSG_FLAG_SENDER_AUTHED=0x0200
  #If set, then this message's body contains not the whole message, and a link is available in the message to download the rest of it from the POP server. This can be only a few lines of the message (in case of size restriction for the download of messages) or nothing at all (in case of “Fetch headers only”)
  MSG_FLAG_PARTIAL=0x0400
  #If set, this message is queued for delivery. This only ever gets set on messages in the queue folder, but is used to protect against the case of other messages having made their way in there somehow – if some other program put a message in the queue, it won't be delivered later!
  MSG_FLAG_QUEUED=0x0800
  #This message has been forwarded.
  MSG_FLAG_FORWARDED=0x1000
  #These are used to remember the message priority in interal status flags.
  MSG_FLAG_PRIORITIES=0xE000

  
  #X-Mozilla-Status2
  #This message is new since the last time the folder was closed.
  MSG_FLAG2_NEW=0x00010000
  #If set, this thread is ignored.
  MSG_FLAG2_IGNORED=0x00040000
  #If set, this message is marked as deleted on the server. This only applies to messages on IMAP servers.
  MSG_FLAG2_IMAP_DELETED=0x00200000
  #This message required to send a MDN (Message Disposition Notification) to the sender of the message. For information about MDN see Wikipedia:Return receipt.
  MSG_FLAG2_MDN_REPORT_NEEDED=0x00400000
  #An MDN report message has been sent for this message. No more MDN report should be sent to the sender.
  MSG_FLAG2_MDN_REPORT_SENT=0x00800000
  #If set, this message is a template.
  MSG_FLAG2_TEMPLATE=0x01000000
  #These are used to store the message label.
  #label value
  #1 0x02000000
  #2 0x04000000
  #3 0x06000000
  #4 0x08000000
  #5 0x0A000000
  #6 0x0C000000
  #7 0x0E000000
  MSG_FLAG2_LABELS=0x0E000000
  #If set, this message has files attached to it.
  MSG_FLAG2_ATTACHMENT=0x10000000 
end

这样就好办了,写了个程序,查找每个mbox文件内的每个EMail,查看状态,找出状态错误的邮件:
PS:Ruby加起来学了没几天,哈哈哈

#!/usr/bin/ruby

class EnumFiles
  def enumFiles(folderPath)
    #枚举文件
    files = Dir.glob(folderPath+"*")
    return files
  end
  
  def enumFilesAll(folderPath)
    #枚举文件
    files = Dir.glob(folderPath+"**/*")
    return files
  end
end
#!/usr/bin/ruby

class ReadMbox
  def readLine(filePath)
    if File.exist?(filePath)
      f = File.open(filePath,"r+")
      lines=f.readlines
      return lines
    else
      puts(filePath + " does not exist")
    end
  end
  
  def readMsgNum(filePath,rootPath)
    msgNum=0
    msgErr=0
    bError=false
    
    if File.exist?(filePath)
          f = File.open(filePath,"r+")
          f.each{|l|
            if(l[0..6]=="From - ")
              msgNum=msgNum+1
              bError=false
            end
            
            if(l[0..17]=="X-Mozilla-Status: ") && (!bError)
              flag = l[18..21].to_i(16)
              if(flag & 0x0008 > 0)
                puts("]>"+l)
                msgErr=msgErr+1
                bError=true
              end
            end
      
            if(l[0..18]=="X-Mozilla-Status2: ") && (!bError)
              flag2 = l[19..26].to_i(16)
              if(flag2 & 0x00040000 > 0)
                puts("]>"+l)
                msgErr=msgErr+1
                bError=true
              end
            end
          }
    end
          
    puts(filePath.gsub(rootPath,"")+" EmailNum=\t"+msgNum.to_s()+"\terrNum=\t"+msgErr.to_s())
  end
end
#!/usr/bin/ruby

require "./EnumFiles.rb"
require "./ReadMbox.rb"

rootPath="PAHT/TO/MAIL/

files = EnumFiles.new().enumFilesAll(rootPath)
#puts files

mbox = ReadMbox.new()

files.each do |f|
  if(!File.directory?(f)) && (!(File.extname(f).length>0))
    mbox.readMsgNum(f,rootPath)
  end
end

最后,找到文件,发现并不是很多只有5个,就懒得写程序了,手动剪切到回收站,将标志位置为正常,刷新回收站索引,然后一切就太平啦

X-Mozilla-Status: 0001
X-Mozilla-Status2: 00000000

后记:
其实Thunderbird在删除邮件时(从回收站删除),为提高效率,并不一定会真的将邮件删掉,而很可能只是打上一个标记。

这样,其实只要用一个靠谱的编辑器,比如VIM、PSPad等,就可以很方便的定位到你需要的邮件,然后就可以进行备份和还原啦。

参考:
全局还原索引文件
官方推荐的编辑工具列表
标志位说明
标志位源码

jQuery的AJAX示例

	var textRet;
	var textJson;
	var textUrl;
	var timeoutMS;
	$.ajax( {
		type : 'POST',
		data : textJson,
		url : textUrl,
		dataType : 'json',
		timeout : timeoutMS,
		success : function(jsonRet) {
			//do something here
			textRet=...;
		},
		error:function(jqXHR, textStatus, errorThrown) {
			if(textStatus==='error') {
				//do something here
				textRet=...;
			}
			if(textStatus==='timeout') {
				//do something here
				textRet=...;
			}
                }
	});

Tomcat强制使用HTTPS

配置好Tomcat的SSL后,强制使用HTTPS方法如下:

1、全局强制HTTPS
修改%tomcat_home%\conf\web.xml,在文件底部,后面加上这样一段:

    <login-config>  
        <!-- Authorization setting for SSL -->  
        <auth-method>CLIENT-CERT</auth-method>  
        <realm-name>Client Cert Users-only Area</realm-name>  
    </login-config>  
    <security-constraint>  
        <!-- Authorization setting for SSL -->  
        <web-resource-collection >  
            <web-resource-name >SSL</web-resource-name>  
            <url-pattern>/*</url-pattern>  
        </web-resource-collection>  
        <user-data-constraint>  
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>  
        </user-data-constraint>  
    </security-constraint>  

2、某个webapp强制使用HTTPS
编辑该webapp的web.xml文件,增加以下内容:

	<security-constraint>
	    <web-resource-collection>
	        <web-resource-name>securedapp</web-resource-name>
	        <url-pattern>/*</url-pattern>
	    </web-resource-collection>
	    <user-data-constraint>
	        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
	    </user-data-constraint>
	</security-constraint>

关闭 SSL,只需要将CONFIDENTIAL改为NONE即可。