Earthquake – Facebook make its own datacenter open-source!!!

Leave a comment

When you run slowly, you don’t know how the world will be changed by Giant!
Facebook may change the game again, refer to Chinese Version of news.

The orignal news in Facebook site, Open Compute Resources.
Facebook of Open Compute Site!!!

Catch up with the wave!!!the most interesting topic!!!

Advertisements

Open Source Integration on SAP Composite Environment 7.x

Leave a comment

* UI Layer – Struts2 version 2.0.14

  1. Each web request handled by web default class loader will invoke a new Web session object [ObjectFactory or Filter object ] to load struts.xml file.
    Default class Loader path – under root classpath of Web application, exactlly speaking, under \servlet_jsp\\root\WEB-INF\classes. So in order to load Web jsp as action, you need to redirect action name based on class loader path.
    Root
           +—index.jsp+other jsps
           +—WEB-INF
           +—classes <= default class loader path of struts2
           +—lib <= runtime library
    So, when action mapping, A.jsp should be specified as follow ../../A.jsp in struts.xml or other include files.
  2. In order to see if Action is avaiable after the Web session has been started, config-browser could be used, the offical demo of Struts2 debugging could be found Debugging with Struts2.

* Business Reusble Layer – Stateless Session Bean , Hiberate and Spring

Reason

  • Spring and Hiberate could instantiate reusable bean during the deployment;
  • EJB could reuse the Spring and Hiberate bean instance in object pool during life cycle control;
  • Compared with JPA 1.0 OR mapping, Hiberate could provide a leaner implementation, if object cache optimization topic hasn’t been discussed.
  •  

Technical Architecture

    The main architecture has been shown in the following chart.

The core idea of multi-layers is that we can isolated Spring and Hiberate application under EJB layer, then construct a lean and shared Java Client Framework.Then in the UI layer, we can use struts together with Spring client bean to construct a lean UI layer.Easy to forecast that UI layer will be changed dynamically, however the underlined business foundtation services won’t be changed so much. With an isloated EJB layer and underlined core services implementation, together with interface contact, our architecture could adapt to the changes as fast as possible. A short description from bottom to up as follow:

  • Foundation Framework
  1. Platform EJB [Generic Service Layer, such as Generic HiberateDAO service and SAP JCO connection bean]
  2. Open Source libraries DC[Including standardize version of shared open source libraries]
  • Reuse Interface
  1. Share Interface – Cross VM interface [RMI interface, EJB interface, Hiberate DAO interface & Configuration], All of items could be serizable and be passed by different client. In short, Service Contact interface
  2. Java Client Framework – EJB Client Proxy[decouple EJB caller as simple JavaBean implementation, which could be used in Struts&Spring bean]; Reuse Web Client Optimization and Interceptor[Including Gzip of JS client scripts and Interceptor with Profiling for cross Platforms]
  • Business Framework – Common EJB for business logic
  • Presentation Layer –  Web UI layer
  • EJB Client Test Layer – Automated Java Test case based on EJB interface

Implementation of Prototpye

Now I’d like to give the detailed information about implementation prototype.

Distruted Database architect based on Meomory database

Leave a comment

本来是想用中文写的,想了下可以发给andreas和其他兄弟看下,还是用英文写得了。
就算技术讨论吧,本文的主要观点借鉴了2010年7月《程序员》的文章:何伸-基于内存数据库的分布式数据库架构,在读这篇文章的时候,觉得这个模型很像SAP最近一直在内部讨论的In memory database/computing,但如果只是一个简单数据层加速,那就不能成为计算模型。这点我有一些个人的想法。
 
OK, Let’s start the trip now…
 
* Memory RDBMS
 
 
 
 
 
 
 
 

Visual Studio 2010 Architecture Tooling Guidance

Leave a comment

This morning, when going through the blog on CSDN headline, I happened to find this link :

The original link posted by Microsoft guy in CodePlex address : http://vsarchitectureguide.codeplex.com/.
Yeah, hope it’s very valuable and could be certain "best guideline under VS2010 development platform".
 
***************************************************************************************************************************
By the way, great match for German team yesterday night.
They said, Argentina is the best football team in the world. 
3-4 heroes ?= excellent team 
Podolski just comment "Let’s see" before this "santi-war".
Yeah, I see, team work and ironed spirit. 
Remember famous saying, "football is a kind of game with 11 guys". Congratulation, Let’s see.

 
***************************************************************************************************************************
http://news.csdn.net/a/20100702/219013.html Alogrithm for search engine

P/Invoke以及APM编程常识

Leave a comment

  • 下午一口气把EC的后面几章读完聊,有点晕!
  • Jerry大牛的那几篇文章还是要好好读下的,Jerry大牛
  • 使用P/Invoke来实现对完成端口的C#编程,熟悉下.Net 3.5下Marshal类的新特性,复习非托管类型封送的关键点。[代码工程]

