English Sentence Loading...
英语句子加载中...
公告板
预览模式: 普通 | 列表

C#改装dll成com实战


1、用sn工具生成用于强命名的密钥  sn.exe -k test.snk

2、程序属性中配置好为程序签名并选择密钥,选择为com Interop注册和程序集中使用程序集COM可见


3、using System.Runtime.InteropServices;//为了调用GUID
using System.EnterpriseServices;//引用COM+的类

public interface ISharpObject2
    {
        Segment seg
        {
            get;
            set;
        }
        Segment loaddic();
        string segword(Segment seg, string str);

    }

 public class PHPSeg : ServicedComponent, ISharpObject2
    {
        private Segment _seg;
        public Segment seg //Property: Name, Get/Set
        {
            get { return _seg; }
            set { _seg = value; }
        }

        public Segment loaddic()
        {
            Segment seg = new Segment();
            seg.InitWordDics();
            return seg;
            //label_Time.Text = seg.EventTime.ToString();
        }

        public string segword(Segment seg,string str)
        {
            //分词
            if (seg != null)
            {
                seg.Separator = "/";
                str = seg.SegmentText(str, true);
                return str;              
            }
            else return "";
        }
    }


4、regsvcs /fc your.dll注册 /u销毁


下载: TestEvent.cs
  1. public class TestEvent
  2.  {
  3.  public TestEvent()
  4.  {
  5.  }
  6.  //计算1--20的和
  7.  public int caculate()
  8.  {
  9.  int n = 0;
  10.  for (int i = 0; i < 20; i++)
  11.  {
  12.  n += i;
  13.  System.Threading.Thread.Sleep(200);
  14.  OnStateChanged("正在加" + i + " \r\n");
  15.  //System.Threading.Thread.Sleep(200);
  16.  }
  17.  
  18.  return n;
  19.  }
  20.  
  21.  public delegate void StateHandler(object sender, StateEventArgs e);
  22.  public event StateHandler StateChanged;
  23.  private void OnStateChanged(string s)
  24.  {
  25.  if (this.StateChanged != null)
  26.  this.StateChanged(this, new StateEventArgs(s));
  27.  }
  28.  }
  29.  
  30.  public class StateEventArgs : EventArgs
  31.  {
  32.  
  33.  private string state;
  34.  public string State
  35.  {
  36.  get
  37.  {
  38.  return state;
  39.  }
  40.  }
  41.  public StateEventArgs(string s)
  42.  {
  43.  this.state = s;
  44.  }
  45.  }


用的一个Form的界面(一个label1 和一个button1)
主要调用代码

下载: form1.cs
  1. delegate void settextcallback(string text);
  2.  private void setlabeltext(string text)
  3.  {
  4.  if (this.label1.InvokeRequired)
  5.  {
  6.  settextcallback se = new settextcallback(setlabeltext);
  7.  this.Invoke(se, new object[] { text });
  8.  }
  9.  else
  10.  {
  11.  this.label1.Text = text;
  12.  }
  13.  }
  14.  
  15.  
  16.  public Form1()
  17.  {
  18.  InitializeComponent();
  19.  }
  20.  
  21.  
  22.  private void te_StateChanged(object sender,StateEventArgs e)
  23.  {
  24.  setlabeltext(e.State);
  25.  }
  26.  
  27.  private void button1_Click(object sender, EventArgs e)
  28.  {
  29.  System.Threading.Thread th = new System.Threading.Thread(new System.Threading.ThreadStart(threadfunc));
  30.  th.Start();
  31.  }
  32.  private void threadfunc()
  33.  {
  34.  TestEvent te = new TestEvent();
  35.  te.StateChanged += new TestEvent.StateHandler(te_StateChanged);
  36.  int n = te.caculate();
  37.  MessageBox.Show("结果是" + n.ToString());
  38.  }






Form1里面的 InitializeComponent(); 就不贴了~~~
希望对类里面事件的写法有所帮助


SharpDevelop源码-用户界面

Demo界面及功能解释
相关概念
Demo代码分析
总结
Demo下载

1、Demo界面及功能解释:

启动界面:

支持打开图片:

支持打开网页:

