首页 文章 精选 留言 我的

精选列表

搜索[安全研究],共10000篇文章
优秀的个人博客,低调大师

Android 轻“.NET研究”松实现语音识别

苹果的iphone 有语音识别用的是Google 的技术,做为Google 力推的Android 自然会将其核心技术往Android 系统里面植入,并结合google 的云端技术将其发扬光大。 所以Google Voice Recognition在Android 的实现就变得极其轻松。 语音识别,借助于云端技术可以识别用户的语音输入,包括语音控制等技术,下面我们将利用Google 提供的Api 实现这一功能。 功能点为:通过用户语音将用户输入的语音识别出来,并打印在列表上。 功能界面如下: 用户通过点击speak按钮显示界面: 用户说完话后,将提交到云端搜索: 在云端搜索完成后,返回打印数据: 完整代码如下: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> /* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS,上海闵行企业网站制作r /> * WITHOUT WARRANTIE上海企业网站制作S OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.android.apis.app; import com.example.android.apis.R; import android.app.Activity; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Bundle; import android.speech.RecognizerIntent; import android.view.View; import android.view.View.OnClickListener; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.ListView; import java.util.ArrayList; import java.util.List; /** * Sample code that invokes the speech recognition intent API. */ public class VoiceRecognition extends Activity implements OnClickListener { private static final int VOICE_RECOGNITION_REQUEST_CODE = 1234 ; private ListView mList; /** * Called with the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { 上海网站建设yle="color: #0000ff;">super .onCreate(savedInstanceState); // Inflate our UI from its XML layout description. setContentView(R.layout.voice_recognition); // Get display items for later interaction Button speakButton = (Button) findViewById(R.id.btn_speak); mList = (ListView) findViewById(R.id.list); // Check to see if a recognition activity is present PackageManager pm = getPackageManager(); List < ResolveInfo > activities = pm.queryIntentActivities( new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0 ); if (activities.size() != 0 ) { speakButton.setOnClickListener( this ); } else { speakButton.setEnabled( false );上海闵行企业网站设计与制作='color:white;' href='http://www.93tj.com'>上海徐汇企业网站制作 sp上海企业网站设计与制作eakButton.setText( " Recognizer not present " ); } } /** * Handle the click on the start recognition button. */ public void onClick(View v) { if (v.getId() == R.id.btn_speak) { startVoiceRecognitionActivity(); } } /** * Fire an intent to start the speech recognition activity. */ private void startVoiceRecognitionActivity() { Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); intent.putExtra(RecognizerIntent.EXTRA_PROMPT, " Speech recognition demo " ); startActivityForResult(intent, VOICE_RECOGNITION_REQUEST_CODE); } /** * Handle the results from the recognition activity. */ @Override protected void onActivityResult( int requestCode, int resultCode, Intent data) { if (requestCode == VOICE_RECOGNITION_REQUEST_CODE && resultCode == RESULT_OK) { // Fill the list view with the strings the recognizer thought it could have heard ArrayList < String > matches = data.getStringArrayListExtra( RecognizerIntent.EXTRA_RESULTS); mList.setAdapter( new ArrayAdapter < String > ( this , android.R.layout.simple_list_it上海徐汇企业网站设计与制作em_1, matches)); } super .onActivityResult(requestCode, resultCode, data); }} Tip:本篇 从Api Demo直接复制过来,必须有网络支持。

优秀的个人博客,低调大师

JPDA 架构研究18 - JDI的Mirror机制

引入: 上篇文章从整体上来看待JDI协议,这里结合Eclipse的实现代码来讨论下JDI的Mirror机制。 分析: 镜像机制是将目标虚拟机上的所有数据、类型、域、方法、事件、状态和资源,以及调试器发向目标虚拟机的事件请求等都映射成 Mirror 对象。其思想和我们经常说的O/R Mapping一样,其主要思想就是把2个异构的系统中的事物统一起来。 Mirror接口是JDI规范中定义的主接口,它位于com.sun.jdi包中: 1 2 3 4 5 public abstract interface Mirror { public abstract StringtoString(); public abstract VirtualMachinevirtualMachine(); } 这个接口只提供了2个方法,一个是返回该镜像的字符串描述,一个是获取某镜像的实例的虚拟机。 Mirror机制定义了一个庞大的接口hierarchy, com.sun.jdi包中定义的几乎所有接口都直接或者间接继承了Mirror接口,从而把庞大的Debug过程中用到的任何元素,过程,事件都映射起来。 比如基本类型的值被映射为PrimitiveValue, 对象实例被映射为ObjectReference等。 在Eclipse中,它提供了MirrorImpl的镜像实现类,其中获取镜像虚拟机的代码是读取成员变量fVirtualMachineImpl字段,该字段在构造器中初始化: 1 2 3 4 5 6 7 8 9 public MirrorImpl(Stringdescription) { this .fDescription=description; this .fVirtualMachineImpl=((VirtualMachineImpl) this ); PrintWriterwriter=((VirtualMachineManagerImpl) Bootstrap.virtualMachineManager()).verbosePrintWriter(); if (writer!= null ) this .fVerboseWriter= new VerboseWriter(writer); } 虚拟机类提供了许多方法来直接或间接地获取目标虚拟机上所有的数据和状态信息,也可以挂起、恢复、终止目标虚拟机。这样调试器就可以通过某个Mirror,然后间接获得对应虚拟机,并且发送相应指令来完成相应操作了。 本文转自 charles_wang888 51CTO博客,原文链接:http://blog.51cto.com/supercharles888/1587968,如需转载请自行联系原作者

优秀的个人博客,低调大师

基于XMPP协议的Android IM研究一

之前在做基于XMPP协议的Android IM项目的过程中遇到了不少问题,由于国内这方面的资料相对比较少,而且不够全面,经过不断的学习和请教,项目有了一点进展,下面分享一下在项目的过程中遇到的问题和解决办法。 首先,声明XMPP连接: Java代码 publicstaticfinalConnectionConfigurationconnConfig=newConnectionConfiguration("169.254.50.19",5222,"http://06peng.com"); publicstaticXMPPConnectionconnection; ConnectionConfiguration类的三个参数分别为ip地址,端口号,域名。 建立XMPP连接 Java代码 static{ connConfig.setSASLAuthenticationEnabled(true);//不使用SASL验证,设置为false connection=newXMPPConnection(connConfig); connection.connect();//连接 connection.login("06peng","111111");//登陆 } 这样就能够和服务器连接了,运行代码,结果悲剧。报下面的错误: Java代码 java.security.KeyStoreException:KeyStorejksimplementationnotfound 还有: Java代码 SASLauthenticationfailedusingmechanismPLAIN: 验证不通过,可是我已经设置了不使用SASL验证了,居然还出现这样的问题,于是看官方网站的例子,发现前面加了下面的配置: Java代码 ConnectionConfigurationconnectionConfig=newConnectionConfiguration(host,5222,""); connectionConfig.setTruststorePath("/system/etc/security/cacerts.bks"); connectionConfig.setTruststorePassword("changeit"); connectionConfig.setTruststoreType("bks"); 好吧,加上这样的验证代码应该是没问题了,哪知道一运行,还是悲剧,继续报错: Java代码 not-authorized(401) atorg.jivesoftware.smack.NonSASLAuthentication.authenticate(NonSASLAuthentication.java:109) atorg.jivesoftware.smack.XMPPConnection.login(XMPPConnection.java:239) atorg.jivesoftware.smack.Connection.login(Connection.java:353) 鉴权失败,不过至少不报KeyStore jks implementation not found的错误了。于是,继续看官方例子,寻找相关资料,结果修改代码如下: Java代码 connConfig.setReconnectionAllowed(true); connConfig.setSecurityMode(ConnectionConfiguration.SecurityMode.enabled); connConfig.setSASLAuthenticationEnabled(true); connConfig.setTruststorePath("/system/etc/security/cacerts.bks"); connConfig.setTruststorePassword("changeit"); connConfig.setTruststoreType("bks"); connection=newXMPPConnection(connConfig); 一运行,通过了,心里那个激动啊。。。 感谢博客园一位叫“没有代码”的哥们,给了我一些建议,受到了帮助和启发。 由于代码写的比较复杂,主要就是引用了比较多的类和接口,所以不贴出来了,因为很麻烦,这里介绍一些比较简单的例子: Java代码 connection.getAccountManager().createAccount(username,password);//创建一个用户 Java代码 roster.removeEntry(roster.getEntry(friendName));//删除某个好友 Java代码 roster.setSubscriptionMode(Roster.SubscriptionMode.accept_all); roster.createEntry(user,nickname,friends);//添加一个好友到朋友组上 Java代码 Collection<RosterEntry>entries=roster.getEntries(); for(Iterator<RosterEntry>entry=entries.iterator();entry.hasNext();){ RosterEntryre=entry.next();//获取所有好友 } 相关属性的介绍: 1、ConnectionConfiguration 作为用于与XMPP服务建立连接的配置。它能配置;连接是否使用TLS,SASL加密。 包含内嵌类:ConnectionConfiguration.SecurityMode 2、XMPPConnection. XMPPConnection这个类用来连接XMPP服务. 可以使用connect()方法建立与服务器的连接。disconnect()方法断开与服务器的连接. 在创建连接前可以使用XMPPConnection.DEBUG_ENABLED = true; 使开发过程中可以弹出一个GUI窗口,用于显示我们的连接与发送Packet的信息。 3、ChatManager 用于监控当前所有chat。可以使用createChat(String userJID, MessageListener listener)创建一个聊天。 4、Chat Chat用于监控两个用户间的一系列message。使用addMessageListener(MessageListener listener)当有任何消息到达时将会触发listener的processMessage(Chat chat, Message message) 5、Message Message用于表示一个消息包(可以用调试工具看到发送包和接收包的具体内容)。它有以下多种类型。 Message.Type.NORMAL -- (默认)文本消息(比如邮件) Message.Type.CHAT -- 典型的短消息,如QQ聊天的一行一行显示的消息 Message.Type.GROUP_CHAT -- 群聊消息 Message.Type.HEADLINE -- 滚动显示的消息 Message.TYPE.ERROR -- 错误的消息 Message有两个内部类: Message.Body -- 表示消息体 Message.Type -- 表示消息类型 6、Roster 表示存储了很多RosterEntry的一个花名册.为了易于管理,花名册的项被分贝到了各个group中. 当建立与XMPP服务的连接后可以使用connection.getRoster()获取Roster对象。 别的用户可以使用一个订阅请求(相当于QQ加好友)尝试订阅目的用户。可以使用枚举类型Roster.SubscriptionMode的值处理这些请求: accept_all: 接收所有订阅请求 reject_all:拒绝所有订阅请求 manual:手工处理订阅请求 创建组:RosterGroup group = roster.createGroup("大学"); 向组中添加RosterEntry对象: group.addEntry(entry); 7、RosterEntry 表示Roster(花名册)中的每条记录.它包含了用户的JID,用户名,或用户分配的昵称. 8、RosterGroup 表示RosterEntry的组。可以使用addEntry(RosterEntry entry)添加。contains(String user) 判断某用户是否在组中.当然removeEntry(RosterEntry entry)就是从组中移除了。getEntries()获取所有RosterEntry. 9、Presence 表示XMPP状态的packet。每个presence packet都有一个状态。 用枚举类型Presence.Type的值表示: available -- (默认)用户空闲状态 unavailable -- 用户没空看消息 subscribe -- 请求订阅别人,即请求加对方为好友 subscribed -- 统一被别人订阅,也就是确认被对方加为好友 unsubscribe -- 他取消订阅别人,请求删除某好友 unsubscribed -- 拒绝被别人订阅,即拒绝对放的添加请求 error -- 当前状态packet有错误 内嵌两个枚举类型:Presence.Mode和Presence.Type. 具体使用方法可参考前一篇文章中的Smack中文文档。 本文转自06peng 51CTO博客,原文链接:http://blog.51cto.com/06peng/963449,如需转载请自行联系原作者

优秀的个人博客,低调大师

JPDA 架构研究19 - JDI的连接模块

引入: 上文提到了JDI的Mirror机制,把整个目标虚拟机上的所有数据、类型、域、方法、事件、状态和资源,以及调试器发向目标虚拟机的事件请求等都映射成Mirror 对象。这里进一步讨论JDI的链接模块。 分析: 连接模块其主要目的是提供调试器(Debugger)到目标虚拟机(Target VM)之间的交互通道。 从连接的发起方来看:连接的发起方可以是调试器,也可以是目标虚拟机。 从连接的数量来看,一个调试器可以连接多个目标VM, 但是一个目标VM只可以连接一个调试器。 我们从调试器(Debugger)的角度,可以把连接分为主动连接和被动连接。 分类1:主动连接 (它表示调试器主动去连接Target VM) 又分两种情况: a. 当Target VM还没启动时,则使用LaunchingConnector这种形式的连接器,它会启动目标VM并连接。 Step 1: 调试器调用 VirtualMachineManager 的 launchingConnectors()方法获取所有的LaunchingConnector的实例。 1 2 3 4 5 6 7 public List<LaunchingConnector>launchingConnectors() { ArrayListlist= new ArrayList( 2 ); list.add( new SocketLaunchingConnectorImpl( this )); list.add( new SocketRawLaunchingConnectorImpl( this )); return list; } Step 2:根据传输方式或其他特征选择一个LaunchingConnector,调用其 launch() 方法启动并且连接目标虚拟机 。启动后,返回目标虚拟机的实例。 比如说,如果选用SocketLaunchingConnectorImpl,则它的launch()方法如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 public VirtualMachinelaunch(Map<String,? extends Connector.Argument>connectionArgs) throws IOException,IllegalConnectorArgumentsException,VMStartException { getConnectionArguments(connectionArgs); SocketListeningConnectorImpllistenConnector= new SocketListeningConnectorImpl( virtualMachineManager()); Mapargs=listenConnector.defaultArguments(); ((Connector.IntegerArgument)args.get( "timeout" )).setValue( 10000 ); Stringaddress=listenConnector.startListening(args); Stringslash=System.getProperty( "file.separator" ); StringexecString= this .fHome+slash+ "bin" +slash+ this .fLauncher; execString=execString+ "-Xdebug-Xnoagent-Djava.compiler=NONE" ; execString=execString+ "-Xrunjdwp:transport=dt_socket,address=" +address+ ",server=n,suspend=" +( this .fSuspend? "y" : "n" ); if ( this .fOptions!= null ){ execString=execString+ "" + this .fOptions; } execString=execString+ "" + this .fMain; String[]cmdLine=DebugPlugin.parseArguments(execString); Processproc=Runtime.getRuntime().exec(cmdLine); try { virtualMachine=(VirtualMachineImpl)listenConnector.accept(args); } catch (InterruptedIOExceptionlocalInterruptedIOException) { VirtualMachineImplvirtualMachine; proc.destroy(); Stringmessage=NLS.bind(ConnectMessages.SocketLaunchingConnectorImpl_VM_did_not_connect_within_given_time___0__ms_1, new String[]{ ((Connector.IntegerArgument)args .get( "timeout" )).value()}); throw new VMStartException(message,proc); } VirtualMachineImplvirtualMachine; virtualMachine.setLaunchedProcess(proc); return virtualMachine; } b.当Target VM已经启动时,则使用AttachingConnector这种形式的连接器,它会挂接到目标虚拟机上。 前提是,Target VM必须以以下方式启动 -agentlib:jdwp=transport=xxx,server=y 参数启动,并根据传输方式生成监听地址。 Step1:调试器启动,调用 VirtualMachineManager 的 attachingConnectors() 方法获取所有的AttachingConnector的实例。 1 2 3 4 5 public List<AttachingConnector>attachingConnectors() { ArrayListlist= new ArrayList( 1 ); list.add( new SocketAttachingConnectorImpl( this )); return list; Step 2: 根据目标虚拟机采用的传输方式选择一个AttachingConnector,调用其 attach() 方法挂接到目标虚拟机上。完成连接后,返回目标虚拟机的实例。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public VirtualMachineattach(Map<String,? extends Connector.Argument>connectionArgs) throws IOException,IllegalConnectorArgumentsException { getConnectionArguments(connectionArgs); Connectionconnection= null ; try { connection=((SocketTransportImpl) this .fTransport).attach( this .fHostname, this .fPort, this .fTimeout,0L); } catch (IllegalArgumentExceptione){ Listargs= new ArrayList(); args.add( "hostname" ); args.add( "port" ); throw new IllegalConnectorArgumentsException(e.getMessage(),args); } return establishedConnection(connection); } 分类2:被动连接(它表示Debugger被动地等待或者监听由Target VM发起的连接) 前提是,Target VM必须以以下方式启动 -agentlib:jdwp=transport=xxx,address=yyy 参数启动,并根据传输方式生成监听地址。 Step 1:调试器通过 VirtualMachineManager 的 listeningConnectors() 方法获取所有的ListeningConnector实例。 1 2 3 4 5 6 public List<ListeningConnector>listeningConnectors() { ArrayListlist= new ArrayList( 1 ); list.add( new SocketListeningConnectorImpl( this )); return list; } Step 2:调用ListeningConnector的 startListening() 方法让连接器进入监听状态。通过 accept() 方法通知连接器开始等待正确的入站链接,该方法将返回调试器正在监听的地址描述符;目标虚拟机会自动地 attach 到调试器上建立连接,然后返回目标虚拟机的实例。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 public StringstartListening(Map<String,? extends Connector.Argument>connectionArgs) throws IOException,IllegalConnectorArgumentsException { getConnectionArguments(connectionArgs); Stringresult= null ; try { result=((SocketTransportImpl) this .fTransport).startListening( this .fPort); } catch (IllegalArgumentExceptionlocalIllegalArgumentException){ throw new IllegalConnectorArgumentsException( ConnectMessages.SocketListeningConnectorImpl_ListeningConnector_Socket_Port, "port" ); } return result; } 本文转自 charles_wang888 51CTO博客,原文链接:http://blog.51cto.com/supercharles888/1588011,如需转载请自行联系原作者

优秀的个人博客,低调大师

【MSN Direct研究笔记】MSN Direct项目简介

提起MSN,大家首先想到的就是MSN Message即时通讯软件,其实MSN Message远不是MSN的全部,MSN的英文全称为Microsoft Server Network(微软网络服务),起源于1995年8月24日微软创建的因特网接入服务,其提供类似CompuServe及AOL的收费服务,如拨号上网、增值信息及聊天室等服务,同时也允许其他互联网用户通过因特网来使用。 而MSN Direct,则是由微软前总裁比尔盖茨在2003年提出的一种网络信息服务,它是通过FM信号来传输信息的一种技术(微软公司与SCA数据系统公司联合研发的DirectBand无线电技术)。 (2003年11月16日于拉斯维加斯的Comdex贸易展) 使用该项服务的首批设备是由Fossil和Suunto等公司制造的手表,再以后是能显示天气预报的咖啡壶,最近的产品是在北美有着广泛应用的GPS实时交通导航系统。 (2009年5月拍摄于西雅图MSN Direct部门展厅) 其核心技术架构如下: Garmin PND设备MSN Direct截图(如下图): 该设备可以接收交通、天气、油价、股票、新闻、本地信息等等内容,此外还可以订阅专属于个人相关的信息(如定制的新闻、股票等等)。 这时候也许有人会问,为什么在通信技术发达的今天,还要采用FM副载波技术这种相对比较老的技术,比如GPRS就是很好的技术(其实目前国内的一些PND公司就是采用了GPRS进行实时交通信息传输)。 理由如下: 1、 成本相对低廉。 2、 技术创新,特别是采用了LDPC技术,大大提高了通信成功率,有效地提高了带宽,为可靠传输大量实时的信息提供了技术保障。 3、 对交通实时信息来说,广播对点对点通信来说,更节省资源,符合目前时代发展的大趋势。 近几年来,由于采用了MSN Direct技术的PND设备,在北美地区得到比较好的应用和推广,所以目前该项技术也来到了中国,目前在台北和北京已经有条不紊的开展了试点工作。 MSN Direct包括各种软硬件、服务器技术: 硬件设备:由SCA数据系统公司提供DirectBand无线电技术和设备,美国国家半导体公司为SPOT产品提供芯片。 系统平台:PND系统 WINCE ;FM接收系统 .net Micro framework;服务器 windows Server 2008 R2 /Windows Server 2003 数据库:SQL2005 四大服务程序:C#语言开发 此外还有各式各样的开发和调试工具,所以要想熟练掌握MSN Direct技术,至少需要熟悉软硬件开发、通信、数据库等相关技术。 最近为了利于快速开发新的channels,一直在看MSN Direct系统的源码,发现其架构设计及技术实现细节都有不俗之处,值得深入钻研揣摩。所以今后也会针对于此,陆续写点这方面的技术心得。 (我的工作平台) 官方网站: http://www.msndirect.com/ 相关文章: 1、使用“智能手表”与您的 Outlook 日历保持连接 http://office.microsoft.com/zh-cn/outlook/HA011196242052.aspx 2、微软SPOT咖啡壶上市 用MSN Direct获知天气 http://tech.163.com/06/1117/08/304AOBKI000915BD.html 3、畅享网络资源!MSN Direct与GPS联姻 http://www.51gps.com/news/HTML/6052.html 本文转自yefanqiu51CTO博客,原文链接:http://blog.51cto.com/yfsoft/324238,如需转载请自行联系原作者

优秀的个人博客,低调大师

android中阿拉伯文研究

阿拉伯語系在文字處理上是我目前所知道最複雜的。阿拉伯文一些獨有的特性,導致其文字儲存時的編碼或在記憶體的原始 Unicode characters 序列,跟最後螢幕上看到的有很大的差異。 兩者最大的差異有: 順序不同 阿拉伯文的書寫(或顯示)順序是由右向左的 阿拉伯文字元序列間如果有數字或英文等左邊開始書寫的文字,這些左向右寫的文字,呈現時不能跟著阿拉伯字一起字序倒轉 單一字元最後顯示的形狀也不同 字型檔處理上,會針對最後螢幕上呈現的字元給與另一套獨立的編碼 這個獨立編碼,根據最新的 Unicode 標準,是不規範的,也就是由字型檔的創造者自行處理,可參考Generating Arabic Fonts 不過為了相容,Unicode 還是保留一組編碼作為這個用途,例如阿拉伯語專用的 Arabic Presentation Forms-B ,可參考Arabic characters in Unicode 可參看Arabic: 'source' Unicode to final display Unicode - Stack Overflow 阿拉伯文字,從記憶體中原始 Unicode 順序(memory representation in logical order),到最後螢幕呈現的結果(glyphs arrangement in visual order),中間的整個處理流程叫作造形(shaping),一般是顯示時由 rendering engine 處理的。 Arabic Shaping 可以區分成下列五部分: 書寫連接(Arabic Cursive Joining) 阿拉伯文只有書寫體(沒有印刷體或標準體),即使是印刷在紙上,或顯示在電腦上,都得考慮草寫連接問題 連接時,每個字元會因兩旁字元不同,而有不同形狀(glyphs),以應付不連,右連,左連,双連等情況 形狀重塑(Arabic Ligatures) 除了連接需求外,一些連續的特定兩個字元,會結合(ligature)成另一種形狀(glyph) 記號標注(Combining Marks) 用來標注重音等等 字序重排(Reordering) 處理右到左的書寫,及混合左到右書寫的情形 鏡像矯正(Mirroring) 針對大於小於及括號等因左右方向不同而有不同意義的字元作修正 前三者要依序處理。字序重排及鏡像矯正可以最先處理或最後處理,但會因先後處理不同會影響到前三項處理的細節。完整的字序重排及鏡像矯正說明可以參閱UAX #9: Unicode Bidirectional Algorithm。 網路上可以找到的 source code 如下: Arabic Support for Windows CE How to support Arabic text in Android? - Stack Overflow harfbuzz-arabic.c 其中, Android 版是 CE 版的改寫,但這兩支程式都有個問題,就是沒考慮到 Combining Marks ,遇到 Transparent Joining Types 的字元時,就會出錯,這很容易遇到。第三支程式應該比較完整,但它太龐雜了,有耐心的話可以慢慢啃 。建議直接參考Unicode6.1.0/ch08.pdf的 8.2 Arabic 這個章節,針對會遇到的部份,自己重寫比較直接。 如果要處理的文字只有阿拉伯語(不含其他阿拉伯語系的文字,例如波斯、埃及等),那只要處理 Arabic Block 中,也有在ISO/IEC 8859-6列出的部份。對應的 glyphs 都可以在 Arabic Presentation Forms-B 找到。 要完整處理整個阿拉伯語系,那勢必得直接採用下列資料: ArabicShaping.txt DerivedJoiningGroup.txt DerivedJoiningType.txt 其他值得參考的資料如下: Template:Arabic alphabet shapes/joining What you need to know about the bidi algorithm and inline markup Right-To-Left Text in Markup Languages 本文转自xyz_lmn51CTO博客,原文链接:http://blog.51cto.com/xyzlmn/1230808 ,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册