1。工具以及应用资料:P/Invoke的值以及引用封送CLR的封送处理;建议使用P/Invoke的兄弟去看看这个工具,P/Invoke Interop Assistant 1.0[含代码],MS的P/Invoke买一送一工具!

2。线程池搭配完成端口的实现[和Jerry写的那个基本上一个模子倒出来的]

  • 花了点时间把Jerry的版本[核心5第10章,IO完成端口的例子]用P/Invoke转为C#的版本,主要再熟悉下P/Invoke在3.5环境中的用法和改进。[比2003强大多了]犯了几个错误,还有一些心得,都整理下吧,计划把Jerry的例子都转为C#放在自己的函数库里面,这样快速开发的时候应该有很多可用的素材。毕竟。NET的界面开发还是要方便的多。
  • 正题之前感概一下,唉!线程池,完成端口这些重武器被我拿来写异步拷贝文件,大才小用了!

1.一个误用关于PreserveSig = false

P/Invoke原型如下:

[DllImportAttribute("kernel32.dll", EntryPoint = "CreateFileW", SetLastError = true /*PreserveSig = false*/)]
        public static extern IntPtr CreateFileW([InAttribute()] [MarshalAsAttribute(UnmanagedType.LPWStr)] string lpFileName, FileAccessRight dwDesiredAccess, FileSharedMode dwShareMode,
            [InAttribute()] IntPtr lpSecurityAttributes, CreatePosition dwCreationDisposition, FileFlagAndAttribute dwFlagsAndAttributes, [InAttribute()] IntPtr hTemplateFile);
先看下<.NET本质论>的描述:“DllImport在OLE32Wrapper.CoSomeAPI32的情况下,以HRESULT返回的方法为short值,对于用底层的[out,retval]参数”。再看下MSDN的描述:

简单的说,这个参数是将HRESULT返回忽略,代之以“[out,retval]”的参数[多out参数呢?],然后用COMexception来处理返回异常。OK,而此处封装的CreateFileW并不满足这个条件,如果让引擎忽略了返回句柄,那等于白干了!

2.封送类型[Marshal Type],没什么说的,Don的书上说的很清楚。这里再次崇拜MS的强大,那个工具里面可变类型和不可变类型能够轻松识别,当然这一切的基础在于正规化的Win32变量命名。[再次说明了开发要正规化的远见卓识]

3.P/Invoke的基石:值类型的默认Marshal处理[这个文章是P/Invoke必读!]由于CLR要与非托管模式交互,其类型布局和访问权限就必须要在类型定义中显式指明,这也就是很多人遇到了“无法预知长度”异常的原因了!注意怎么指定Union结构体的布局,本质论上有,也可以参见文章!

4.P/Invoke的麻烦:本地代码和CLR环境的转化,这就是P/Invoke被称为怪物的原因了!转化起来很麻烦,而且有的时候不得不面临一些资源泄露[虽然我们可以说GC在,没问题,但有的地方GC却无法插手!而那个时候,就该你挽起袖子干活]

所以,第一,对于为IntPtr用Marshal显式分配的内存,必须在托管环境下显式回收!第二,当你需要处理指向指针的指针,并且存在类派生时[很多是指向值类型的指针],要在托管环境中显式处理。第三,IntPtr这个怪物,是在托管环境中的非托管指针,所以请你千万要给它以及它的孪生兄弟指向的托管类型一个内存,在用Marshal.StructureToPtr之前!动手编程之前最好看下小巧但威力强大的Marshal,比原来的版本强了不止一个数量级,呵呵!可以直接从非托管环境里面读取值类型,包括上面提到的StructurToPtr,和逆过程

  • 下面是IORequest的代码,提醒自己InPtr的回收和指向指针的指针处理[还好这里是值类型,可以用ref省去一些力气]