功能说明:程序有个浮动窗口显示当前磁盘文件,选择文件并双击后在中心窗口中以适当的察看器打开文件;持拖曳打开文件;程序关闭后再次启动时能够“记忆”前一次程序关闭时的窗体大小位置及打开过的文件。

2、相关概念:
主窗体部分:              Workbench
磁盘文件查看窗口:    Pad
文件查看窗口:         ViewContent
说明:
Pad可以使用ICSharpCode.Core的Addin插件机制来扩充Pad,如Visual Studio的资源管理器、类查看器、属性窗口、消息窗口等都属于Pad
ViewContent同样支持插件扩充,根据不同的文件类型使用不同的控件来处理显示,Demo中已实现的文件类型支持:网页文件、图片、普通文本,Visual Studio中的代码窗口、窗体设计器、资源编辑器、对象查看器等都属于ViewContent
Workbench与WorkbenchLayout结合使用来控制主窗口的外观显示,如普通的MDI(PhotoShop?)或Demo使用的WeifenLuo.WinFormsUI.Docking显示方式……

3、Demo代码分析
(注:下面的分析前提是你已经了解如何使用ICSharpCode.Core的Addin插件机制)
通过上面的界面及功能说明,可以确定程序至少应包括接口声明、基本实现两个项目,而接口中又分为:Pad接口、ViewContent接口、Workbench接口,这样的程序设计重点与难点在哪呢?思考后的结果应该是接口,从接口中能看到程序各部分是如何交互的,以及插件的扩展点,接口的设计好坏决定着程序的易维护性与易扩展性,所以下面就重点看接口的定义(附介绍相关对象的创建等):

Pad接口
 1//  Core|Interface 定义部分:
 2public interface IPadContent : IDisposable
 3{
 4    System.Windows.Forms.Control Control get; }
 5    
 6    void RedrawContent();
 7}

 8public class PadDescriptor : IDisposable
 9{
10    Codon       codon;
11    IPadContent padContent;
12    bool        padContentCreated;
13    
14    public string Title {
15        get {
16            return codon.Properties["title"];
17        }

18    }

19    public string Icon {
20        get {
21            return codon.Properties["icon"];
22        }

23    }

24    public string Class {
25        get {
26            return codon.Properties["class"];
27        }

28    }

29    public IPadContent PadContent {
30        get {
31            CreatePad();
32            return padContent;
33        }

34    }

35    public void CreatePad()
36    {
37        if (!padContentCreated) {
38            padContentCreated = true;
39            padContent = (IPadContent)codon.AddIn.CreateObject(Class);
40        }

41    }

42    //省略部分方法、属性
43    public PadDescriptor(Codon codon)
44    {
45        this.codon = codon;
46    }

47}

48//  Gui项目中的实现
49class PadContentWrapper : DockContent
50{
51    PadDescriptor padDescriptor;    //通过此对象来获取相关属性
52    //
53}
看到IPadContent接口返回一个WinForm的Control控件,此控件在实现时被相应的窗体获取并适当地显示,Demo中的磁盘查看器Pad返回的Control是一个UserConrol,使用了TreeView和ListView组合。注意IPadContent接口中定义返回一个Control而非Form是很聪明的技巧,可以看到实现端的PadContentWrapper继承自WeifenLuo.WinFormsUI.DockContent,这依赖于实现端的表现方式,而接口可以不受影响。PadDescriptor是个辅助类,用以返回Pad相关的属性信息,包括返回IPadContent的实例对象。
接下来看Pad的xml声明及客户端调用:
Pad声明及使用
 1//取自Entry项目的SD_UI.addin
 2<Path name = "/SharpDevelop/Workbench/Pads">
 3    <!--
 4    ProjectBrowser
 5    ClassBrowser
 6    SideBar
 7    ErrorList
 8    TaskList
 9    CompilerMessageView
10    PropertyPad
11    SearchResults
12    Bookmarks
13    DefinitionView
14    
15    -->
16    <Pad id       = "FileScout"
17         category = "Tools"
18         title    = "${res:MainWindow.Windows.FileScoutLabel}"
19         icon     = "PadIcons.FileBrowser"
20         shortcut = "Control|Alt|F"
21         class    = "SDUserInterface.GUI.Pad.FileScout"/>
22</Path>
23// 取自Gui项目的DefaultWorkbench.cs
24void InitializeWorkspace()
25{
26    //
27    ArrayList contents = AddInTree.GetTreeNode("/SharpDevelop/Workbench/Pads").BuildChildItems(this);
28    foreach (PadDescriptor content in contents)
29    {
30        if (content != null)
31        {
32            ShowPad(content);
33        }

34    }

35    //
36}

