【问题标题】:Functions to deal with Unicode string manipulation with PowerBuilder 12.1使用 PowerBuilder 12.1 处理 Unicode 字符串操作的函数
【发布时间】:2012-10-02 16:14:15
【问题描述】:

我目前正在将目前不支持 Unicode 的 PowerBuilder 12.1 应用程序转换为支持 Unicode 的应用程序。

我已经进行了一些修改以将 Unicode 数据保存到我们的数据库以及文件中,但我在处理字符串时遇到了一点小问题。

例如,字符????是代理对,PowerBuilder 将其解释为 2 个字符(类似于 .NET 的操作方式)。因此:

LEN("????") = 2

对我来说,这部分很有意义,因为它将每个代码单元计算为一个字符。

目前我们提出了两种解决方案来处理使用 Unicode 字符的字符串函数:

  • 用 C# .NET 编写的可调用 OLEObjects
  • 使用 PBNI 接口调用 C# .NET(希望尽可能远离此解决方案

我们正在考虑用于确定字符串长度的 .NET 代码示例如下:

StringInfo.ParseCombiningCharacters("????").Length = 1

我们只是担心不断调用 OLEObjects/PBNI 来完成我们所有的字符串处理对性能的影响。这里有没有其他 PowerBuilder 开发人员做过 Unicode 字符串操作(LEN、MID、POS 等),你是怎么做的?

谢谢。