[StructLayout(LayoutKind.Sequential)]
    public class IORequest : OVERLAPPED, IDisposable
    {
        //private field
        public static int BUFFSIZE = 64 * 1024;
        private uint m_nBuffSize;
        private IntPtr m_pvData;

        /// <summary>
        /// Initializes a new instance of the <see cref="IORequest"/> class.
        /// </summary>
        public IORequest()
        {
            this.Internal = this.InternalHigh = 0;
            this.Union1.Struct1.Offset = this.Union1.Struct1.OffsetHigh = 0;
            hEvent = IntPtr.Zero;
            m_nBuffSize = 0; m_pvData = IntPtr.Zero;
        }

        /// <summary>
        /// Thises to int PTR.OVERLAPPED method!
        /// </summary>
        /// <returns></returns>
        private IntPtr ThisToIntPtr()
        {
            OVERLAPPED cur = (OVERLAPPED)this;
            IntPtr pnt = Marshal.AllocHGlobal(Marshal.SizeOf(cur));//显式类型转化,已经非托管指针转化
            Marshal.StructureToPtr(cur, pnt, false);

            return pnt;
        }

        /// <summary>
        /// Allocs the buffer.
        /// </summary>
        /// <param name="nBuffSize">Size of the n buff.</param>
        /// <returns></returns>
        public bool AllocBuffer(uint nBuffSize)
        {
            m_nBuffSize = nBuffSize;
            m_pvData = Marshal.AllocHGlobal((int)nBuffSize);
            return (m_pvData != IntPtr.Zero);
        }

        /// <summary>
        /// Reads the specified h device.
        /// </summary>
        /// <param name="hDevice">The h device.</param>
        /// <param name="pliOffset">The pli offset.</param>
        /// <returns></returns>
        public bool Read(IntPtr hDevice, IntPtr pliOffset)
        {
            if (pliOffset != IntPtr.Zero)
            {
                LARGE_INTEGER liOffset = (LARGE_INTEGER)Marshal.PtrToStructure(pliOffset, typeof(LARGE_INTEGER));
                this.Union1.Struct1.Offset = liOffset.Struct1.LowPart;
                this.Union1.Struct1.OffsetHigh = (uint)liOffset.Struct1.HighPart;
            }
            // Initialize unmanged memory to hold the struct, sign! dummy implementation
           
            return (Win32File.ReadFile(hDevice, m_pvData, m_nBuffSize, IntPtr.Zero, ThisToIntPtr()));
        }

        /// <summary>
        /// Writes the specified h device.
        /// </summary>
        /// <param name="hDevice">The h device.</param>
        /// <param name="pliOffset">The pli offset.</param>
        /// <returns></returns>
        public bool Write(IntPtr hDevice, IntPtr pliOffset)
        {
            if (pliOffset != IntPtr.Zero)
            {
                LARGE_INTEGER liOffset = (LARGE_INTEGER)Marshal.PtrToStructure(pliOffset, typeof(LARGE_INTEGER));
                this.Union1.Struct1.Offset = liOffset.Struct1.LowPart;
                this.Union1.Struct1.OffsetHigh = (uint)liOffset.Struct1.HighPart;
            }
            // Initialize unmanged memory to hold the struct, sign! dummy implementation
            return (Win32File.WriteFile(hDevice, m_pvData, m_nBuffSize, IntPtr.Zero, ThisToIntPtr()));
        }

        #region IDisposable Members
        public void Dispose()
        {
            if (m_pvData != IntPtr.Zero) Marshal.FreeHGlobal(m_pvData);//挽起袖子干的脏活,GC应该干不料,它没那么聪明!
        }
        #endregion

    }

  • 完成端口配合线程池的实现[这个线程的入口是一个委托的异步调用,至于为什么异步是个线程,本质论的异步方法调用P193有描述,这个模型的后续产物就是,我们在 private void Completed(IAsyncResult call) 里面需要UI线程判断以及另一个委托来更新界面,具体的实现可以参见Chris Sells的《Windows Form程序设计》第14章 多线程环境下的用户界面 或者MSDN里面搜索InvokeRequired或者UIDispatch]。这个括号打太大了,见笑,下面是将Jerry的代码转化为托管之后的实现,当然代码有点C++的风格,呵呵!Jerry的实现是用UI线程来处理的,所以要死一段时间。这里没有这个问题,不过,我写的很粗糙,设计模式完全没学好!

        /// <summary>
        /// Threads the proc.
        /// </summary>
        public void ThreadProc()
        {
            //文件初始化处理

            //following logic: to create IOCompletionPort then start Four [Herusitic Method] ThreadPool Task to I/O handling!
            //however, how about file lock? please dwell on it!
            this.ioCP.AssociateDevice(this.hFileSrc, CK_READ);
            this.ioCP.AssociateDevice(this.hFileDist, CK_WRITE);

            //shared parameters intialization
            this.nReadsInProgress = 0;
            this.nWritesInProgress = 4;
            this.liNextReadOffset = new LARGE_INTEGER();
            ioTaskDone.Reset();//Events
            //ThreadPool for Task item
            ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadPoolWorkItem));

            //Then IOrequest item
            for (int i = 0; i < 4; i++)
            {
                Debug.Assert(ioRequest[i].AllocBuffer(BUFFSIZE));
                IntPtr ior_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ioRequest[i]));
                Marshal.StructureToPtr(ioRequest[i], ior_ptr, false);
                this.ioCP.PostStatus(CK_WRITE, 0, ior_ptr);//Post to IO Completion Port
            }

            ioTaskDone.WaitOne();
            //shrink 文件结束处理
        }

        //ThreadPool WorkItem
        private void ThreadPoolWorkItem(object state)
        {
            //ignore the loop
            while (this.nReadsInProgress > 0 || this.nWritesInProgress > 0)
            {
                //Get IO Completion Key from caller
                uint CompletionKey = 0, dwNumBytes = 0;
                IORequest curRequest = new IORequest();
                IntPtr pior = Marshal.AllocHGlobal(Marshal.SizeOf(curRequest));
                this.ioCP.GetStatus(ref CompletionKey, ref dwNumBytes, ref pior, Win32Helper.INFINITE);
                //convert pior back to curRequest
                Marshal.PtrToStructure(pior, curRequest);

                //judge by Completion Key, back c
                if (CompletionKey == CK_READ)
                {
                    Interlocked.Decrement(ref this.nReadsInProgress);
                    if (!curRequest.Write(this.hFileDist, IntPtr.Zero))
                    {
                        //Debug.WriteLine(Marshal.GetLastWin32Error());
                    }                   
                    Interlocked.Increment(ref this.nWritesInProgress);
                }
                else if (CompletionKey == CK_WRITE)
                {
                    Interlocked.Decrement(ref this.nWritesInProgress);
                    if (this.liNextReadOffset.QuadPart < this.liFileSizeDist.QuadPart)
                    {
                        //not end
                        IntPtr nextReads = Marshal.AllocHGlobal(Marshal.SizeOf(this.liNextReadOffset));
                        Marshal.StructureToPtr(this.liNextReadOffset, nextReads, true);
                        if (!curRequest.Read(this.hFileSrc, nextReads))
                        {
                            //Debug.WriteLine(Marshal.GetLastWin32Error());
                        }
                        Interlocked.Increment(ref this.nReadsInProgress);
                        Interlocked.Add(ref this.liNextReadOffset.QuadPart, BUFFSIZE);
                    }
                }
            }
            this.ioTaskDone.Set();//release resource
        }

  • APM from Jerry Richter. [if you have read Jerry’s previous books, or see his speech online, yeah….funny!]