配置文件中的class指定了实现IPadContent的一个类型(全称限定名),使用时通过ICSharpCode.Core的AddInTree对象构建相关PadDescriptor集合……

下面来看ViewContent的定义:

ViewContent接口
 1// Core|Interface 定义部分:
 2public interface IViewContent : IDisposable
 3{
 4    Control Control getset; }
 5
 6    IWorkbenchWindow WorkbenchWindow getset; }
 7
 8    string TitleName getset; }
 9
10    string FileName getset; }
11
12    bool IsReadOnly get; }
13
14    void Load(string fileName);
15
16    event EventHandler TitleNameChanged;
17}

18public class DisplayBindingDescriptor
19{
20    object binding = null;
21    Codon codon;
22    
23    public IDisplayBinding Binding {
24        get {
25            if (binding == null{
26                binding = codon.AddIn.CreateObject(codon.Properties["class"]);
27            }

28            return binding as IDisplayBinding;
29        }

30    }

31    
32    public Codon Codon {
33        get {
34            return codon;
35        }

36    }

37    
38    public DisplayBindingDescriptor(Codon codon)
39    {
40        this.codon = codon;
41    }

42    
43    public bool CanAttachToFile(string fileName)
44    {
45        string fileNameRegex = codon.Properties["fileNamePattern"];
46        if (fileNameRegex == null || fileNameRegex.Length == 0// no regex specified
47            return true;
48        return Regex.IsMatch(fileName, fileNameRegex, RegexOptions.IgnoreCase);
49    }

50}

51public interface IDisplayBinding
52{
53    bool CanCreateContentForFile(string fileName);
54    
55    IViewContent CreateContentForFile(string fileName);
56}

57// Gui项目中的实现:
58public class SdiWorkspaceWindow : DockContent, IWorkbenchWindow
59{
60    IViewContent content;
61    //
62}

可以看到IViewContent同样是返回一个Conrol,供使用端(SdiWorkspaceWindow)根据需要封装组合;DisplayBindingDescriptor同样是个辅助类,除了返回ViewContent的相关属性信息外,提供了bool CanAttachToFile(string fileName)方法,用以判断当前显示插件是否可以显示相关类型的文件,这里的判断是通过配置文件中的fileNamePattern属性作正则判断(注:文件名称符合一定规则的可能会用到此属性,一般不常用),注意到该辅助类返回了一个IDisplayBinding接口,查看该接口的方法可以看到使用它来更进一步地判断当前文件是否是可支持类型(通过文件扩展名或试读取等方式),如果属于该插件支持类型的文件则创建并返回IViewContenet接口。ViewContent插件的声明如下:

ViewContent插件声明
 1<Path name = "/SharpDevelop/Workbench/DisplayBindings">
 2    <DisplayBinding id               = "Browser"
 3                    supportedformats = "Web Pages"
 4                    class            = "SDUserInterface.GUI.ViewContent.BrowserDisplayBinding"/>
 5    <DisplayBinding id    = "Text"
 6                        insertafter = "Browser"
 7                        supportedformats = "Text Files,Source Files"
 8                        class = "SDUserInterface.GUI.ViewContent.TextViewDisplayBinding" />
 9    <DisplayBinding id    = "Image"
10                        insertbefore = "Text"
11                        supportedformats = "图片"
12                        class = "SDUserInterface.GUI.ViewContent.ImageDisplayBinding" />
13</Path>

值得注意的是insertbefore, insertafter 属性,此属性指明获取所有DisplayBindingDescriptor后的先后顺序,如:一个.rtf文件可以由Office-Word和记事本打开,一般要优先选择使用Word打开。
获取ViewContent对象的过程如下:双击磁盘文件Pad中的一个文件项时,调用FileService中的OpenFile(string fileName)方法,相关代码如下:

获取/使用ViewContent
 1// 取自Gui项目中的Common/FileService.cs
 2public static IWorkbenchWindow OpenFile(string fileName)
 3{
 4    //
 5    IDisplayBinding binding = DisplayBindingService.GetBindingPerFileName(fileName);
 6    
 7    if (binding != null{
 8        binding.CreateContentForFile(fileName);
 9        WorkbenchSingleton.Workbench.ShowView(newContent);
10        //
11    }
 else {
12        throw new ApplicationException("Can't open " + fileName + ", no display codon found.");
13    }

14    return GetOpenFile(fileName);
15}

16// 取自Gui项目中的Common/DisplayBindingService.cs
17static DisplayBindingDescriptor GetCodonPerFileName(string filename)
18{
19    foreach (DisplayBindingDescriptor binding in bindings) {
20        if (binding.CanAttachToFile(filename)) {
21            if (binding.Binding != null && binding.Binding.CanCreateContentForFile(filename)) {
22                return binding;
23            }

24        }

25    }

26    return null;
27}

接下来看主窗体的定义:

Workbench接口
 1public interface IWorkbench
 2{
 3    string Title  getset; }
 4
 5    List<IViewContent> ViewContentCollection get; }
 6
 7    List<PadDescriptor> PadContentCollection get; }
 8
 9    IWorkbenchWindow ActiveWorkbenchWindow get; }