【问题讨论】:

    标签: unicode powerbuilder


    【解决方案1】:

    这是为了响应 Seki 的十六进制转换功能。我将其发布为答案,以便我可以包含源代码。我使用 Microsoft 加密函数在我的调试工具中显示 blob。这是我的 blob 窗口的简化版本。我使用的是基于 PFC 的,它使用了一个包装了 MS Crypto 库的对象。它来自 PB 12.5,但应该导入任何 Unicode 版本的 PB。

    HA$PBExportHeader$w_show_blob.srw
    forward
    global type w_show_blob from window
    end type
    type sle_1 from singlelineedit within w_show_blob
    end type
    type mle_1 from multilineedit within w_show_blob
    end type
    end forward
    
    global type w_show_blob from window
    integer width = 3081
    integer height = 1988
    boolean titlebar = true
    boolean controlmenu = true
    boolean minbox = true
    boolean maxbox = true
    boolean resizable = true
    boolean center = true
    sle_1 sle_1
    mle_1 mle_1
    end type
    global w_show_blob w_show_blob
    
    type prototypes
    FUNCTION boolean CryptBinaryToString ( &
        Blob pbBinary, &
        ulong cbBinary, &
        ulong dwFlags, &
        Ref string pszString, &
        Ref ulong pcchString ) &
    LIBRARY "crypt32.dll" ALIAS FOR "CryptBinaryToStringW"
    
    end prototypes
    
    type variables
    CONSTANT Ulong CRYPT_STRING_HEXASCIIADDR = 11   
    
    end variables
    
    forward prototypes
    public subroutine of_showblob (ref blob abl_data)
    end prototypes
    
    public subroutine of_showblob (ref blob abl_data);unsignedlong lul_size, lul_bufsize
    string ls_hex
    try
        lul_size = len(abl_data)
        sle_1.text = string(lul_size)
    
    
        setnull(ls_hex)
        cryptbinarytostring( abl_data, lul_size, CRYPT_STRING_HEXASCIIADDR, ls_hex, lul_bufsize)
        ls_hex = space(lul_bufsize)
        if not cryptbinarytostring( abl_data, lul_size, CRYPT_STRING_HEXASCIIADDR , ls_hex, lul_bufsize) then
            mle_1.text = "error converting blob data"
        else
            mle_1.text = ls_hex
        end if
    catch(runtimeerror re)
        messagebox("oops", re.text)
    
    
    end try
    
    
    end subroutine
    
    on w_show_blob.create
    this.sle_1=create sle_1
    this.mle_1=create mle_1
    this.Control[]={this.sle_1,&
    this.mle_1}
    end on
    
    on w_show_blob.destroy
    destroy(this.sle_1)
    destroy(this.mle_1)
    end on
    
    type sle_1 from singlelineedit within w_show_blob
    integer x = 73
    integer width = 517
    integer height = 88
    integer taborder = 10
    integer textsize = -10
    integer weight = 400
    fontcharset fontcharset = ansi!
    fontpitch fontpitch = variable!
    fontfamily fontfamily = swiss!
    string facename = "Arial"
    long textcolor = 33554432
    long backcolor = 553648127
    string text = "none"
    boolean displayonly = true
    borderstyle borderstyle = stylelowered!
    end type
    
    type mle_1 from multilineedit within w_show_blob
    integer x = 64
    integer y = 96
    integer width = 2898
    integer height = 1716
    integer taborder = 10
    integer textsize = -10
    integer weight = 400
    fontcharset fontcharset = ansi!
    fontpitch fontpitch = fixed!
    fontfamily fontfamily = modern!
    string facename = "Courier New"
    long textcolor = 33554432
    string text = "none"
    boolean hscrollbar = true
    boolean vscrollbar = true
    boolean displayonly = true
    borderstyle borderstyle = stylelowered!
    end type
    

    要使用它,假设您的 blob 是 lbl_myBlob:

    open(w_show_blob)
    w_show_blob.of_showblob(lbl_myBlob)
    

    MLE 中的输出如下所示:

    0000    42 4d ee 00 00 00 00 00  00 00 76 00 00 00 28 00   BM........v...(.
    0010    00 00 10 00 00 00 0f 00  00 00 01 00 04 00 00 00   ................
    0020    00 00 78 00 00 00 00 00  00 00 00 00 00 00 00 00   ..x.............
    0030    00 00 00 00 00 00 00 00  00 00 00 00 80 00 00 80   ................
    0040    00 00 00 80 80 00 80 00  00 00 80 00 80 00 80 80   ................
    0050    00 00 80 80 80 00 c0 c0  c0 00 00 00 ff 00 00 ff   ................
    0060    00 00 00 ff ff 00 ff 00  00 00 ff 00 ff 00 ff ff   ................
    0070    00 00 ff ff ff 00 88 88  88 88 88 88 88 88 88 88   ................
    0080    80 88 88 88 88 88 88 88  80 08 88 88 88 88 88 88   ................
    0090    80 00 88 88 88 88 88 88  80 00 08 88 88 88 88 88   ................
    00a0    80 00 00 88 88 88 88 88  80 00 00 08 88 88 88 88   ................
    00b0    80 00 00 00 88 88 88 88  80 00 00 08 88 88 88 88   ................
    00c0    80 00 00 88 88 88 88 88  80 00 08 88 88 88 88 88   ................
    00d0    80 00 88 88 88 88 88 88  80 08 88 88 88 88 88 88   ................
    00e0    80 88 88 88 88 88 88 88  88 88 88 88 88 88         ..............
    

    【讨论】:

      【解决方案2】:

      自 10 版以来,PB 支持 unicode (utf-16le)。所以遗留的Len() 是隐式的LenW()(与其他字符串函数一样,处理遗留数据可能意味着使用显式的LenA())。

      你确定你得到了一些 utf-16le 编码吗?给定以下函数,如果您使用 hexdump_blob(blob(your_string)) 调用它,它会在包含您的数据的字符串上返回什么?

      将此代码粘贴到名为 hexdump_blob 的新全局函数的源代码中,以便对 blob 内容进行十六进制显示(类似于十六进制编辑器)。

      global type hexdump_blob from function_object
      end type
      
      forward prototypes
      global function string hexdump_blob (blob abl_data, boolean ab_fill_lastline)
      end prototypes
      
      global function string hexdump_blob (blob abl_data, boolean ab_fill_lastline);//hexify a blob content
      string ls_tohex = "0123456789ABCDEF"
      string ls_msg = "", ls_line, ls_binary
      long i, j, length
      byte b
      string ls_fill
      
      if isnull( abl_data ) then return ""
      
      if ab_fill_lastline then
          ls_fill = " __"
      else
          ls_fill = "   "
      end if
      
      length = len( abl_data )
      for i = 1 to length
          GetByte( abl_data, i, b )
          ls_line += mid( ls_tohex, 1+ mod(int(b/16),16), 1)
          ls_line += mid( ls_tohex, 1+ mod(b,16), 1)
          ls_line += " "
          ls_binary += string( iif(b>31 and b<128,char(b)," "))
          if mod(i,16) = 0 and i > 0 then
              ls_binary = replaceall( ls_binary, "~r", "·")   //no cr/lf
              ls_binary = replaceall( ls_binary, "~n", "·")
              ls_binary = replaceall( ls_binary, "~t", "·")
              ls_msg += "[" + string( i - 16, "0000") + "] " + ls_line + "~t" + ls_binary + "~r~n"
              ls_line = ""
              ls_binary = ""
          end if
      next
      i -- // i - 1 due to the last loop in for
      ls_line += fill(ls_fill, 3 * ( 16 - mod(i, 16) ) )
      ls_msg += "[" + string( i - mod(i,16), "0000") + "] " + ls_line + "~t" + ls_binary
      
      return ls_msg
      
      end function
      

      另外,这里是hexdump_blob()使用的replaceall()函数

      global type replaceall from function_object
      end type
      
      forward prototypes
      global function string replaceall (string as_source, string as_pattern, string as_replace)
      end prototypes
      
      global function string replaceall (string as_source, string as_pattern, string as_replace);//remplace toute les occurences de as_pattern de as_source par as_replace 
      string ls_target
      long i, j
      
      ls_target=""
      i = 1
      j = 1
      do
          i = pos( as_source, as_pattern, j )
          if i>0 then
              ls_target += mid( as_source, j, i - j )
              ls_target += as_replace
              j = i + len( as_pattern )
          else
              ls_target += mid( as_source, j )
          end if
      loop while i>0
      
      return ls_target
      end function
      

      以及模拟 C 三元运算符的iif(),或visual basic iif()

      global type iif from function_object
      end type
      
      forward prototypes
      global function any iif (boolean ab_cond, any aa_true, any aa_false)
      end prototypes
      
      global function any iif (boolean ab_cond, any aa_true, any aa_false);
      // simulates the VB iif or C ternary operator
      
      if ab_cond then
          return aa_true
      else
          return aa_false
      end if
      
      end function
      

      【讨论】:

        【解决方案3】:

        【讨论】:

        • 由于LenA() 是针对ansi 文本的,我猜OP 不会有不同的结果。
        • 是的,很遗憾 LenA() 无法满足我们的需求。我们正在尝试按视觉字符总数而不是代码单元来计算。
        猜你喜欢
        • 1970-01-01
        • 2015-10-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-06-12
        • 1970-01-01
        • 2015-07-11
        相关资源
        最近更新 更多