1。you need to avoid having state data reside on the thread’s stack because data on the thread’s stack cannot migrate to another thread.[Lost virtual pointer, Common Sense].
2。you need to split up your code into callback methods, sometimes called continuations.[Yeah,in delegation, we also get familiar with that, however, someone will forget on which thread they’re handling with!]
3。Third, there are many useful programming constructs—such as try/catch/finally statements, the lock statement, the using statement, and even loops [lock,Mointor.enter(),try()….,OK,don’t forget the basic unit of synblock under CLR is object!]
4。Finally, trying to offer features such as coordinating the result of multiple overlapping operations, cancellation, timeout, and marshaling UI control modifications to the GUI thread in a Windows® Forms or Windows Presentation Foundation (WPF) application adds even more complexity to using the APM.[OK,the master seems to say that take care of single UI principle, yeah, it’s important and sometims always be ingored by some guys]
 

Orlando try to do a simple exercise,howeve,just a minute,a glass of water.Let’s enjoy coding time now! Found it’s a little bit easy for me to complete, yeah, let’s turn to implementation, however, just take care of coding from byte to char.

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Diagnostics;
using System.Threading;

namespace APMpro
{
    /// <summary>
    /// APM programming learnt from Jerry richter
    /// </summary>
    class Program
    {
        static string file = "..\\..\\1.mht";
        static int len = 8192;

        static void Main(string[] args)
        {
            SynMethod();
            ApmPatternWithMultipleMethods();
            ApmLamdba();
            Console.Read();
        }

        //dummy implemenation for process data
        static void processData(byte[] data)
        {
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
            Console.WriteLine("***************************************************");
            //UnicodeEncoding _curCoding = new UnicodeEncoding();
           
            //Console.WriteLine(new String(_curCoding.GetChars(data)));
            char[] csofFile=new char[Encoding.ASCII.GetCharCount(data, 0, data.Length)];
            Encoding.ASCII.GetChars(data, 0, data.Length, csofFile, 0/*csofFile.Length*/);
            Console.WriteLine(csofFile);
            Console.WriteLine("***************************************************");
        }

        #region synmethod
        private static void SynMethod()
        {
            using (FileStream inFile = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read, len, FileOptions.None))
            {
                Byte[] data = new Byte[inFile.Length];
                inFile.Read(data, 0, len);
                processData(data);
                inFile.Close();
            }
        }
        #endregion

        #region APMwithAsyn
        private sealed class ApmData
        {
            public FileStream fs;
            public byte[] m_data;
        }