10    
11    object ActiveContent get; }
12    
13    IWorkbenchLayout WorkbenchLayout getset; }
14    
15    void ShowView(IViewContent content);
16
17    void CloseAllViews();
18    
19    void CloseView(IViewContent content);
20    
21    void ShowPad(PadDescriptor content);
22    
23    PadDescriptor GetPad(Type type);
24
25    void RedrawAllComponents();
26}

27public interface IWorkbenchLayout
28{
29    bool FullScreen getset; }
30
31    IWorkbenchWindow ActiveWorkbenchwindow get; }
32
33    object ActiveContent get; }
34    
35    void Attach(IWorkbench workbench);
36    
37    void Detach();
38    
39    void ShowPad(PadDescriptor content);
40
41    void ShowPad(PadDescriptor content,bool bActivateIt);
42    
43    IWorkbenchWindow ShowView(IViewContent content);
44
45    void RedrawAllComponents();
46
47    void LoadConfiguration();
48    void StoreConfiguration();
49}

IWorkbench定义主窗体,IWorkbenchLayout定义窗体布局,可以看到IWorkbench的两个重要属性是Pad和ViewContent的对象集合(维护已打开的窗体记录,避免重复打开等作用),其实现类的ShowPad()/ShowView()方法执行的操作即向对应的集合添加成员,然后调用IWorkbenchLayout的ShowPad()/ShowView()。IWorkbenchLayout的LoadConfiguration()和StoreConfiguration()方法用以在窗体加载或关闭时执行加载或保存子窗口布局的操作。

至此Demo的核心已分析完了,我们可以根据定义的接口扩展程序,如增加项目管理/查看Pad, 增加.swf等文件查看的ViewContent, 或更换主界面显示为普通MDI方式……

4、总结:
此Demo更说明了ICSharpCode.Core的插件支持可以应用到很多的方面:
a, 界面组成部分Pad
b, 界面中不同类型的文件查看器ViewContent
c, 磁盘文件查看Pad的下侧文件列表针对不同文件显示相关图标(详见SD_UI.addin文件的"/Workspace/Icons"层次下的定义)
...
SharpDevelop的这种界面设计方案使得应用程序很容易扩展和进一步开发,而不与已开发的模块冲突;从中得到的启发是应用程序要重点设计接口(契约)以及处理对象间的关系……

说明:Demo代码基本来源于SharpDevelop源码,删改了部分代码以使Demo精简和突出重点。

转自:http://www.cnblogs.com/michael-zhang/articles/629724.html

Daemon Tools3.47常用的虚拟光驱软件。近日却在windows server2008上安装不成功,不仅不成功,安装后蓝屏。重启后无限次蓝屏。麻烦大了。。


看蓝屏的说明。是驱动的问题。尝试删除Dtools的安装文件夹。重启后依旧蓝屏。。

刚好有两个系统,一个xp...想过先进xp查找Dtools安装时安装的.sys驱动删除看看。。。进入windows/system32/drivers/删除 d347bus.sys和d347prt.sys两个驱动文件

成功!

