• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            colorful

            zc qq:1337220912

             

            每個(gè)軟件開發(fā)者必須絕對(duì)至少需要了解的Unicode和Character Sets的知識(shí)(沒(méi)有借口!)

            http://blog.csdn.net/natsu1211/article/details/8518398

            每個(gè)軟件開發(fā)者必須絕對(duì)至少需要了解的Unicode和Character Sets的知識(shí)(沒(méi)有借口!)

             

            原文:http://www.joelonsoftware.com/articles/Unicode.html

             

            by Joel Spolsky

            windam

             

            2003.10.8 星期三

            你是否曾經(jīng)對(duì)那個(gè)神秘的Content-Type標(biāo)記感到不解?

            譯注:每個(gè)HTML頁(yè)面的head塊中都可能包含一個(gè)Content-Type標(biāo)記,例如:

            <meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8″ />

            你知道這東西應(yīng)該被放到HTML里,但是你從來(lái)都沒(méi)有確切得弄清楚它到底應(yīng)該是什么?

             

            你是否曾經(jīng)收到過(guò)你朋友從Bulgaria發(fā)來(lái)的Email,它的主題行是“???? ?????? ??? ????”?

             

            當(dāng)我發(fā)現(xiàn)還有那么多的軟件開發(fā)者并沒(méi)有真正領(lǐng)會(huì)關(guān)于字符集(Character sets),編碼(encoding),Unicode以及相關(guān)知識(shí)的時(shí)候,我非常失望。幾年前,FogBUGZ的一個(gè)beta測(cè)試者對(duì)于它是否能處理收到的日語(yǔ)郵件感到疑惑。日語(yǔ)?他們有日文的Email?我不知道。但當(dāng)我仔細(xì)研究我們用來(lái)解析MIME email的商業(yè)ActiveX控件時(shí),我們發(fā)現(xiàn)它恰恰正好對(duì)字符集做了完全錯(cuò)誤的處理,于 是,為了撤銷控件中所做的錯(cuò)誤轉(zhuǎn)換,并正確的重新處理,我們不得不編寫修正它的補(bǔ)救代碼。而當(dāng)我研究另一個(gè)商業(yè)庫(kù)的時(shí)候,發(fā)現(xiàn)它有一樣的完全錯(cuò)誤的字符代 碼實(shí)現(xiàn)。我和那個(gè)代碼庫(kù)的開發(fā)者通信,發(fā)現(xiàn)他的想法是,他們“不能(對(duì)字符集)做任何事(正確的處理)”。就像很多程序員一樣,他只是祈禱著,這一切麻煩 事都可以被吹走。

             

            但事實(shí)上不會(huì)!當(dāng)我發(fā)現(xiàn)流行的web開發(fā)語(yǔ)言PHP幾乎完全的忽略了字符編碼的問(wèn)題,沒(méi)心沒(méi)肺的用了8bit字符,這種傻逼的行為讓開發(fā)好的國(guó)際化web應(yīng)用變得幾乎不可能的時(shí)候,我想,我受夠了。

             

            我在此聲明:如果你是一個(gè)工作在2003年或之后的程序員(此文寫于2003年10月),并且你還沒(méi)有對(duì)字符,字符集,編碼和Unicode有所了解,而且你被我我抓住了,我會(huì)罰你在潛艇里剝6個(gè)月的洋蔥皮!我發(fā)誓我會(huì)這樣做的!

             

            此外還有一事:

             

            這真的沒(méi)那么難

             

            在本文中,我將會(huì)告訴你每個(gè)在工作中的程序員所應(yīng)知道的。所有關(guān)于“plain text = ascii = character就是8bit”的知識(shí)不僅僅是錯(cuò)誤的,而且是錯(cuò)得令人絕望。如果你依然像這樣編程,那么你真不比一個(gè)不信基因的醫(yī)生好到哪里去。在讀完本文之前,請(qǐng)不要再編寫任何一行代碼!

             

            在我開始之前,我應(yīng)該提醒你,如果你是那些少數(shù)懂得國(guó) 際化的知識(shí)的程序員,那么你會(huì)發(fā)現(xiàn)我討論的整個(gè)話題有那么一點(diǎn)過(guò)于簡(jiǎn)化。我僅僅只是希望在此設(shè)立一個(gè)門檻,使得每個(gè)人都理解關(guān)于字符編碼究竟都發(fā)生了些什 么事情,并有希望使寫出的代碼可以在任意語(yǔ)言下正常工作,而非僅僅只能工作在在不帶方言詞匯的英語(yǔ)環(huán)境中。我還要再提醒你,想創(chuàng)建可以在國(guó)際化語(yǔ)言環(huán)境下 工作的軟件,字符處理僅僅只是很小的一部分工作,但是我一次只能寫一個(gè)主題,所以本文就是關(guān)于字符集的。

             

            從歷史的角度

             

            理解一件事情的最簡(jiǎn)單的方法,就是回到它發(fā)生的時(shí)候去。

             

            你可能以為我要在此談?wù)撃切┓浅@吓f的字符集如EBCDIC。嘛,我們不討論那些。EBCDIC和你的生活沒(méi)有關(guān)聯(lián)。我們不需要走到那么遠(yuǎn)古的時(shí)期。

             

            clip_image002[13]回到再近一點(diǎn)的時(shí)間,當(dāng)Unix被發(fā)明,K&R正在寫那本著名的The C Programming Language的時(shí)候,一切都還很簡(jiǎn)單。EBCDIC正逐漸消亡。那時(shí)唯一有意義的就是那些美好的,不包含方言字符的英文字母。于是我們將這套將每一個(gè)字符通過(guò)32到127之間的數(shù)進(jìn)行表示的編碼,記做ASCII。例如,空格是32, 字母“A”是65。這些字符用7個(gè)bit就可以存儲(chǔ)。那個(gè)年代的電腦多數(shù)采用8bit為一字節(jié),因此你不光可以用7個(gè)bit保存每個(gè)可能的ASCII字 符,你還有一個(gè)bit的空余,如果你夠邪惡,你也可以將之用于自己的狡猾目的:WordStar用了一個(gè)很2B的做法——用最高位來(lái)標(biāo)識(shí)一個(gè)單詞的最后一 個(gè)字母,這宣告了WordStar僅能用于英文文本。比32小的編碼被稱為不可打印字符,并且被用來(lái)釋放詛咒——只是開個(gè)玩笑,實(shí)際上它們是控制字符,比 如7可以讓你的電腦發(fā)出蜂鳴聲,12可以讓當(dāng)前頁(yè)紙被送出打印機(jī)并傳入新紙。

             

            如果你只是一個(gè)英語(yǔ)使用者的話,這一切都很美好。

             

            因?yàn)橐粋€(gè)字節(jié)有8個(gè)比特,于是很多人就想,“哎,我們可以使用128-255作為自己的用途”。不過(guò)麻煩在于,很多人同時(shí)有了這個(gè)想法,并且他們關(guān)于如何使用128~255的想法又各不相同。IBM-PC弄出來(lái)一個(gè)被稱為OEM字符集的玩意,為歐洲的語(yǔ)言提供了一些方言字母,以及一串用來(lái)繪制線條的字符如水平條,豎直條,右側(cè)帶有小的拐角的水平條等。這樣,你就可以使用這些畫線字符,在屏幕上繪制整潔漂亮的方框與線條了。你至今依然可以在那些那些運(yùn)行于8088計(jì)算機(jī)的干洗機(jī)上看到這些字符。事實(shí)上,當(dāng)除美國(guó)之外的人們開始購(gòu)買PC時(shí),人們憑空捏造出各種各樣的OEM字符集,都將高128位用于自己的用途。舉例來(lái)說(shuō),在一些PC上,字符碼130被顯示為é,而在以色列銷售的計(jì)算機(jī),這個(gè)字符碼則顯示為希伯來(lái)字母(clip_image004[32]) ,于是,如果美國(guó)人將他們的résumés(簡(jiǎn)歷)發(fā)送到以色列,這簡(jiǎn)歷在到達(dá)后就變成了rclip_image004[33]sumclip_image004[34]s。在很多場(chǎng)合,比如俄語(yǔ)中,關(guān)于如何使用高128位字符有各種各樣的辦法,因此你甚至無(wú)法可靠的交換俄語(yǔ)文檔。

             

            最終,這種混亂無(wú)序的OEM編碼被ANSI標(biāo)準(zhǔn)統(tǒng)一了。在ANSI標(biāo)準(zhǔn)中,所有人都同意對(duì)低128的定義,與ASCII碼保持一致,高128位編碼的處理方式,則取決于你生活在什么地方。這些對(duì)高128位編碼做不同處理的體系被稱為code pages(代碼頁(yè))。所以,例如以色列的DOS使用 的代碼頁(yè)被稱為862,而希臘的用戶使用的代碼頁(yè)是737。這些不同代碼頁(yè)在128以下的部分都是相同的,而對(duì)于128以上的編碼則有不同的處理方案(那 些搞笑的字母皆被含在其中)。MS-DOS的國(guó)家版本中包含了很多上述這種代碼頁(yè),可以處理從英語(yǔ)到冰島語(yǔ)的一切,他們甚至還包括了少數(shù)“多語(yǔ)言”代碼 頁(yè),可以在一臺(tái)電腦上同時(shí)支持世界語(yǔ)和加利西亞語(yǔ)!WOW!但是話說(shuō)回來(lái),由于希伯來(lái)語(yǔ)和希臘語(yǔ)分屬不同的代碼頁(yè),對(duì)大于128的字符有完全不同的解釋,因此除非使用位圖,否則想在一臺(tái)電腦上同時(shí)支持這兩種語(yǔ)言則是一件完全不可能的任務(wù)。

             

            另一方面,在亞洲,事情則更加令人抓狂了,因?yàn)閬喼薜脑S多語(yǔ)言擁有數(shù)以千記的字符,這是無(wú)論如何不可能用8 個(gè)bit進(jìn)行編碼的。這種情況通常是用“DBCS”的方式進(jìn)行解決,也即雙字節(jié)字符集,在雙字節(jié)字符集中,有的字符使用一個(gè)字節(jié)進(jìn)行表示,而有的則需要存 儲(chǔ)在2個(gè)字節(jié)中。這種字符集的問(wèn)題在于,通常想要在字符串中順序遍歷比較容易,但是要想反向遍歷,則幾乎不可能。對(duì)于這類字符串,程序員們最好不要使用 s++或者s–對(duì)其進(jìn)行遍歷,而是最好使用預(yù)定義的函數(shù),例如Windows平臺(tái)上的AnsiNext和AnsiPrev函數(shù),它們知道如何處理這一切亂 七八糟的麻煩事。

             

            但是,絕大多數(shù)人依然以為一個(gè)字節(jié)就恰好對(duì)應(yīng)著一個(gè)字 母,或是一個(gè)字母就是一個(gè)字節(jié)。只要你永遠(yuǎn)不把一個(gè)字符串從一臺(tái)電腦上拷貝到另一臺(tái)電腦上,或者從來(lái)不使用超過(guò)一種語(yǔ)言,這種做法就可以在某種意義上正常 的工作。但是,理所當(dāng)然的,由于因特網(wǎng)的普及,現(xiàn)在將字符串從一臺(tái)電腦拷貝到另一臺(tái)電腦變得越來(lái)越常見,那么這一切做法的基礎(chǔ)就垮臺(tái)了。幸運(yùn)的是,Unicode被發(fā)明了。

             

            Unicode

             

            針對(duì)人們想要?jiǎng)?chuàng)建一個(gè)可以囊括這顆星球上一切可能的書寫系統(tǒng)的字符集的目標(biāo),Unicode 是一次勇敢的嘗試。一些人以為Unicode只是一個(gè)簡(jiǎn)單的16bit編碼,其中的每個(gè)字符都可以擁有16個(gè)bit,因而可以支持最多65536種可能的字符,這種對(duì)Unicode的認(rèn)識(shí),事實(shí)上,是錯(cuò)誤的。這是針對(duì)Unicode流傳得最廣的一種誤解,所以,如果你也是這樣認(rèn)為的,不用覺(jué)得過(guò)于沮喪。

             

            事實(shí)上,Unicode針對(duì)字符有一套完全不同的思路,因此你必須遵循Unicode看待事物的思維模式,否則你什么都理解不了。

             

            直到現(xiàn)在,我們都認(rèn)為一個(gè)字母可以被映射為若干比特,你可以將之存儲(chǔ)于內(nèi)存中或者磁盤上。

             

            例如 A -> 0100 0001

             

            Unicode中,一個(gè)字母被映射到一個(gè)稱為code point的東西,這只是一個(gè)理論上的抽象概念。至于這個(gè)code point如何在內(nèi)存中表示,或是在磁盤中存儲(chǔ),則又是另一回事了。

             

            Unicode中,字母A是抽象的形象。它在天堂中漂浮著:

             

            A

            這個(gè)抽象的Unicode中的A不同于B,且不同于a。但是與A或者A以 及A都是等同的。關(guān)鍵的地方在于,Times New Roman字體中的A與Helvetica字體中的A是相同的字符,而與小寫的“a”是不同的字符。這看起來(lái)并沒(méi)有什么有所疑議的,但是在某些語(yǔ)言中,僅 僅指出一個(gè)字母是什么就可能引發(fā)疑議。德文字母ß究竟是一個(gè)真實(shí)的字母,還是僅僅只是s的另一種花式寫法?如果一個(gè)單詞末尾的字母的形狀改變了,那么這個(gè) 字母是否意味著一個(gè)不同的字母——請(qǐng)作答?在希伯來(lái)文中,上面這個(gè)問(wèn)題的回答為真,而在阿拉伯語(yǔ)中,則為假。無(wú)論如何,Unicode協(xié)會(huì)的那些聰明人們 已經(jīng)在上一個(gè)十年間把這些東西都搞定了,盡管那其中依然包含了一大堆政治上的討價(jià)還價(jià),但是最終的結(jié)果是,你不用再為這些麻煩事而煩神了——他們把這些玩 意都搞定了。

             

            Unicode協(xié)會(huì)為每一個(gè)字母表中的每一個(gè)抽象字母都賦予了一個(gè)Magic number,寫起來(lái)就像是這樣:U+0639。這個(gè)Magic number(魔數(shù))就被稱為code point。其中的U+意味著“Unicode”,而數(shù)字的部分則是16進(jìn)制的(譯注:4位16進(jìn)制數(shù)也就意味著需要16個(gè)bit的存儲(chǔ)空間)。那么U+0639實(shí)際上就是阿拉伯字母Ain。英文字母A則是U+0041。你可以在Windows 2000/XP(譯注:在Vista or Win7上也可)使用charmap實(shí)用工具來(lái)查詢這些code point(譯注:點(diǎn)擊開始菜單,運(yùn)行,輸入charmap回車啟動(dòng)該工具),也可以通過(guò)訪問(wèn)Unicode的網(wǎng)站查詢。

             

            clip_image006[13]

            (譯補(bǔ)圖:這是charmap實(shí)用工具的運(yùn)行界面,其中英文字母A如圖所示恰為U+0041)

             

            并沒(méi)有人真正對(duì)Unicode所能表示字母數(shù)目上限進(jìn)行限制,事實(shí)上,Unicode所能表示的字母數(shù)目可以超過(guò)65536,所以并不是每一個(gè)Unicode字母都可以被塞進(jìn)2字節(jié)的空間中,不過(guò)這只是個(gè)傳聞。

             

            OK,假設(shè)我們有這樣一個(gè)字符串

             

            Hello

            Unicode中,這被表示為以下五個(gè)code point:

             

            U+0047  U+0065  U+006C  U+006C  U+006F.

             

            只是一組code point。事實(shí)上,也就是數(shù)字。到目前為止,我們還沒(méi)有提到過(guò)如何在內(nèi)存中存儲(chǔ)它們,或是在email中如何表示它們。

             

            Encodings

             

            這就是encodings (編碼)發(fā)揮作用的地方了。

             

            關(guān)于Unicode編碼的最早的主意是這樣的,嘿伙計(jì),咱們把這些數(shù)字每個(gè)存成2字節(jié)吧。(這個(gè)主意也正是2字節(jié)神話的淵源)于是,我們的Helllo就變成了下面這樣:

             

            00 48 00 65 00 6C 00 6C 00 6F

             

            對(duì)嗎?別著急!為什么不能是下面這樣呢:

             

            48 00 65 00 6C 00 6C 00 6F 00

             

            好吧,從技術(shù)上說(shuō),這樣也可以,我確實(shí)這么認(rèn)為,而事實(shí)上,由于早期的實(shí)現(xiàn)者們?cè)谒麄円鎯?chǔ)Unicode code point的時(shí)候,希望依據(jù)特定的CPU架構(gòu)選擇是使用大端(high-endian)還是小端(low-endian)模式,這樣使得CPU處理速度得 以最佳化。于是,看哪,很快的,就出現(xiàn)了兩種不同的存儲(chǔ)Unicode的方式。于是人們不得不創(chuàng)造一個(gè)離奇的約定,在Unicode的字符串的最前面加上 一個(gè)FE FF標(biāo)識(shí)符。這個(gè)標(biāo)識(shí)符被稱為Unicode Byte Order Mark(Unicode字節(jié)序標(biāo)識(shí)符),并且,如果你反轉(zhuǎn)了你的高低字節(jié),那么這個(gè)標(biāo)識(shí)符就會(huì)變成FF FE,于是讀取你的字符串的人就可以知道他們必須要翻轉(zhuǎn)你的每一對(duì)高低字節(jié)。但是,喔,并不是每一個(gè)Unicode字符串都在開頭有這個(gè)字節(jié)序標(biāo)識(shí)符。

             

            一開始,這一切看起來(lái)似乎還是挺好的,但是逐漸的,程序員們開始抱怨,“看那一堆沒(méi)用的0!” ——由于這些美國(guó)程序員多數(shù)情況下只使用英文文本,也就意味著他們幾乎不會(huì)用到那些高于U+00FF的code point。尤其是他們多數(shù)還是加州的新自由主義嬉皮士,假若他們是德州人,那么他們多半不會(huì)在意這些多出來(lái)的字節(jié)。但是最終,這幫加州的苦孩子們終于無(wú) 法容忍字符串存儲(chǔ)空間被無(wú)端的增長(zhǎng)一倍,并且,由于有那么多的文檔已經(jīng)用各種ANSI和DBCS字符集存在了,誰(shuí)會(huì)把這些文檔都轉(zhuǎn)換到Unicode下來(lái) 呢?難道是我(法語(yǔ))來(lái)??jī)H僅因?yàn)檫@樣的想法,于是在好幾年的時(shí)間里,大多數(shù)人都決定無(wú)視Unicode,這使得事情變得更糟。

             

            終于,一個(gè)天才的概念被發(fā)明出來(lái)了——UTF-8UTF-8在內(nèi)存中通過(guò)8bit的字節(jié)來(lái)保存U + magic number,定義了保存Unicode字符串的一整套系統(tǒng)。在UTF-8中,0-127之間的code point被保存在一個(gè)單字節(jié)中。只有那些大于等于128的code point,需要用到2,3以及多至6個(gè)字節(jié)來(lái)保存。

             

            clip_image008[14]

             

            這種做法獲得了一個(gè)非常不錯(cuò)的副作用——那就是UTF-8中的英文文本與ASCII中的英文文本可以完全的保持一致,于是美國(guó)人們都不會(huì)發(fā)現(xiàn)有什么事情變得不一樣了。只有這世界上其他地方的人們不得不跳過(guò)這個(gè)坑。舉例來(lái)說(shuō),Hello, 這個(gè)字符串由code point:U+0048 U+0065 U+006C U+006C U+006F組成,在存儲(chǔ)的時(shí)候,被保存為48 65 6C 6C 6F,這,恰恰正好與ASCII,ANSI,以及這顆星球上所有的OEM字符集中的表示都完全一樣。現(xiàn)在,如果你需要去使用方言字母,或者是希臘字母,或 者是克林貢語(yǔ)字母的話,那么你就不得不為每個(gè)code point使用多個(gè)字節(jié)去存儲(chǔ)了,不過(guò)美國(guó)人永遠(yuǎn)都不用在意這些了。(UTF-8還有一個(gè)非常漂亮的特性,以往的Unicode字符串想使用老式的以單個(gè) byte的0作為字符串的結(jié)尾并不至于切斷字符串的話需要一些處理代碼,而UTF-8則可以忽略之。)

             

            到目前為止,我已經(jīng)告訴了你Unicode 編碼的三種方法。最傳統(tǒng)的兩字節(jié)存儲(chǔ)方式被稱為UCS-2(因?yàn)橛?個(gè)字節(jié))或者UTF-16(因?yàn)橛?6個(gè)Bit),并且你還得自己弄清楚究竟這是一個(gè) 大端(High-endian)UCS-2還是一個(gè)小端(low-endian)UCS-2。你還可以采用全新的UTF-8標(biāo)準(zhǔn),如果你只使用英文文本, 它會(huì)讓你在碰到一個(gè)無(wú)腦程序時(shí),即便它完全無(wú)視了除ACSII之外的一切,你依然會(huì)過(guò)得很幸福!

             

            事實(shí)上還有其他一系列方法來(lái)編碼Unicode。 有一種編碼叫做UTF-7,它與UTF-8有很多相似之處,但是它假定所有字節(jié)的最高比特都是0。因?yàn)檫@個(gè)原因,如果你要把Unicode字符串傳遞給一 個(gè)嚴(yán)格認(rèn)為7bit就足夠用的警方郵件系統(tǒng),那么感謝UTF-7吧,它能使你免于痛苦。還有種UCS-4編碼,它使用4個(gè)字節(jié)存儲(chǔ)一個(gè)code point,它有個(gè)不錯(cuò)的特性,每個(gè)code point都是等長(zhǎng)的,但是麻煩在于,它是在浪費(fèi)了太多的內(nèi)存,以至于即便是得克薩斯人也不敢使用它。

             

            事實(shí)上你正在使用Unicode code point所表示的柏拉圖式的理想的字母來(lái)考慮這些問(wèn)題,這些Unicode code point同樣也可以使用任何一種舊的學(xué)院派的編碼方案來(lái)表示。舉例而言,你同樣可以用ASCII或古希臘OEM編碼或希伯來(lái)ANSI編碼,乃至迄今為止 已被發(fā)明的數(shù)百種編碼,來(lái)表示一個(gè)Unicode編碼的字符串Hello(U+0048 U+0065 U+006C U+006C U+006F)。但是這些做法有一個(gè)陷阱,那就是某些字母可能不能正常顯示!如果你想要將某個(gè)Unicode code point在某種編碼中表示,而該編碼中又沒(méi)有能對(duì)應(yīng)上該code point的,你常常會(huì)得到一些小的問(wèn)號(hào):?或者,如果你的人品不錯(cuò),你會(huì)得到一個(gè)?

             

            存在數(shù)以百計(jì)的傳統(tǒng)編碼,它們都只能正確表示Unicode code point的某些子集,而對(duì)那些處理不了的code point,則用問(wèn)號(hào)來(lái)處理。有一些流行的英文編碼,諸如Windows-1252(這是Windows 9x中的西歐語(yǔ)言標(biāo)準(zhǔn)),以及ISO-8859-1aka Latin-1(同樣在任何一個(gè)西歐語(yǔ)言中都會(huì)有用的),如果你想要用上面這些編碼來(lái)處理俄文或者是希伯來(lái)字母,那么你會(huì)得到大量的問(wèn)號(hào)。與之對(duì)應(yīng)的,UTF7,8,16以及32等編碼則有非常棒的特性,它們可以正確表示任何Unicode code point

             

            關(guān)于編碼的最重要的事實(shí)

             

            如果你把我之前所解釋的所有一切都忘光了,請(qǐng)你至少記住一個(gè)最最最重要的事實(shí)。如果你有一個(gè)字符串,而不知道它的編碼,那么這個(gè)字符串是毫無(wú)意義的。你再也不能把腦袋埋到沙子里,然后假裝“普通”文本就是ASCII。

             

            這世界上就沒(méi)有普通文本這回事。

             

            如果你有一個(gè)字符串,不管是在內(nèi)存里,還是在文件里,還是在一封email中,你必須知道它的確切的編碼,否則你不可能做到正確的解釋它,或是向用戶顯示。

             

            幾乎所有的像是“我的網(wǎng)站看起來(lái)像是在胡言亂語(yǔ)”,或者是“如果我在郵件里用了方言字母,那么她就無(wú)法閱讀”的傻逼問(wèn)題,幾乎都是由于某些天真犯二的程序員沒(méi)能理解下面這個(gè)事實(shí):如果你不告訴我一個(gè)特定的字符串用的是哪一種編碼,UTF-8或是ASCII或是ISO 8859-1(Latin 1)或是Windows 1252(西歐),那么我就不可能正確的顯示這個(gè)字符串,甚至不可能知道哪里是它的結(jié)尾。有上百種編碼格式的存在,并且一旦出現(xiàn)大于127的code point,那么一切就全完了。

             

            一個(gè)字符串是如何編碼的,我們要如何維護(hù)這樣一個(gè)信息呢?好吧,關(guān)于這件事情,有一些標(biāo)準(zhǔn)做法。對(duì)于email消息,你最好在正文的頭部,加入這樣一行字符串:

             

            Content-Type: text/plain; charset=”UTF-8″

             

            對(duì)于網(wǎng)頁(yè)頁(yè)面,最早的想法是由web服務(wù)器返回一個(gè)類似的Content-Type,把這個(gè)信息放在與網(wǎng)頁(yè)內(nèi)容一同傳輸?shù)腍TTP報(bào)頭中,不是放在HTML頁(yè)面里,而是放在響應(yīng)報(bào)頭里,在HTML內(nèi)容之前被發(fā)送。

             

            但這種做法會(huì)導(dǎo)致問(wèn)題。想象一下你有一個(gè)巨大的web 服務(wù)器,上面跑著很多網(wǎng)站,并且有著由不同的人貢獻(xiàn)的數(shù)以百計(jì)的網(wǎng)頁(yè)。這些人創(chuàng)建網(wǎng)頁(yè)的時(shí)候,他們所使用的Microsoft FrontPage可能以任何它覺(jué)得合適的方式來(lái)選擇編碼進(jìn)行存儲(chǔ)。web服務(wù)器本身對(duì)此一無(wú)所知,它不可能知道每一個(gè)文件是以什么編碼格式寫的,所以它 也就無(wú)法為之發(fā)送Content-Type頭。

             

            如果你使用某種特殊的tag,把 HTML文件所使用的Content-Type直接寫到HTML文件里,就會(huì)讓后續(xù)的事情變得更加方便。當(dāng)然這種做法會(huì)讓某些純化論者感到抓狂…如果你不 知道這個(gè)HTML文件的編碼,你要如何去讀取它?!幸運(yùn)的是,幾乎所有的編碼對(duì)32到127之間的字符都是同樣對(duì)待的,于是,在需要使用任何詭異的字母之 前,你總是可以在HTML頁(yè)面中讀取到至少像下面這樣多的內(nèi)容:

             

            <html>

            <head>

            <meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″>

             

            但是需要注意的是,這個(gè)meta tag必須是<head>節(jié)中最先出現(xiàn)的東西。因?yàn)橹灰W(wǎng)頁(yè)瀏覽器見到這個(gè)tag,它就會(huì)停止解析這個(gè)頁(yè)面,并且使用你所指定的編碼開始重新解釋整個(gè)頁(yè)面。

             

            如果網(wǎng)頁(yè)瀏覽器即無(wú)法從http報(bào)頭也 無(wú)法從HTML的meta標(biāo)記中找到任何Content-Type信息,那么它們會(huì)如何對(duì)待這個(gè)網(wǎng)頁(yè)呢?事實(shí)上,Internet Explorer做了一些有趣的事情,它基于一種啟發(fā)式的方法去猜(依照典型編碼的典型文本中,各種不同的語(yǔ)言使其字節(jié)呈現(xiàn)不同的分布頻率的規(guī)律)。因?yàn)?各種舊的8bit代碼頁(yè)會(huì)嘗試把他們國(guó)家的字母放在128~255中不同的區(qū)間段里,同時(shí)又由于每一種人類語(yǔ)言對(duì)字母的使用都呈現(xiàn)不同的統(tǒng)計(jì)特征,所以上 述方案,有一定的概率是可以工作的。這做法是很怪異的,這使得那些天真無(wú)邪的網(wǎng)頁(yè)作者,在從來(lái)不知道每個(gè)HTML頁(yè)面都需要一個(gè)Content-Type 頭的情況下繼續(xù)寫網(wǎng)頁(yè),并且當(dāng)他們?cè)跒g覽器中查看時(shí),發(fā)現(xiàn)一切都是正常的。直到有一天,他們寫了點(diǎn)東西,與他們母語(yǔ)中的字母頻率分布不相符合,于是 Internet Explorer便認(rèn)為這是一段韓語(yǔ),然后,就這么繼續(xù)顯示出來(lái)……我相信,這證明了Postel法則中所說(shuō)的,“寬容的對(duì)待輸入,而保守的輸出”,坦白說(shuō)并不是一個(gè)好的工程原則。無(wú)論如何,當(dāng)這個(gè)網(wǎng)站的可憐的讀者,在面對(duì)這個(gè)被顯示成韓語(yǔ)(并且事實(shí)上是根本無(wú)法理解的韓語(yǔ))而事實(shí)上是保加利亞語(yǔ)的網(wǎng)頁(yè)時(shí),要怎么做呢?他使用View|Encoding菜單,并且依次嘗試每一個(gè)編碼的選項(xiàng)(至少有十?dāng)?shù)個(gè)東歐語(yǔ)言選項(xiàng)),直到一切變得正常。但是,事實(shí)上,多數(shù)人都不知道要這么做。

             

            clip_image009[13]

             

            我公司所發(fā)布的網(wǎng)站管理軟件CityDesk的最新版本中,我們決定內(nèi)部的一切都用UCS-2(2字節(jié))Unicode表示,這也是Visual Basic,COM以及Windows NT/2000/XP所使用的原生的字符串類型。

             

            C++代碼中,這意味著當(dāng)定義字符串時(shí),我們使用wchar_t(寬字符)來(lái)替代char,并且使用wcs系函數(shù)來(lái)替代str系函數(shù)(例如,使用wcscatwcslen而不是strcatstrlen)。要在C代碼中創(chuàng)建一個(gè)UCS-2的字符串,你只需要在字符串定義前增加一個(gè)L,如:L”Hello”

             

            當(dāng)CityDesk發(fā)布網(wǎng)頁(yè)時(shí),它將之轉(zhuǎn)換為已經(jīng)為網(wǎng)頁(yè)瀏覽器所支持多年的UTF-8編碼格式。這也是Joel on Software全部29種語(yǔ)言版本所使用的編碼,并且我從來(lái)沒(méi)有聽到過(guò)任何一個(gè)人抱怨說(shuō)在閱讀它的時(shí)候遇到麻煩。

             

            本文的篇幅有點(diǎn)長(zhǎng),并且我也不可能覆蓋關(guān)于Unicode和字符編碼的所有話題,我希望的是,如果你已經(jīng)閱讀到這里,你已經(jīng)知道了足夠多的知識(shí),我留給你的任務(wù),就是回去編寫程序,并且記得在對(duì)付疾病的時(shí)候使用抗生素,而不是水蛭和魔咒。

             

            還想知道更多?你現(xiàn)在閱讀的是Joel on Software,這里填滿了各種經(jīng)年累月積累下來(lái)的關(guān)于軟件開發(fā),管理軟件團(tuán)隊(duì),設(shè)計(jì)用戶界面,成功運(yùn)營(yíng)一家軟件公司,以及橡皮鴨的各種胡言亂語(yǔ)的文章。

             

            關(guān)于作者:我 是Joel Spolsky,F(xiàn)og Creek Software的共同創(chuàng)始人,F(xiàn)og Creek Software是一家紐約的公司,它證明了你可以在對(duì)待程序員們很好的同時(shí)創(chuàng)造出很高的利潤(rùn)。這里的程序員擁有私人的辦公室,免費(fèi)的午餐,以及每周40 個(gè)小時(shí)的工作時(shí)間。公司的客戶只為他們滿意的軟件付費(fèi)。我們創(chuàng)造了一個(gè)更先進(jìn)的bug跟蹤軟件FogBugz,以及軟件開發(fā)工具。Kiln,一個(gè)分布式的源代碼管理系統(tǒng),如果你迷戀svn,它會(huì)讓你非常驚喜,以及Fog Creek Copilot,可以讓訪問(wèn)遠(yuǎn)程桌面變得更加容易。我同時(shí)也是Stack Overflow的共同創(chuàng)始人。

             

             

            譯注:本文對(duì)Unicode和編碼的解釋非常棒,將編碼和字符集的來(lái)龍去脈解釋得深入淺出,是每個(gè)合格的程序員所必知必會(huì)的基礎(chǔ)知識(shí),本人在閱讀《Game Engine Architecture》一書時(shí),了解到此文,遂生出翻譯的興趣,翻譯的過(guò)程中確又發(fā)現(xiàn)再次理清了若干此前未曾真正理解的概念,只因英文水平和精力有限,難免有所錯(cuò)漏,如有指正,不吝感激。

            posted @ 2013-06-22 15:47 多彩人生 閱讀(2995) | 評(píng)論 (2)編輯 收藏

            gregorian::greg_month::get_month_map_ptr()

            Error: undefined reference to 'boost::gregorian::greg_month::get_month_map_ptr() '

            g++ -L/usr/lib -lboost_date_time

             

            note: should install boost_date_time in Ubuntu.

            posted @ 2013-06-15 14:24 多彩人生 閱讀(841) | 評(píng)論 (0)編輯 收藏

            defy

            http://www.itopdog.cn/android/defy-root-rom.html

            posted @ 2013-06-15 00:20 多彩人生 閱讀(157) | 評(píng)論 (0)編輯 收藏

            正確使用stl map的erase方法

            http://www.cnblogs.com/kex1n/archive/2011/12/06/2278505.html

            先聲明:下面的文章是針對(duì)windows的用法,因?yàn)閟td::map的erase函數(shù)的windows的實(shí)現(xiàn)版本是返回一個(gè)std::map的迭代器,但是STL標(biāo)準(zhǔn)里面的該函數(shù)的返回值確是:

            map.erase有3個(gè)重載:
            void erase ( iterator position );
            size_type erase ( const key_type& x );
            void erase ( iterator first, iterator last );

            所以下面的代碼中的最后一個(gè)例子僅僅可以在windows下的map下運(yùn)行。

             

            STL的map表里有一個(gè)erase方法用來(lái)從一個(gè)map中刪除掉指令的節(jié)點(diǎn)
            eg1:

            map<string,string> mapTest;
            typedef map<string,string>::iterator ITER;

            ITER iter=mapTest.find(key);
            mapTest.erase(iter);

             像上面這樣只是刪除單個(gè)節(jié)點(diǎn),map的形為不會(huì)出現(xiàn)任務(wù)問(wèn)題,
            但是當(dāng)在一個(gè)循環(huán)里用的時(shí)候,往往會(huì)被誤用,那是因?yàn)槭褂谜邲](méi)有正確理解iterator的概念.
            像下面這樣的一個(gè)例子就是錯(cuò)誤的寫法,
            eg2:

            for(ITER iter=mapTest.begin();iter!=mapTest.end();++iter)
            {
            cout<<iter->first<<":"<<iter->second<<endl;
            mapTest.erase(iter);
            }

            這是一種錯(cuò)誤的寫法,會(huì)導(dǎo)致程序行為不可知.究其原因是map 是關(guān)聯(lián)容器,對(duì)于關(guān)聯(lián)容器來(lái)說(shuō),如果某一個(gè)元素已經(jīng)被刪除,那么其對(duì)應(yīng)的迭代器就失效了,不應(yīng)該再被使用;否則會(huì)導(dǎo)致程序無(wú)定義的行為。
            可以用以下方法解決這問(wèn)題:
            正確的寫法
            1.使用刪除之前的迭代器定位下一個(gè)元素。STL建議的使用方式

            for(ITER iter=mapTest.begin();iter!=mapTest.end();)
            {
            cout<<iter->first<<":"<<iter->second<<endl;
            mapTest.erase(iter++);
            }

            2. erase() 成員函數(shù)返回下一個(gè)元素的迭代器

            for(ITER iter=mapTest.begin();iter!=mapTest.end();)
            {
            cout<<iter->first<<":"<<iter->second<<endl;
            iter=mapTest.erase(iter);
            }

            posted @ 2013-05-30 16:51 多彩人生 閱讀(302) | 評(píng)論 (0)編輯 收藏

            cocos2d-x

            http://www.cnblogs.com/graphicsme/archive/2012/11/06/2756914.html

            http://www.lvcoffee.info/archives/date/2013/03
            http://www.cnblogs.com/klobohyz/archive/2012/08/01/2617794.html

            posted @ 2013-05-28 22:15 多彩人生 閱讀(222) | 評(píng)論 (0)編輯 收藏

            mangos

            http://www.cnblogs.com/ychellboy/archive/2012/02/10/2345879.html
            http://blog.csdn.net/lixinso/article/details/4694921

            posted @ 2013-05-24 17:04 多彩人生 閱讀(284) | 評(píng)論 (0)編輯 收藏

            Vim 配置詳解

            http://www.cnblogs.com/witcxc/archive/2011/12/28/2304704.html
            http://www.cnblogs.com/ma6174/archive/2011/12/10/2283393.html
            http://www.thegeekstuff.com/2009/01/tutorial-make-vim-as-your-cc-ide-using-cvim-plugin/

            posted @ 2013-05-24 08:57 多彩人生 閱讀(195) | 評(píng)論 (0)編輯 收藏

            lua fPIC error

            安裝lua

            tar zxvf lua-5.1.4.tar.gz

            cd lua-5.1.4

            如果你的服務(wù)器是64位的,這時(shí)要調(diào)整一下Makefile:vi src/Makefile,在CFLAGS里加上-fPIC,否則會(huì)出錯(cuò):

            /usr/bin/ld: /usr/local/lib/liblua.a(lapi.o):

            relocation R_X86_64_32 against `luaO_nilobject_' can not be used when making a shared object;

            recompile with -fPIC

            /usr/local/lib/liblua.a: could not read symbols: Bad value

            接下來(lái)不用執(zhí)行常見的configure,直接make:

            make linux

            make install

            posted @ 2013-04-23 14:50 多彩人生 閱讀(1621) | 評(píng)論 (0)編輯 收藏

            pg_ctl

            pg_ctl
            名稱
            pg_ctl -- 啟動(dòng)、停止、重啟 PostgreSQL
            語(yǔ)法
            pg_ctl start [-w] [-s] [-D datadir] [-l filename] [-o options] [-p path]
            pg_ctl stop [-W] [-s] [-D datadir] [-m s[mart] | f[ast] | i[mmediate] ]
            pg_ctl restart [-w] [-s] [-D datadir] [-m s[mart] | f[ast] | i[mmediate] ] [-o options]
            pg_ctl reload [-s] [-D datadir]
            pg_ctl status [-D datadir]
            pg_ctl kill [signal_name] [process_id]
            pg_ctl register [-N servicename] [-U username] [-P password] [-D datadir] [-w] [-o options]
            pg_ctl unregister [-N servicename]

            描述
            pg_ctl 用于啟動(dòng)、停止、重啟 PostgreSQL 后端服務(wù)器(postgres),或者顯示一個(gè)運(yùn)行著的服務(wù)器的狀態(tài)。盡管可以手動(dòng)啟動(dòng)服務(wù)器,但是 pg_ctl 封裝了重新定向日志輸出,與終端和進(jìn)程組合理分離,以及另外提供了一個(gè)選項(xiàng)用于有控制的關(guān)閉。

            在 start 模式里會(huì)啟動(dòng)一個(gè)新的服務(wù)器。服務(wù)器是在后臺(tái)啟動(dòng)的,標(biāo)準(zhǔn)輸入被附著到了 /dev/null 上。如果使用了 -l ,那么標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤將被定向到一個(gè)日志文件,要么就是重定向到 pg_ctl 的標(biāo)準(zhǔn)輸出(而不是標(biāo)準(zhǔn)錯(cuò)誤)。如果沒(méi)有選定日志文件,pg_ctl 的標(biāo)準(zhǔn)輸出應(yīng)該重定向到一個(gè)文件或者用管道輸出到類似 rotatelogs 這樣的日志滾動(dòng)程序,否則,postgres 將把它的輸出寫到控制終端(在后臺(tái))并且將不會(huì)脫離 shell 的進(jìn)程組。

            在 stop 模式下,那個(gè)正在特定數(shù)據(jù)目錄運(yùn)行的服務(wù)器將被關(guān)閉。你可以用 -m 選項(xiàng)選擇三種不同的關(guān)閉模式:"Smart"模式等待所有客戶端中斷連接,這是缺省。"Fast"模式并不等待客戶端中斷連接,所有活躍事務(wù)都被回滾并且客戶端都被強(qiáng)制斷開。"Immediate"模式將在沒(méi)有干凈關(guān)閉的情況下強(qiáng)行退出。這么做將導(dǎo)致在重新啟動(dòng)的時(shí)候的恢復(fù)。

            restart 實(shí)際上是先執(zhí)行一個(gè)停止,然后緊跟一個(gè)啟動(dòng)。它允許變換 postgres 的命令行選項(xiàng)。

            reload 模式簡(jiǎn)單地給 postgres 發(fā)送一個(gè) SIGHUP 信號(hào),導(dǎo)致它重新讀取配置文件(postgresql.conf, pg_hba.conf 等),這樣就允許修改配置文件選項(xiàng)而不用重啟系統(tǒng)即可生效。

            status 模式監(jiān)查一個(gè)服務(wù)器是否在指定的數(shù)據(jù)目錄運(yùn)行,如果是,那么顯示其 PID 和調(diào)用它的命令行選項(xiàng)。

            kill 模式允許你給一個(gè)指定的進(jìn)程發(fā)送信號(hào)。這個(gè)功能對(duì) Microsoft Windows 特別有用,因?yàn)樗鼪](méi)有 kill 命令。使用 --help 查看支持的信號(hào)名字列表。

            register 模式允許你在 Microsoft Windows 上注冊(cè)一個(gè)系統(tǒng)服務(wù)。

            unregister 模式允許你在 Microsoft Windows 上刪除先前用 register 命令注冊(cè)的系統(tǒng)服務(wù)。

            選項(xiàng)
            -D datadir
            聲明該數(shù)據(jù)庫(kù)的文件系統(tǒng)位置。如果忽略則使用 PGDATA 環(huán)境變量。

            -l filename
            把服務(wù)器日志輸出附加在 filename 文件上。如果該文件不存在則創(chuàng)建它。umask 設(shè)置為 077 ,因此缺省時(shí)是不允許從其它用戶向日志文件訪問(wèn)的。

            -m mode
            聲明關(guān)閉模式。mode 可以是 smart, fast, immediate 之一,或者是這三個(gè)的首字母之一。

            -o options
            聲明要直接傳遞給 postgres 的選項(xiàng)。

            參數(shù)通常都用單或者雙引號(hào)包圍以保證它們作為一個(gè)整體傳遞。

            -p path
            聲明 postgres 可執(zhí)行文件的位置。缺省位于 pg_ctl 自身所在目錄,如果沒(méi)找到則使用硬編碼的安裝目錄。除非你想干點(diǎn)什么特別的事情,并且想得到類似沒(méi)有找到 postgres 這樣的錯(cuò)誤,否則必須使用這個(gè)選項(xiàng)。

            -s
            只打印錯(cuò)誤,而不打印提示性信息。

            -w
            等待啟動(dòng)或者關(guān)閉的完成(60 秒超時(shí)),這個(gè)參數(shù)是關(guān)閉時(shí)的缺省值。成功的關(guān)閉是以刪除 PID 文件為標(biāo)志的。對(duì)于啟動(dòng)而言,一次成功的 psql -l 就標(biāo)志著成功。pg_ctl 將企圖使用對(duì) psql 合適的端口,如果存在 PGPORT 環(huán)境變量,那么將用它。否則,它將查找在 postgresql.conf 文件里是否設(shè)置了一個(gè)端口。如果都沒(méi)有,它將使用 PostgreSQL 編譯時(shí)的缺省端口(缺省 5432)。在等待的時(shí)候,pg_ctl 將根據(jù)啟動(dòng)或者關(guān)閉的成功狀況返回一個(gè)準(zhǔn)確的退出代碼。

            -W
            不等待啟動(dòng)或者停止的完成。這是啟動(dòng)和重啟的缺省。

            Windows 選項(xiàng)
            -N servicename
            要注冊(cè)的系統(tǒng)服務(wù)的名字。這個(gè)名字將用于服務(wù)名和顯示名。

            -P password
            用戶啟動(dòng)服務(wù)的口令

            -U username
            用于啟動(dòng)服務(wù)的用戶的用戶名。對(duì)于域用戶,使用 DOMAIN\username 格式。

            環(huán)境變量
            PGDATA
            缺省數(shù)據(jù)目錄位置

            PGPORT
            psql 的缺省端口(由 -w 選項(xiàng)使用)。

            其它的環(huán)境變量請(qǐng)參閱 postgres

            文件
            postmaster.pid
            這個(gè)文件存在于數(shù)據(jù)目錄中是為了幫助 pg_ctl 判斷服務(wù)器當(dāng)前是否在運(yùn)行。

            postmaster.opts.default
            如果這個(gè)文件存在于數(shù)據(jù)目錄,pg_ctl (在 start 模式下)將把文件地內(nèi)容當(dāng)作傳遞給 postgres 命令的選項(xiàng)傳遞過(guò)去,除非被 -o 選項(xiàng)覆蓋。

            postmaster.opts
            如果這個(gè)文件存在于數(shù)據(jù)目錄,pg_ctl (在 start 模式下)將把文件地內(nèi)容當(dāng)作傳遞給 postgres 命令的選項(xiàng)傳遞過(guò)去,除非被 -o 選項(xiàng)覆蓋。這個(gè)文件的內(nèi)容也會(huì)在 status 模式里顯示出來(lái)。

            postgresql.conf
            這個(gè)文件在數(shù)據(jù)目錄中,會(huì)分析它以查找和 psql 一起用的合適的端口(在 start 模式里給出 -w 的時(shí)候)。

            注意
            等待完全啟動(dòng)還不是一個(gè)定義得很完整的操作,如果訪問(wèn)控制設(shè)置為本地客戶端在沒(méi)有手工交互的情況下不能訪問(wèn)的話還可能會(huì)失效(比如口令認(rèn)證)。

            例子
            啟動(dòng)服務(wù)器
            啟動(dòng)服務(wù)器:

            $ pg_ctl start啟動(dòng)服務(wù)器的一個(gè)例子,等到服務(wù)器啟動(dòng)了才退出:

            $ pg_ctl -w start服務(wù)器使用 5433 端口,而且不帶 fsync 運(yùn)行,使用:

            $ pg_ctl -o "-F -p 5433" start停止服務(wù)器
            $ pg_ctl stop使用 -m 選項(xiàng)停止服務(wù)器允許用戶控制如何關(guān)閉后端。

            重啟服務(wù)器
            這個(gè)命令幾乎等于先停止服務(wù)器然后再啟動(dòng)它,只不過(guò) pg_ctl 保存并重新使用上一次運(yùn)行服務(wù)器的命令行參數(shù)。重啟服務(wù)器的最簡(jiǎn)單的方法是:

            $ pg_ctl restart重啟服務(wù)器,等待其停止和重啟:

            $ pg_ctl -w restart使用 5433 端口重啟并且重啟后關(guān)閉 fsync :

            $ pg_ctl -o "-F -p 5433" restart顯示服務(wù)器狀態(tài)
            下面是來(lái)自 pg_ctl 的狀態(tài)輸出的例子:

            $ pg_ctl statuspg_ctl: server is running (pid: 13718)Command line was:/usr/local/pgsql/bin/postgres '-D' '/usr/local/pgsql/data' '-p' '5433' '-B' '128'這就是在 restart 模式中被調(diào)用的命令行。

            又見
            postgres

            pg_resetxlog
            名稱
            pg_resetxlog -- 重置一個(gè)數(shù)據(jù)庫(kù)集群的預(yù)寫日志以及其它控制內(nèi)容
            語(yǔ)法
            pg_resetxlog [-f] [-n] [-ooid ] [-x xid ] [-e xid_epoch ] [-m mxid ] [-O mxoff ] [-l timelineid, fileid, seg ] datadir

            描述
            pg_resetxlog 清理預(yù)寫日志(WAL)并且可以有選擇地重置其它一些存儲(chǔ)在 pg_control 文件中的控制信息。有時(shí)候,如果這些文件崩潰了,就需要這個(gè)功能。一定只把它用作最后的方法,就是說(shuō)只有因?yàn)檫@樣的崩潰導(dǎo)致服務(wù)器無(wú)法啟動(dòng)的時(shí)候才使用。

            運(yùn)行這個(gè)命令之后,可能就可以啟動(dòng)服務(wù)器了,但是,一定要記住數(shù)據(jù)庫(kù)可能因?yàn)椴糠痔峤坏氖聞?wù)而含有不完整的數(shù)據(jù)。你應(yīng)該馬上轉(zhuǎn)儲(chǔ)數(shù)據(jù),運(yùn)行 initdb ,然后重新加載。在重新加載之后,檢查不完整的部分然后根據(jù)需要進(jìn)行修復(fù)。

            這個(gè)命令只能由安裝服務(wù)器的用戶運(yùn)行,因?yàn)樗枰獙?duì)數(shù)據(jù)目錄的讀寫權(quán)限。出于安全考慮,pg_resetxlog 不使用環(huán)境變量 PGDATA ,你必須在命令行上聲明數(shù)據(jù)目錄。

            如果 pg_resetxlog 抱怨說(shuō)它無(wú)法判斷用于 pg_control 的有效數(shù)據(jù),那么你可以強(qiáng)制它繼續(xù)處理,方法是聲明 -f(強(qiáng)制)開關(guān)。在這種情況下,那些丟失了的數(shù)據(jù)將用模糊的近似數(shù)值代替。大多數(shù)字段都可以匹配上,但是下一個(gè) OID 、下一個(gè)事務(wù) ID 、下一個(gè)事務(wù) ID 的 epoch(時(shí)間點(diǎn))、下一個(gè)多事務(wù) ID(兩階段提交的東西)、下一個(gè)多事務(wù)偏移量、WAL 開始地址、數(shù)據(jù)庫(kù)區(qū)域字段可能需要手工幫助,前面六個(gè)可以用下面討論的開關(guān)設(shè)置。pg_resetxlog 自己的環(huán)境是猜測(cè)區(qū)域字段的來(lái)源;看看 LANG 等東西,它們應(yīng)該和 initdb 運(yùn)行的環(huán)境相匹配。如果你不能判斷所有這些字段的正確數(shù)值,那么 -f 仍然可以使用,但是這樣恢復(fù)過(guò)來(lái)的數(shù)據(jù)庫(kù)正確性更值得懷疑:立即轉(zhuǎn)儲(chǔ)和重新加載是必須的。在轉(zhuǎn)儲(chǔ)之前不要執(zhí)行任何修改數(shù)據(jù)的操作,因?yàn)槿魏芜@樣的動(dòng)作都可能把事情搞得更糟糕。

            -o, -x, -e, -m, -O, -l 開關(guān)允許手工設(shè)置下一個(gè) OID 、下一個(gè)事務(wù) ID 、下一個(gè)事務(wù) ID epoch 、下一個(gè)多事務(wù) ID 、下一個(gè)多事務(wù)偏移量、WAL 起始位置的數(shù)值。只有在 pg_resetxlog 無(wú)法通過(guò)讀取 pg_control 判斷合適的數(shù)值的時(shí)候才需要它。安全的數(shù)值可以用下面的方法判斷:

            對(duì)于下一個(gè)事務(wù) ID(-x)而言,一個(gè)安全的數(shù)值是看看數(shù)據(jù)目錄里的 pg_clog 里數(shù)值最大的文件名,然后加一,然后再乘上 1048576 。請(qǐng)注意那些文件名是十六進(jìn)制的。通常也以十六進(jìn)制的形式聲明開關(guān)值是最簡(jiǎn)單的。比如,如果 0011 是 pg_clog 里最大的記錄,-x 0x1200000 就可以了(后面的五個(gè)零提供了合適的乘積)。

            下一個(gè)多事務(wù) ID(-m)的安全值可以通過(guò)查看數(shù)據(jù)目錄里 pg_multixact/offsets 子目錄里面的數(shù)字最大的文件名,加一,然后乘以 65536 得到。和上面一樣,文件名是十六進(jìn)制的,因此最簡(jiǎn)單的方法是給開關(guān)聲明一個(gè)十六進(jìn)制的開關(guān)值,然后在結(jié)尾加四個(gè)零。

            下一個(gè)多事務(wù)偏移量(-O)的安全值可以通過(guò)檢查數(shù)據(jù)目錄里 pg_multixact/members 子目錄下的數(shù)字最大的文件名,加一,然后乘以 65536 得到。和上面一樣,文件名是十六進(jìn)制的,因此最簡(jiǎn)單的方法是給開關(guān)聲明一個(gè)十六進(jìn)制的開關(guān)值,然后在結(jié)尾加四個(gè)零。

            WAL 的起始位置(-l)應(yīng)該比目前存在于數(shù)據(jù)目錄 pg_xlog 里面的任何文件號(hào)都大。它的文件名也是十六進(jìn)制的,并且有三部分。第一部分是"時(shí)間線 ID",通常應(yīng)該保持相同。第三部分不要選擇大于 255(0xFF);應(yīng)該是在達(dá)到 255 的時(shí)候給第二部分增一然后重置第三部分為 0 。比如,如果 00000001000000320000004A 是 pg_xlog 里最大的條目,那么 -l 0x1,0x32,0x4B 就可以了;但如果最大的條目是 000000010000003A000000FF ,那么選擇 -l 0x1,0x3B,0x0 或更多。

            沒(méi)有很容易的辦法來(lái)判斷比數(shù)據(jù)庫(kù)中最大的 OID 大一號(hào)的下一個(gè) OID ,不過(guò)很走運(yùn)的是獲取正確的下一個(gè) OID 并非非常關(guān)鍵的事情。

            除了由 pg_resetxlog 設(shè)定的字段外,事務(wù) ID epoch 實(shí)際上并未存儲(chǔ)在數(shù)據(jù)庫(kù)里的任何地方。所以只要是涉及到數(shù)據(jù)庫(kù)自身的任何數(shù)值都有效。你可能需要調(diào)整這個(gè)值以確保諸如 Slony-I 之類的備份系統(tǒng)能夠正常工作。如果是這樣的話,應(yīng)當(dāng)從下游已復(fù)制的數(shù)據(jù)庫(kù)中獲取恰當(dāng)?shù)闹怠?br />
            -n(無(wú)操作)開關(guān)指示 pg_resetxlog 打印從 pg_control 重新構(gòu)造的數(shù)值然后不修改任何值就退出。這主要是一個(gè)調(diào)試工具,但是在 pg_resetxlog 真正處理前進(jìn)行的整潔性檢查的時(shí)候可能會(huì)有用。

            注意
            在服務(wù)器運(yùn)行的時(shí)候一定不要運(yùn)行這個(gè)命令。如果發(fā)現(xiàn)在數(shù)據(jù)文件目錄里有鎖文件,那么 pg_resetxlog 將拒絕啟動(dòng)。如果服務(wù)器崩潰,那么可能會(huì)剩下一個(gè)鎖文件;如果這樣,你可以刪除該鎖文件以便允許 pg_resetxlog 運(yùn)行。但是在你這么做之前,一定要確保沒(méi)有任何后端服務(wù)器進(jìn)程仍在運(yùn)行。

            postgres
            名稱
            postgres -- PostgreSQL 數(shù)據(jù)庫(kù)服務(wù)器
            語(yǔ)法
            postgres [option...]

            描述
            postgres 是 PostgreSQL 數(shù)據(jù)庫(kù)服務(wù)器。客戶端應(yīng)用程序?yàn)榱嗽L問(wèn)數(shù)據(jù)庫(kù),將通過(guò) TCP Socket 或 Unix domain socket 連接到一個(gè)運(yùn)行中的 postgres 進(jìn)程。然后該 postgres 實(shí)例將啟動(dòng)(fork)一個(gè)新的、獨(dú)立的服務(wù)器進(jìn)程來(lái)處理這個(gè)連接。

            一個(gè) postgres 總是管理來(lái)自同一個(gè)數(shù)據(jù)庫(kù)集群的數(shù)據(jù)。一個(gè)數(shù)據(jù)庫(kù)集群是一組在同一個(gè)文件系統(tǒng)位置("數(shù)據(jù)區(qū)")存放數(shù)據(jù)的數(shù)據(jù)庫(kù)。一個(gè)系統(tǒng)上可以同時(shí)運(yùn)行多個(gè) postgres 進(jìn)程,只要他們使用不同的數(shù)據(jù)區(qū)和不同的端口號(hào)(見下文)。postgres 啟動(dòng)時(shí)需要知道數(shù)據(jù)區(qū)的位置,該位置必須通過(guò) -D 選項(xiàng)或 PGDATA 環(huán)境變量指定。通常,-D 或 PGDATA 都直接指向由 initdb 創(chuàng)建的集群目錄。其他可能的文件布局在節(jié)17.2里面有討論。

            缺省時(shí) postgres 在前臺(tái)啟動(dòng)并將日志信息輸出到標(biāo)準(zhǔn)錯(cuò)誤。但在實(shí)際應(yīng)用中,postgres 應(yīng)當(dāng)作為后臺(tái)進(jìn)程啟動(dòng),而且多數(shù)是在系統(tǒng)啟動(dòng)時(shí)自動(dòng)啟動(dòng)。

            postgres 還能以單用戶模式運(yùn)行。這種用法的主要用于 initdb 的初始化過(guò)程中。有時(shí)候它也被用于調(diào)試災(zāi)難性恢復(fù)。不過(guò),單用戶模式運(yùn)行的服務(wù)器并不適合于調(diào)試,因?yàn)闆](méi)有實(shí)際的進(jìn)程間通訊和鎖動(dòng)作發(fā)生。當(dāng)從 shell 上以單用戶模式調(diào)用時(shí),用戶可以輸入查詢,然后結(jié)果會(huì)在屏幕上以一種更適合開發(fā)者閱讀(不適合普通用戶)的格式顯示出來(lái)。在單用戶模式下,將把會(huì)話用戶 ID 設(shè)為 1 并賦予超級(jí)用戶權(quán)限。該用戶不必實(shí)際存在,因此單用戶模式運(yùn)行的服務(wù)器可以用于對(duì)某些意外損壞的系統(tǒng)表進(jìn)行手工恢復(fù)。

            選項(xiàng)
            postgres 接受下列命令行參數(shù)。關(guān)于這些選項(xiàng)的更詳細(xì)討論請(qǐng)參考章17。你也可以通過(guò)設(shè)置一個(gè)配置文件來(lái)減少敲擊這些選項(xiàng)。有些(安全的)選項(xiàng)還可以從連接過(guò)來(lái)的客戶端設(shè)置,以一種應(yīng)用無(wú)關(guān)的方法僅對(duì)該會(huì)話生效。比如,如果設(shè)置了 PGOPTIONS 環(huán)境變量,那么基于 libpq 的客戶端就都把那個(gè)字符串傳遞給服務(wù)器,并被服務(wù)器解釋成 postgres 命令行選項(xiàng)。

            通用用途
            -A 0|1
            打開運(yùn)行時(shí)斷言檢查,是檢測(cè)編程錯(cuò)誤的調(diào)試幫助。只有在編譯 PostgreSQL 時(shí)打開了它,你才能使用它。如果編譯時(shí)打開了,缺省是打開。

            -B nbuffers
            為服務(wù)器進(jìn)程分配和管理的共享內(nèi)存緩沖區(qū)數(shù)量。這個(gè)參數(shù)的缺省值是 initdb 自動(dòng)選擇的;參考節(jié)17.4.1獲取更多信息。

            -c name=value
            設(shè)置一個(gè)命名的運(yùn)行時(shí)參數(shù)。PostgreSQL 支持的配置參數(shù)在章17里描述。大多數(shù)其它命令行選項(xiàng)實(shí)際上都是這樣的參數(shù)賦值的短形式。-c 可以出現(xiàn)多次從而設(shè)置多個(gè)參數(shù)。

            -d debug-level
            設(shè)置調(diào)試級(jí)別。數(shù)值越高,寫到服務(wù)器日志的調(diào)試輸出越多。取值范圍是 1 到 5 。還可以針對(duì)某次單獨(dú)的會(huì)話使用 -d 0 來(lái)防止從父 postgres 進(jìn)程繼承日志級(jí)別。

            -D datadir
            聲明數(shù)據(jù)目錄或者配置文件的文件系統(tǒng)路徑。細(xì)節(jié)詳見節(jié)17.2。

            -e
            把缺省日期風(fēng)格設(shè)置為"European",也就是說(shuō)用 DMY 規(guī)則解釋日期輸入,并且在一些日期輸出格式里日子在月份前面打印。參閱節(jié)8.5獲取更多細(xì)節(jié)。

            -F
            關(guān)閉 fsync 調(diào)用以提高性能,但是要冒系統(tǒng)崩潰時(shí)數(shù)據(jù)毀壞的風(fēng)險(xiǎn)。聲明這個(gè)選項(xiàng)等效關(guān)閉了 fsync 參數(shù)。在使用之前閱讀詳細(xì)文檔!

            -h hostname
            指定 postgres 偵聽來(lái)自前端應(yīng)用 TCP/IP 連接的 IP 主機(jī)名或地址。數(shù)值也可以是一個(gè)用空格分隔的地址列表,或者 * 表示監(jiān)聽所有可用的地址。空值表示不監(jiān)聽任何 IP 地址,而只使用 Unix 域套接字與客戶端通信。缺省只監(jiān)聽 localhost 。聲明這個(gè)選項(xiàng)等效于設(shè)置 listen_addresses 配置參數(shù)。

            -i
            這個(gè)選項(xiàng)允許遠(yuǎn)程客戶通過(guò) TCP/IP(網(wǎng)際域套接字)與服務(wù)器通訊。沒(méi)有這個(gè)選項(xiàng),服務(wù)器將只接受本地連接。這個(gè)選項(xiàng)等效于在 postgresql.conf 中或者通過(guò) -h 選項(xiàng)將 listen_addresses 設(shè)為 *

            這個(gè)選項(xiàng)已經(jīng)廢棄了,因?yàn)樗荒軐?shí)現(xiàn) listen_addresses 的所有功能。所以最好直接設(shè)置 listen_addresses

            -k directory
            指定 postgres 偵聽來(lái)自前端應(yīng)用連接的 Unix 域套接字的目錄。缺省通常是 /tmp ,但是可以在編譯的時(shí)候修改。

            -l
            這個(gè)選項(xiàng)使用 SSL 進(jìn)行的安全通訊。要使用這個(gè)選項(xiàng),編譯 PostgreSQL 時(shí)你必須打開了 SSL 支持。有關(guān)使用 SSL 的信息,請(qǐng)參考節(jié)16.7。

            -N max-connections
            設(shè)置最多允許同時(shí)連接多少個(gè)客戶端(也就是最多同時(shí)運(yùn)行多少個(gè)服務(wù)器進(jìn)程)。缺省值為 32 ,不過(guò)該值最大可以設(shè)置為系統(tǒng)所能承受的極限。請(qǐng)注意 -B 的值要求至少兩倍于 -N 的值。參閱節(jié)16.4獲取有關(guān)大量客戶的系統(tǒng)資源需求。聲明這個(gè)選項(xiàng)等效于聲明 max_connections 配置參數(shù)。

            -o extra-options
            在 extra-options 里面指定的命令行選項(xiàng)將被傳遞給所有由這個(gè) postgres 派生的服務(wù)進(jìn)程。如果選項(xiàng)字符串包含任何空白,那么整個(gè)字符串必須用引號(hào)界定。

            反對(duì)使用該選項(xiàng),所有服務(wù)器進(jìn)程的命令行選項(xiàng)都可以直接在 postgres 命令行上指定,不必這么麻煩。

            -p port
            指定 postgres 偵聽客戶端連接的 TCP/IP 端口或本地 Unix domain socket 文件的擴(kuò)展。缺省的端口號(hào)是環(huán)境變量 PGPORT 的值。如果 PGPORT 沒(méi)有設(shè)置,那么缺省是 PostgreSQL 編譯時(shí)指定的值(通常是 5432)。如果你聲明了一個(gè)非缺省端口,那么所有前端應(yīng)用都必須用命令行選項(xiàng)或者 PGPORT 聲明同一個(gè)端口。

            -s
            在每條命令結(jié)束時(shí)打印時(shí)間信息和其它統(tǒng)計(jì)信息。這個(gè)開關(guān)對(duì)測(cè)試性能和調(diào)節(jié)緩沖區(qū)數(shù)量有好處。

            -S work-mem
            聲明內(nèi)部排序和散列在求助于臨時(shí)磁盤文件之前可以使用的內(nèi)存數(shù)量。參閱節(jié)17.4.1里描述的配置變量 work_mem

            --name=value
            設(shè)置一個(gè)命名的運(yùn)行時(shí)參數(shù);其縮寫形式是 -c

            --describe-config
            以制表符分隔的 COPY 格式,導(dǎo)出服務(wù)器內(nèi)部配置變量、描述、缺省值。設(shè)計(jì)它主要是給管理工具使用。

            半內(nèi)部選項(xiàng)
            還有幾個(gè)其它的選項(xiàng)可以聲明,主要用于調(diào)試用途。這些東西在這里列出只是給 PostgreSQL 系統(tǒng)開發(fā)人員使用的。強(qiáng)烈反對(duì)使用這些選項(xiàng)。另外這些選項(xiàng)的任何一項(xiàng)都可能在未來(lái)版本中消失而不加說(shuō)明。

            -f { s | i | m | n | h }
            禁止某種掃描和連接方法的使用:s 和 i 分別關(guān)閉順序和索引掃描,而 n, m, h 分別關(guān)閉嵌套循環(huán),融合(merge)和 Hash 連接。

            順序掃描和嵌套循環(huán)都不可能完全被關(guān)閉。 -fs 和 -fn 選項(xiàng)僅僅是在存在其它方法時(shí)阻礙優(yōu)化器使用這些方法罷了。

            -n
            該選項(xiàng)主要用于調(diào)試導(dǎo)致服務(wù)器進(jìn)程異常崩潰的問(wèn)題。對(duì)付這種情況的一般策略是通知所有其它服務(wù)器進(jìn)程終止并重新初始化共享內(nèi)存和信號(hào)燈。這是因?yàn)橐粋€(gè)出錯(cuò)的服務(wù)器進(jìn)程可能在終止之前就已經(jīng)對(duì)共享的東西造成了破壞。該選項(xiàng)指定 postgres 不重新初始化共享數(shù)據(jù)結(jié)構(gòu)。一個(gè)有經(jīng)驗(yàn)的系統(tǒng)程序員這時(shí)就可以使用調(diào)試器檢查共享內(nèi)存和信號(hào)燈狀態(tài)。

            -O
            允許修改系統(tǒng)表的結(jié)構(gòu)。這個(gè)參數(shù)用于 initdb

            -P
            讀取系統(tǒng)表時(shí)忽略系統(tǒng)索引(但在更改數(shù)據(jù)時(shí)仍然更新索引)。這對(duì)于從索引已經(jīng)損壞的系統(tǒng)表中回復(fù)是很有幫助的。

            -t pa[rser] | pl[anner] | e[xecutor]
            打印與每個(gè)主要系統(tǒng)模塊相關(guān)的查詢記時(shí)統(tǒng)計(jì)。它不能和 -s 選項(xiàng)一起使用。

            -T
            該選項(xiàng)主要用于調(diào)試導(dǎo)致服務(wù)器進(jìn)程異常崩潰的問(wèn)題。對(duì)付這種情況的一般策略是通知所有其它服務(wù)器進(jìn)程終止并重新初始化共享內(nèi)存和信號(hào)燈。這是因?yàn)橐粋€(gè)出錯(cuò)的服務(wù)器進(jìn)程可能在終止之前就已經(jīng)對(duì)共享的東西造成了破壞。該選項(xiàng)指定 postgres 通過(guò)發(fā)送 SIGSTOP 信號(hào)停止其他所有服務(wù)器進(jìn)程,但是并不讓它們退出。這樣就允許系統(tǒng)程序員手動(dòng)從所有服務(wù)器進(jìn)程搜集內(nèi)核轉(zhuǎn)儲(chǔ)。

            -v protocol
            聲明這次會(huì)話使用的前/后服務(wù)器協(xié)議的版本數(shù)。該選項(xiàng)僅在內(nèi)部使用。

            -W seconds
            一旦看見這個(gè)選項(xiàng),進(jìn)程就睡眠標(biāo)出的秒數(shù)。這樣就給開發(fā)者一些時(shí)間把調(diào)試器附著在該服務(wù)器進(jìn)程上。

            -y database
            表明這是一個(gè)由父 postgres 進(jìn)程啟動(dòng)的子進(jìn)程,并使用指定的數(shù)據(jù)庫(kù)。該選項(xiàng)僅供內(nèi)部使用。

            單用戶模式的選項(xiàng)
            下面的選項(xiàng)僅在單用戶模式下可用。

            --single
            選中單用戶模式。這個(gè)必須是命令行中的第一個(gè)選項(xiàng)。

            database
            要訪問(wèn)的數(shù)據(jù)庫(kù)名字。如果忽略掉則缺省為用戶名。

            -E
            回顯所有命令

            -j
            禁止使用新行作為語(yǔ)句分隔符

            -r filename
            將所有服務(wù)器輸出日志保存到 filename 中。在多用戶模式下該選項(xiàng)將被忽略,所有進(jìn)程都將使用 stderr

            環(huán)境變量
            PGCLIENTENCODING
            客戶端使用的缺省字符編碼。客戶端可以獨(dú)立地覆蓋它。這個(gè)值也可以在配置文件里設(shè)置。

            PGDATA
            缺省數(shù)據(jù)目錄位置

            PGDATESTYLE
            運(yùn)行時(shí)參數(shù) DateStyle 的缺省值。現(xiàn)在反對(duì)使用該環(huán)境變量。

            PGPORT
            缺省端口(最好在配置文件中設(shè)置)

            TZ
            服務(wù)器的時(shí)區(qū)

            診斷
            一個(gè)提到了 semget 或 shmget 的錯(cuò)誤信息可能意味著你需要重新配置你的內(nèi)核,提供足夠的共享內(nèi)存和信號(hào)燈。更多討論,參閱節(jié)16.4。你也可以通過(guò)降低 shared_buffers 值以減少 PostgreSQL 的共享內(nèi)存的消耗,或者降低 max_connections 值減少 PostgreSQL 的信號(hào)燈的消耗。

            如果碰到一個(gè)說(shuō)另外一個(gè)服務(wù)器正在運(yùn)行的錯(cuò)誤信息,可以根據(jù)不同的系統(tǒng)使用命令

            $ ps ax | grep postgres或

            $ ps -ef | grep postgres如果確信沒(méi)有沖突的服務(wù)器正在運(yùn)行,那么你可以刪除消息里提到的鎖文件然后再次運(yùn)行。

            抱怨無(wú)法綁定端口的錯(cuò)誤信息可能表明該端口已經(jīng)被其它非 PostgreSQL 進(jìn)程使用。如果終止 postgres 后又馬上用同一個(gè)端口運(yùn)行它,也可能得到這個(gè)錯(cuò)誤信息;這時(shí),你必須多等幾秒,等操作系統(tǒng)關(guān)閉了該端口后再試。最后,如果你使用了一個(gè)操作系統(tǒng)認(rèn)為是保留的端口,也可能導(dǎo)致這個(gè)錯(cuò)誤信息。例如,我的 Unix 版本認(rèn)為低于 1024 的端口號(hào)是"可信任的",因而只有 Unix 超級(jí)用戶可以使用它們。

            注意
            如果有可能,不要使用 SIGKILL 殺死主 postgres 服務(wù)器進(jìn)程。這樣會(huì)阻止 postgres 在退出前釋放它持有的系統(tǒng)資源(例如共享內(nèi)存和信號(hào)燈)。這樣可能會(huì)影響到將來(lái)啟動(dòng)新的 postgres 進(jìn)程。

            可以使用 SIGTERM, SIGINT, SIGQUIT 信號(hào)正常結(jié)束 postgres 服務(wù)器進(jìn)程。第一個(gè)信號(hào)將等待所有的客戶端退出后才退出。第二個(gè)將強(qiáng)制斷開所有客戶端,而第三個(gè)將不停止立刻退出,導(dǎo)致在重啟時(shí)的恢復(fù)運(yùn)行。SIGHUP 會(huì)重新加載服務(wù)器配置文件。也可以向一個(gè)單獨(dú)的服務(wù)器進(jìn)程發(fā)送 SIGHUP 信號(hào),但是這樣做沒(méi)什么意義。

            pg_ctl 工具可以用于安全而有效地啟停 postgres ,推薦使用。

            要推出一個(gè)正在運(yùn)行的查詢,可以向正在執(zhí)行該查詢的進(jìn)程發(fā)送 SIGINT 信號(hào)。

            主 postgres 服務(wù)器進(jìn)程向子進(jìn)程發(fā)送 SIGTERM 信號(hào)讓它們正常退出;發(fā)送 SIGQUIT 信號(hào)立即退出且不做清理工作,用戶應(yīng)當(dāng)盡量避免使用該信號(hào)。同時(shí),發(fā)送 SIGKILL 信號(hào)也是不明智的:主 postgres 進(jìn)程將把這個(gè)信號(hào)當(dāng)作崩潰信號(hào),然后會(huì)強(qiáng)制其他兄弟進(jìn)程作為標(biāo)準(zhǔn)的崩潰回復(fù)過(guò)程退出。

            臭蟲
            -- 選項(xiàng)在 FreeBSD 或 OpenBSD 上無(wú)法運(yùn)行,應(yīng)該使用 -c 。這在受影響的系統(tǒng)里是個(gè)臭蟲;如果這個(gè)毛病沒(méi)有修補(bǔ)好,將來(lái)的 PostgreSQL 版本將提供一個(gè)繞開的辦法。

            用法
            啟動(dòng)一個(gè)單用戶模式的服務(wù)器:

            postgres --single -D /usr/local/pgsql/data other-options my_database用 -D 給服務(wù)器提供正確的數(shù)據(jù)庫(kù)目錄的路徑,或者確保環(huán)境變量 PGDATA 已經(jīng)正確設(shè)置。同時(shí)還要聲名你想用的特定數(shù)據(jù)庫(kù)名字。

            通常,獨(dú)立運(yùn)行的服務(wù)器把換行符當(dāng)做命令輸入完成字符;它還不懂分號(hào)的作用,因?yàn)槟切〇|西是在 psql 里的。要想把一行分成多行寫,你必需在除最后一個(gè)換行符以外的每個(gè)換行符前面敲一個(gè)反斜杠。

            但是如果使用了 -j 命令行選項(xiàng),新行將不被當(dāng)作命令結(jié)束符。此時(shí)服務(wù)器將從標(biāo)準(zhǔn)輸入一直讀取到 EOF 標(biāo)志為止,然后把把所有讀到的內(nèi)容當(dāng)作一個(gè)完整的命令字符串看待,并且反斜杠與換行符也被當(dāng)作普通字符來(lái)看待。

            輸入 EOF(Control+D)即可退出會(huì)話。如果你已經(jīng)使用了 -j 則必須連續(xù)使用兩個(gè) EOF 才行。

            請(qǐng)注意單用戶模式運(yùn)行的服務(wù)器不會(huì)提供復(fù)雜的行編輯功能(比如,沒(méi)有命令行歷史)。

            例子
            用缺省值在后臺(tái)啟動(dòng) postgres :

            $ nohup postgres >logfile 2>&1 </dev/null &在指定的端口啟動(dòng) postgres :

            $ postgres -p 1234這條命令將在端口 1234 啟動(dòng) postgres 。你應(yīng)該這樣使用 psql 與之連接:

            $ psql -p 1234或者設(shè)置環(huán)境變量 PGPORT :

            $ export PGPORT=1234$ psql命名的運(yùn)行時(shí)參數(shù)可以用下列的風(fēng)格之一設(shè)置:

            $ postgres -c work_mem=1234$ postgres --work-mem=1234兩種形式都覆蓋那些現(xiàn)有的在 postgresql.conf 里面的 work_mem 設(shè)置。請(qǐng)注意在參數(shù)名里的下劃線在命令行上可以寫成下劃線,也可以寫成連字符。除了用于短期的實(shí)驗(yàn)以外,更好的習(xí)慣是編輯 postgresql.conf 里面的設(shè)置,而不是倚賴命令行開關(guān)設(shè)置參數(shù)。

            又見
            initdb, pg_ctl

            postmaster
            Name
            postmaster -- PostgreSQL 數(shù)據(jù)庫(kù)服務(wù)器
            Synopsis
            postmaster [option...]

            Description
            postmaster 是 postgres 的別名,反對(duì)使用。

            又見
            postgres

            posted @ 2013-04-22 14:06 多彩人生 閱讀(1204) | 評(píng)論 (0)編輯 收藏

            AOP編程

            http://www.cnblogs.com/beliefbetrayal/archive/2012/02/03/2337522.html

            posted @ 2013-04-02 18:13 多彩人生 閱讀(181) | 評(píng)論 (0)編輯 收藏

            僅列出標(biāo)題
            共25頁(yè): First 7 8 9 10 11 12 13 14 15 Last 

            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            留言簿(3)

            隨筆分類

            隨筆檔案

            搜索

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            久久久久久久久久久久中文字幕 | 狠狠色丁香久久婷婷综合图片| 国产精品伦理久久久久久| 看全色黄大色大片免费久久久| 久久AV高潮AV无码AV| 久久er99热精品一区二区| 久久成人永久免费播放| 香蕉久久夜色精品升级完成| 99久久综合狠狠综合久久| 久久无码中文字幕东京热| 久久99热国产这有精品| 99精品国产99久久久久久97| 国产精品久久久久久福利漫画| 日本亚洲色大成网站WWW久久| WWW婷婷AV久久久影片| 国内精品伊人久久久影院| 国产一区二区三精品久久久无广告 | 无码精品久久久天天影视| 理论片午午伦夜理片久久| 99久久精品国内| 国产麻豆精品久久一二三| 亚洲国产成人久久精品99 | 精品久久久久久国产| 久久婷婷五月综合97色| 久久精品国产99久久久古代| 久久亚洲精品无码播放| 99久久婷婷国产综合精品草原 | 久久久精品国产亚洲成人满18免费网站 | 狠狠久久亚洲欧美专区| 久久久久亚洲av无码专区导航 | 91久久精品视频| 热久久国产精品| 国产激情久久久久影院小草| 香港aa三级久久三级| 99久久99久久精品国产| 国产成人精品久久综合| 久久久久久国产精品美女| 久久综合色之久久综合| 成人综合久久精品色婷婷| 久久国产免费直播| 久久精品国产第一区二区三区|