        private static void ApmPatternWithMultipleMethods()
        {
            FileStream inFile = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read, len, FileOptions.Asynchronous);//don’t use using
            ApmData _data = new ApmData();
            _data.m_data = new byte[len];
            _data.fs = inFile;
            inFile.BeginRead(_data.m_data, 0, len, ReadCompleted, _data);
            //after read completed
        }

        private static void ReadCompleted(IAsyncResult result)
        {
            ApmData _curdata = (ApmData)result.AsyncState;
            //read bytes
            Int32 readBytes = _curdata.fs.EndRead(result);
            processData(_curdata.m_data);
            Debug.WriteLine("Read Completed : " + readBytes);
            _curdata.fs.Close();
        }

        #endregion

        #region APMwithLamdba Expression
        private static void ApmLamdba()
        {
            FileStream inFile = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read, len, FileOptions.Asynchronous);//don’t use using
            byte[] data = new byte[len];
            inFile.BeginRead(data, 0, data.Length, result=>
            {
                Int32 bytesRead = inFile.EndRead(result);
                processData(data);
                inFile.Close(); // No ‘using’
            }, null);
        }
        #endregion
    }
}

1。一个是要加锁,Dictionary是无同步锁的集合,但这里还好是对集合的对象处理!本来是想对集合加锁的,但想了下好像没必要,这样的代码会长一些!

2。不过可以用MethodImpl来进行方法同步,细细想下,八杆子打不着!所以,直接对操作对象加锁就可以了!

3。ThreadPool里面用dummy来避免传递参数![试验了下和SilverLight一样线程池对象在Asp。Net里面都支持了,想当年做Asp。Net的时候,还没有这些东西,连脚本都是非常恶心的方式搞定的,时代在进步呀!忽然想到了一个东西如果那个时候有LINQ就好了,不用搞得那么头大了,做个中间层写了爆多的东西!PS:都是垃圾]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Text;

namespace SynCache
{
    /// <summary>
    /// Sample for cache updating with ThreadPool implementation
    /// </summary>
    class Program
    {/// <summary>
        /// Medium : items, which are synchronized with Dictionary in the p/s cache.
        /// </summary>
        public class Medium
        {
            /// <summary>
            /// Gets or sets the content of Medium.
            /// </summary>
            /// <value>The store.</value>
            public object Store { get; set; }

            /// <summary>
            /// Gets or sets a value indicating whether this instance is updating.
            /// </summary>
            /// <value>
            ///  <c>true</c> if this instance is updating; otherwise, <c>false</c>.
            /// </value>
            public bool IsUpdating { get; set; }
        }

        /// <summary>
        /// Task items
        /// </summary>
        public class Task
        {
            private Func<object> func;
            private Medium target;
            public Task(Medium _t, Func<object> _func)
            {
                func = _func; target = _t;
            }
            public void ThreadProc(object dummy)
            {
                lock (target)
                {
                    target.IsUpdating = true;
                    Console.WriteLine("begin write");
                    target.Store = func.Invoke();
                    Console.WriteLine("end write");
                    target.IsUpdating = false;
                }
            }
        }

        public class DictionaryCache : System.Collections.IEnumerable
        {
            /// <summary>
            /// cache for dictionary
            /// </summary>
            private Dictionary<int, Medium> cache;

            //opertator [] for Dictionary
            public object this[int key]
            {
                get
                {//only way to get synchronization operation
                    if (!cache.ContainsKey(key)) return null;
                    return cache[key].Store;
                }
            }

            public void Add(int key, Func<object> func)
            {
                if (cache.ContainsKey(key))
                {//having key, update with ThreadPool
                    var elem = cache[key];
                    if (elem.IsUpdating) return;
                    Task workItem = new Task(elem, func);
                    try
                    {
                        ThreadPool.QueueUserWorkItem(new WaitCallback(workItem.ThreadProc), workItem);
                    }
                    catch
                    {
                    }
                }
                else
                {//for the current thread
                    Console.WriteLine("Begin first write");
                    cache.Add(key, new Medium { Store = func() });
                    Console.WriteLine("End first write");
                }
            }

            public DictionaryCache()
            {
                this.cache = new Dictionary<int, Medium>();
            }

            #region IEnumerable Members
            public System.Collections.IEnumerator GetEnumerator()
            {
                return cache.GetEnumerator();
            }
            #endregion
        }
        static void Main(string[] args)
        {
            var cache = new DictionaryCache();
            while (true)
            {
                cache.Add(1, GetValue);
                Thread.Sleep(100);
                Console.WriteLine(cache[1]);
            }
        }

        static object GetValue()
        {
            Thread.Sleep(400);//simulate database access
            return DateTime.Now;
        }
    }
}

关于wcout,wofstream的一些东西

Leave a comment