可以启动windows 2008了

重新下载安装最新版本Daemon Tools Lite 4.12.1可以解决该问题。

另外桌面图标大小过大
可以通过 桌面上点右键->查看->经典图标 就可以了.
距离的设置 在桌面右键 ->自定义设置 ->外观 —>高级 的图标间距(垂直)和图标间距(水平)里设置 我的电脑设置成36比较合适

记下犯的弱智问题 & 常用的几个连接语句模板

        Mysql连接语句中的字符集编码只支持 utf8,不支持utf-8这样的写法,害得调试找了半天。发下我常用的几个模板,具体使用你可以去替换。或写成一个static函数。sqlserver因为在程序中考虑到和access的兼容,使用的是oledb的连接方式

       

  1. /// <summary>
  2.  /// Mysql连接语句模板
  3.  /// </summary>
  4.  public static string connMysqlTemplate = "server=[数据库路径];user id=[用户名]; password=[密码]; database=[数据库]; pooling=false;charset=[编码];Port=[端口];";
  5.  
  6.  /// <summary>
  7.  /// SqlServer连接语句模板
  8.  /// </summary>
  9.  public static string connSqlServerTemplate = "Provider=Microsoft.Jet.OLEDB.4.0;Password=;User ID=[用户名];Data Source=[数据库];Jet OLEDB:Database Password=[密码]";
  10.  
  11.  /// <summary>
  12.  /// Sqlite连接语句模板
  13.  /// </summary>
  14.  public static string connSqliteTemplate = "Provider=SQLiteOLEDB;Data Source=[数据库路径]";
  15.  
  16.  /// <summary>
  17.  /// Access连接语句模板
  18.  /// </summary>
  19.  public static string connAccTemplate = "Provider=Microsoft.Jet.OLEDB.4.0;Password=;User ID=;Data Source=[数据库路径];Jet OLEDB:Database Password=";

配了个新电脑 22'宽屏

公司准备再招人,电脑不够了

想用台式机了。刚好把俺的Vostro1500换给小文用
很冲动,昨天想的今天马上就去百脑汇抱回来了,一共5500,可以刷信用卡,还是不错滴

具体配置:

酷睿2 E7200+超频三
威刚 2G/800 *2
技嘉 EP45-DS3L
希捷 500G SATA
七彩虹9600GT 256M
三星T220
SG9500+航嘉冷钻
漫步者音箱
明基DVD等~~

使用Process类重定向输出与错误时遇到的问题

在使用PHP CLI开发交互式程序事遇到的问题,在网上找到的解决办法 http://www.x2blog.cn/BoyTNT/6311.html

【摘要】
    使用Process类重定向时遇到死锁问题,对Process的实现机制进行了一番思考,想看全文就点进去吧。

【全文】

[系统环境]
    .Net Framework 1.1,使用C#开发WinForm程序

[问题描述]
    程序中要调用外部程序cmd.exe执行一些命令行,并取得屏幕输出,使用了Process类,基本代码如下:


    Process process = new Process();
    process.StartInfo.FileName = "cmd.exe";
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardInput = true;
    process.StartInfo.RedirectStandardOutput = true;
    process.StartInfo.RedirectStandardError = true;
    process.StartInfo.CreateNoWindow = true;
    process.Start();

    …………  //一些处理

    process.StandardInput.WriteLine("exit");
    //取输出内容
    String outputString = process.StandardOutput.ReadToEnd();
    process.WaitForExit();
    process.Close();

    实际使用中发现有时程序会无响应,并且是在执行某些特定的命令时才会无响应。跟踪调试发现,问题出在process.StandardOutput.ReadToEnd()上,在这一行按F10,程序不向下执行,也不产生Exception。

[解决过程]
    由于调试时程序不向下执行,猜测ReadToEnd()没有返回,被阻塞住了,查了查MSDN,没有看到有相关内容。又反编了一下mscorlib.dll,看了看StreamReader.ReadToEnd()的实现方法,是这么一段代码:


    public override string ReadToEnd()
    {
        int num1;
        if (this.stream == null)
        {
            __Error.ReaderClosed();
        }
        char[] chArray1 = new char[this.charBuffer.Length];
        StringBuilder builder1 = new StringBuilder(this.charBuffer.Length);
        while ((num1 = this.Read(chArray1, 0, chArray1.Length)) != 0)
        {
            builder1.Append(chArray1, 0, num1);
        }
        return builder1.ToString();
    }

    从中看出ReadToEnd()是利用Read()方法实现的,又去MSDN看了,仍然没有提到Read()是阻塞函数,于是只能上网去查一查相关资料,有人提到了类似的问题,并且给出了解决方法:使用两个线程分别做StandardOutput.ReadToEnd()和StandardError.ReadToEnd()。试了一下,果然可以解决。