遇到一个问题,解决了,做个总结:WIN32编程原来没想到把c++和WIN32放在一起做开发,上次被个缓冲区的溢出搞怕了,所以用c++的流来代替!

结果故事就开始了,文章有点长,要读做好心理准备哈![其实,要知道答案不用看前面,直接看case就晓得怎么编码了,不过,如果你懂了运行时的机制,那么你也就懂料,为什么会有这个问题,所以。。。]

  • 总结下在VC[2005]下的CRT调用

[存在模式转换wcout,wiofstream,如果不需要的话,直接调用_fwrite(crt的ASCI运行时)写入到设备即可]:

operator<< -> streambuf::virtual streamsize __CLR_OR_THIS_CALL xsputn(const _Elem *_Ptr,streamsize _Count)
                  -> int __cdecl fputc (int ch,FILE *str) [msvcr80d.dll]  -> int __cdecl _write_nolock (int fh,  const void *buf, unsigned cnt) [write.c]

最关键的步骤在_write_nolock[这个名字说明函数已经成功通过"关键段"的同步验证]的设计步骤: [这个函数内部会判断所谓的字符模式,注意这个模式是流状态(流缓冲区)的模式]

  1. tmode = _textmode(fh);//测试当前字符状态:__IOINFO_TM_ANSI(ASCN C模式),__IOINFO_TM_UTF8,  __IOINFO_TM_UTF16LE
  2. 当前的字符模式匹配,以及console缓冲区的匹配]                                                                                                                                                               if (_isatty(fh) && (_osfile(fh) & FTEXT))//OK,读取当前模式
    {

                DWORD dwMode;
                _ptiddata ptd = _getptd();
                isCLocale = (ptd->ptlocinfo->lc_handle[LC_CTYPE] == _CLOCALEHANDLE);
                toConsole = GetConsoleMode((HANDLE)_osfhnd(fh), &dwMode);
    }
  3. 转化操作:                                                                                                                                                                                                                toConsole && !(isCLocale && (tmode == __IOINFO_TM_ANSI))) //针对Console的,若当前locale和标准C不匹配,或者当前字符模式不是默认的ANSI模式,则进行转化:首先进行double convert,然后用writeFile写到设备;                                                                                                                                           

简单的说,就是当前的wcout,cout会根据两点来进行核心操作:

  • 当前字符类型,就是上面提到的字符状态:char->wchar_t,wchar_t->char,下面是调用平台相关API[windows下的WideXXXtoChar,或者相反的函数]
  • 当前的现场[c++程序设计语言里locale类]

但这里有个陷阱,就是看上面的转化条件[若当前locale是标准c时,会进行转化么?不会的!]

说了这么多,MS的CRT宽字符转化是什么时候进行,事实是:当你的字符类型是宽字符,且locale不是标准c时才进行。[不相信的话,去VS里面F11自己看!]

好了,这就很容易解释下面的一些现象了:

case 1:

我们在默认的locale条件下,完全没有转化,直接打出,当前这是由于运行时的环境是简体中文的,因此是能输出中文的!

cout<<locale().name().c_str()<<endl;
cout<<cout.getloc().name().c_str()<<endl;
cout<<"cout   不支持输出中文? "<<endl;

case 2:

我去控制面板将系统语言更改为EN_US,locale("")会获取系统平台相关的默认语言,这个时候自然就不能输出中文了!

[顺便说一句,JRE的设置也是从系统默认语言环境中读取的,所以如果你要给老大做演示,而所有的默认系统对话框都是中文,你知道怎么做萨!]

locale::global(locale(""));//cout.imbue(std::locale("Chinese"));这句是强制的流locale绑定,呵呵,建议用这个,locale("")与系统相关,出了问题不好找
cout<<locale().name().c_str()<<endl;
cout<<cout.getloc().name().c_str()<<endl;
cout<<"cout   不支持输出中文? "<<endl;

以上的两种情况都不存在转化[double convert]问题,下面来看两个比较容易错的情况:[呵呵,开始吓了我一跳,仔细分析了下,恍然大悟]

case 3: wcout的试验

wchar_t s0[15]=TEXT("丁磊");
char s2[30];
::WideCharToMultiByte(CP_ACP, NULL, s0, _countof(s0), s2, _countof(s2), NULL, NULL);//to ASCI
cout<<s2<<endl;
wcout<<s0<<endl;

第一cout肯定是没问题的,情况和case1,case2一样,下面的wcout呢?不要惊讶,如果你追踪堆栈的话,你会发现在 int __cdecl fputc (int ch,FILE *str)之后,会得到一个错误码,然后直接退出:

看看这个函数

wint_t __cdecl fputwc (
        wchar_t ch,
        FILE *str
        )
{
        REG1 FILE *stream;
        REG2 wint_t retval;

        _VALIDATE_RETURN((str != NULL), EINVAL, WEOF);

        /* Init stream pointer */
        stream = str;

        _lock_str(stream);
        __try {

        retval = _fputwc_nolock(ch,stream);

        }
        __finally {
                _unlock_str(stream);
        }

        return(retval);
}

/***
*_fputwc_nolock() –  putwc() core routine (locked version)
*
*Purpose:
*       Core putwc() routine; assumes stream is already locked.
*
*       [See putwc() above for more info.]
*
*Entry: [See putwc()]
*
*Exit:  [See putwc()]
*
*Exceptions:
*
*******************************************************************************/

wint_t __cdecl _fputwc_nolock (
        wchar_t ch,
        FILE *str
        )
{

        if (!(str->_flag & _IOSTRG))
        {
            if (_textmode_safe(_fileno(str)) == __IOINFO_TM_UTF16LE)
            {
                /* binary (Unicode) mode */
                if ( (str->_cnt -= sizeof(wchar_t)) >= 0 ) {
                    return (wint_t) (0xffff & (*((wchar_t *)(str->_ptr))++ = (wchar_t)ch));
                } else {
                    return (wint_t) _flswbuf(ch, str);
                }
            }
            else if (_textmode_safe(_fileno(str)) == __IOINFO_TM_UTF8)
            {
                /*
                 * This is for files open for unicode writes. We need 2 chars
                 * instead of 1. Note that even if we are writing UTF8, we don’t
                 * really need to worry about it here. _write will take care of
                 * proper conversion.
                 */

                char * p = (char *)&ch;

                if(_putc_nolock(*p, str) == EOF)
                    return WEOF;

                ++p;

                if(_putc_nolock(*p, str) == EOF)
                    return WEOF;

                return (wint_t)(0xffff & ch);

            }
            else if ((_osfile_safe(_fileno(str)) & FTEXT))//对于标准输入在这里,前面两种是文本模式
            {
                int size, i;
                char mbc[MB_LEN_MAX];

                /* text (multi-byte) mode */
                if (wctomb_s(&size, mbc, MB_LEN_MAX, ch) != 0)
                {
                        /*
                         * Conversion failed; errno is set by wctomb_s;
                         * we return WEOF to indicate failure.
                         */
                        return WEOF;
                }
                for ( i = 0; i < size; i++)
                {
                        if (_putc_nolock(mbc[i], str) == EOF)
                                return WEOF;
                }
                return (wint_t)(0xffff & ch);
            }
        }
        /* binary (Unicode) mode */
        if ( (str->_cnt -= sizeof(wchar_t)) >= 0 )
                return (wint_t) (0xffff & (*((wchar_t *)(str->_ptr))++ = (wchar_t)ch));
        else
                return (wint_t) _flswbuf(ch, str);
}

为什么呢?你可能有点抓狂,可是确实如此,自己犯的错,MS CRT当然不会替你买单!

问题在wchar_t s0[15]=TEXT("丁磊");//这个编码是多长,4*sizeof(wchar_t),两个中文字符在转化入wchart_t时,是以0xXX的形式放入的,虽然能看到自己的名字很爽,但是字符数组里面的存储可能让你很不爽。每个汉字的高低字节被分别存入两个wchar_t里面!俄!~~

随后的事情就很容易理解了,在下面的函数里面,CRT为你的每个wchar_t进行分别的高低字节验证,发现不符合安全验证规范[说实话,这里追进去看代码,没看的很懂的]!新的_s函数当然不买你的帐!直接返回异常码了!

/* text (multi-byte) mode */
                if (wctomb_s(&size, mbc, MB_LEN_MAX, ch) != 0)
                {
                        /*
                         * Conversion failed; errno is set by wctomb_s;
                         * we return WEOF to indicate failure.
                         */
                        return WEOF;
                }

因此对于case 3: wcout的正确写法:

wchar_t s0[15]=TEXT("丁磊");
 char s2[30];
 ::WideCharToMultiByte(CP_ACP, NULL, s0, _countof(s0), s2, _countof(s2), NULL, NULL);//to ASCI
 cout<<s2<<endl;
 wcout<<s2<<endl;//有点惊讶吧,不过这是对的!

但这样还是不直观,如果更直观的搞定呢,其实很简单,我们强制的给流一个locale状态让它不是ASCI的标准状态即可![这样它就不会到FTEXT模式,而是转到相应的Unicode编码处理处了!]

case 4: wcout,cout

wchar_t s0[15]=TEXT("丁磊");
 char s2[30];
 ::WideCharToMultiByte(CP_ACP, NULL, s0, _countof(s0), s2, _countof(s2), NULL, NULL);//to ASCI
 wcout.imbue(locale("Chinese"));
 cout<<s2<<endl;
 wcout<<s0<<endl;