[后续思考]
    问题虽然解决,不过原理没有弄明白,还要继续深入。查阅相关资料,大致了解了Process的运作模式,它以子进程的形式启动cmd.exe,如果指定了重定向Input、Output或Error,就建立相应的管道在父子进程之间进行通讯。
    基于这些内容以及关于管道的理解,得到以下几条猜测:
    1、input、output、error的三条管道是相互独立的。
    2、管道有大小,空时不可读,满时不可写。
    3、遇到管道不可读写时,相应的进程会阻塞等待可读写为止。
    4、子进程结束前,output流与error流不会结束。

    这样再翻回来考虑之前遇到的问题,可以猜测无响应时是这样一种情况:
    建立Process时指定了Output和Error都重定向,父子进程间就建立了2条管道,cmd.exe不停输出output与error,分别进入两条管道,对output,管道满后,子进程会停下来等待父进程取走数据,父进程的StandardOutput.ReadToEnd()方法正是取数据的,它在管道空时会处于阻塞状态,有数据时就取走,这样子进程会继续写output。
    但是对于error,父进程没有相应的ReadToEnd()方法,很快error的管道就满了,由于无法写error,子进程会停下来等待,但是父进程永远不读,子进程也就永远不再继续,形成死锁。
    对于不出问题的情况,一定是error管道根本就没有写满,这也就解释了为什么命令的内容决定了是否会出现无响应的情况。

    那么直接在StandardOutput.ReadToEnd()后面加一条StandardError.ReadToEnd()行不行呢?答案是不行的,基于上面的猜测与分析,ReadToEnd()方法是阻塞的,在子进程结束前,output流不会关闭,所以StandardOutput.ReadToEnd()会一直等待,造成后面的StandardError.ReadToEnd()方法根本不被执行,还是会产生死锁。所以解决方案里才提到了要建立2个线程,让两个管道的ReadToEnd()方法独立执行。

    再回来考虑我的程序中的情况,之所以没有去读Error,是因为我根本不关心子进程产生的error输出,所以应该有更简单的方法,就是把process.StartInfo.RedirectStandardError置为false,经测试验证,想法是对的, 这样还避免了使用线程。
    在分析的过程中还对process.WaitForExit()方法产生了兴趣,从msdn的描述来看,它的作用是等待子进程结束,应该也是阻塞的,但在我的程序中它在ReadToEnd()方法后面,是否还有实际作用呢?猜测子进程结束后,ReadToEnd()方法才返回,WaitForExit()方法才被调用,但此时它已没有什么用了,肯定立刻返回,向下执行。跟踪调试了一下,验证了自己的想法,于是干脆去掉了这一句,经验证并没有对运行产生影响。

    以上很大部分都是自己的猜测,并不敢保证准确,也许很多地方理解有误,欢迎各位大牛指正。

【全文结束】
【评论1】时间:2006-6-22 10:52:40作者:bood
嗯,分析的很有道理
【评论2】时间:2007-11-12 18:03:11作者:九门提督
存在另外一种情况,即Process.StandardOutput.ReadLine(),正常的屏显输出在Process.StandardError.ReadLine(),对于这种情况,只要改从error管道获取就可以解决。
如Oracle的exp.exe
是否具有普遍性尚未考证。
【评论3】时间:2008-6-6 10:50:44作者:Mac
Very simple method can resolve this problem well:
Use asynchronous read operations. See MSDN.

Follow these steps to perform asynchronous read operations on StandardOutput for a Process :
1. Set UseShellExecute to false.
2. Set RedirectStandardOutput to true.
3. Add your event handler to the OutputDataReceived event. The event handler must match the System.Diagnostics..::.DataReceivedEventHandler delegate signature.
4. Start the Process.
Call BeginOutputReadLine for the Process. This call starts asynchronous read operations on StandardOutput.

When asynchronous read operations start, the event handler is called each time the associated Process writes a line of text to its StandardOutput stream.

php汉字的截取完美解决方案

php汉字的截取完美解决方案 函数巧妙地运用了正则表达式, 用起来很方便, 就像 substr 的用法一样, 可以正向截取也可反相截取, 思路值得学习.
函数巧妙地运用了正则表达式, 用起来很方便, 就像 substr 的用法一样, 可以正向截取也可反相截取, 思路值得学习.

PHP代码:
  1. <?php
  2. function c_substr($string, $from, $length = null){
  3.     preg_match_all('/[x80-xff]?./', $string, $match);
  4.     if(is_null($length)){
  5.         $result = implode('', array_slice($match[0], $from));
  6.     }else{
  7.         $result = implode('', array_slice($match[0], $from, $length));
  8.     }
  9.     return $result;
  10. }
  11. $str = "zhon华人min共和guo";
  12. $from = 3;
  13. $length = 7;
  14. echo(c_substr($str, $from, $length));
  15. // 输出: n华人min共
  16. //还有utf-8的
  17. /*
  18. Regarding windix's function to handle UTF-8 strings:
  19. one can use the "u" modifier on the regular expression so that the pattern string is treated as UTF-8
  20. (available from PHP 4.1.0 or greater on Unix and from PHP 4.2.3 on win32).
  21. This way the function works for other encodings too (like Greek for example).
  22. The modified function would read like this:
  23. */
  24. function utf8_substr($str,$start) {
  25. $null = "";
  26.    preg_match_all("/./u", $str, $ar);
  27.    if(func_num_args() >= 3) {
  28.        $end = func_get_arg(2);
  29.        return join($null, array_slice($ar[0],$start,$end));
  30.    } else {
  31.        return join($null, array_slice($ar[0],$start));
  32.    }
  33. }
  34. ?>
  之二:
  1. <?php
  2. /***************************************************/
  3. /*                                                                     */
  4. /*  Author:                                                     */
  5. /*  HomePage: www..com                                          */
  6. /*  Email: phforum@163.com                                             */
  7. /*  QQ:1984412                                                         */
  8. /*                                                                     */
  9. /***************************************************/
  10. function get_substr($string,$start='0',$length='')
  11. {
  12. $start = (int)$start;
  13. $length = (int)$length;
  14. $i = 0;
  15. if(!$string)
  16. {
  17.   return;
  18. }
  19. if($start>=0)
  20. {
  21.   while($i<$start)
  22.   {
  23.    if(ord($string[$i])>127)
  24.    {
  25.     $i = $i+2;
  26.    }
  27.    else
  28.    {
  29.     $i++;
  30.    }
  31.   }
  32.   $start = $i;
  33.   if($length=='')
  34.   {
  35.    return substr($string,$start);
  36.   }
  37.   elseif($length>0)
  38.   {
  39.    $end = $start+$length;
  40.    while($i<$end)
  41.    {
  42.     if(ord($string[$i])>127)
  43.     {
  44.      $i = $i+2;
  45.     }
  46.     else
  47.     {
  48.      $i++;
  49.     }
  50.    }
  51.    if($end != $i-1)
  52.    {
  53.     $end = $i;
  54.    }
  55.    else
  56.    {
  57.     $end--;
  58.    }
  59.    $length = $end-$start;
  60.    return substr($string,$start,$length);
  61.   }
  62.   elseif($length==0)
  63.   {
  64.    return;
  65.   }
  66.   else
  67.   {
  68.    $length = strlen($string)-abs($length)-$start;
  69.    return get_substr($string,$start,$length);
  70.   }
  71. }
  72. else
  73. {
  74.   $start = strlen($string)-abs($start);
  75.   return get_substr($string,$start,$length);
  76. }
  77. }
  78. ?>
·此地為某只的個人YY之地,言論僅代表自己的個人觀點,和現實、社會、政治完全沒關係,沒事請不要在此惹事生非。
·若要轉載本blog内容請註明轉載地址和作者名字,禁止無權轉載/盜鏈等無恥行爲。
·如有轉載侵權請聯系刪除。
·謝謝合作。^_^