case 5: 文件操作类似

wchar_t s0[15]=TEXT("丁磊");

wofstream out("proc.txt");
 if(!out) return EXIT_FAILURE;
 try{
  out.imbue(locale("Chinese"));//如果注释掉这行,那wofstream又会傻拉巴即的去当你的字符是FTEXT处理,自然就是被_s给砍掉了,所以proc.txt就是空
  out<<L"输出0:"<<s0<<endl;//注意L,使得“输出0“也是同上处理,所以自然为空
  out<<L"输出1:"<<s0<<endl;
 }catch(const runtime_error& ex){
  cerr<<ex.what()<<endl;//这个不是用异常处理的,所以ex肯定是永远抓不到,是用返回异常码的方式处理
 }
 out.close(); cout<<endl;

  • GCC呢?赫赫,好的多,为什么好的多呢?GCC是一个纯的编程平台,MS CRT里面还有语言包的转化处理,如果你在GCC里面这样写wchar_t *s0=L"丁磊";,GCC编译都通不过,因此你要辛苦点去处理ASCI码了,去翻汉字国标吧!顺便提一下Code::Block里面其实有wofstream的支持的,只是有点麻烦,不如直接调windows的API方便,见http://www.hardforum.com/archive/index.php/t-973922.html[所以MS方便是方便,就是有的时候,让人费解,如果想GCC那样,什么都开放出来,让你自己去看,反而没人骂了]
  • 至于这个MS的support,呵呵,你可以当不存在,因为与其问别人,不如自己动手去看运行时的程序!http://support.microsoft.com/default.aspx/kb/274012
  • 那天看到有人在CSDN上发贴子,不过没人管,估计是比较冷的地方吧!如果不是想将win32和c++结合起来用一下,也不会搞出这个问题来!做过了,就不难了!

一些关于locale的资料:

  1. BJ的《c++程序设计语言》,附录里面-中文名叫《现场》locale
  2. c++网上的库描述[GCC这块没有MS crt做的好,locale的很多东西都不能用!感觉c++的locale理念和MS的相差很远,所以几乎什么都没有!]

搜索开始,C++的STL部分

Leave a comment

  • C++ STL部分

1.     各个容器的比较:vector[连续内存],list[双向链表],剩下的stack,heap,deque可以基于以上容器;rb_tree based的关联容器!BJ说,应该坚决使用vector,[流汗了],后面还有一句话“除非数据量决定了另一种选择”;好嘛,以后坚决支持,既然大牛都如此在意换入换出的效率![76条]
2.     使用vector和string::c_str与非c++API交互,不要问为什么,看下vector的实现就明白了[78条]
3.     这条让我流汗,我无知了大名鼎鼎的boost里面shared_ptr,不晓得是什么东西!暂时忽略这条,在容器中只存储值和智能指针[shared_ptr]!
4.     push_back按指数级扩大容量,拷贝一次[80条]
5.     多用范围操作[vector::insert(position, first::iterator, last::iterator)],少用单元素操作[我想也适用于多用算法unintialized_copy(),unintialized_fill_n()吧],对于连续内存[allocator<T>,new[]->vitrualAllocate等],当然少移动存在元素的好![81条]
6.     这条又让我流汗了
    "erase-remove“ 法则,c.erase(remove(c.begin(),c.end(), value), c.end()),读懂remove和erase方法!remove是移动值的位置[翻下STL实现,再评价],erase才能将dirty的值真正删掉;
    "magic swap" 法则,containter<T>(c).swap();containter<T>().swap(c)用来压缩容量,没用过,不过先放这里!当然s.reverse(0)以及string(s.begin(),s.end()).swap(s),用来优化!
     加上一条vector什么时候才初始化!想清楚再写代码
     再加一条和JAVA一样,STL也存在所谓的"dirty iterator",你说呢?remove(),erase()都会使得当前iterator无效;还记得J2SE里面的法则么?当你用iterator.remove()之后,还能继续使用么?该如何做呢?[iterator.next()跳过,问题还是有滴!]虽然我很恨JAVA,不过调试JXTA的bugs还是不得不抓出这个臭虫!

Sample:

deque<double>::iterator current=d.begin();
for(size_t i=0; i<max; i++){
   current=d.insert(current, data[i]+41);
   current++;
}
//还是用这个吧
transform(data.begin(),data.end(),inserter(d,d.begin(),bind2nd(plus<double>(),41)));//OK
transform(data,data+max,inserter(d.d.begin())+41);//还是忘了吧!

 
  • 算法部分:
    早晨头好痛,把中位数O(N)算法,油田分布!动规分析了两道题目!
    递归的一道神题
    搜索的实现[入门的三道题]

好了,继续写算法的代码了!

Older Entries