确保所有字体嵌入,是生成高质量学术论文的必要条件。但是在Windows下,总会遇到Matlab或Visio生成字体没有嵌入的问题,当然这个问题的解决办法有很多(例如,对于Visio可以这样做:直接拷贝到Adobe Illustrator(AI)中,另存为eps(选择为“为其他程序嵌入字体”)),这里介绍一种批量式的解决方法。看到有网友介绍,可以用GhostScript来进行来回转换。安装好GhostScript后,在其安装文件夹下的bin目录下,会有gswin64c.exe这个可执行程序(我这里是64位系统,32位系统对应的就是gswin32c.exe),把没有字体嵌入的eps文件拷贝至该目录下,运行:
gswin64c.exe -dNOPAUSE -dBATCH -dEPSCrop -q -sDEVICE=pdfwrite -dCompatibilityLevel#1.3 -dPDFSETTINGS=/prepress -dSubsetFonts=true -dEmbedAllFonts=true -sOutputFile=temp.pdf xxxx.eps
其中xxxx.eps就是需要转换的eps文件,这样生成了一个临时的temp.pdf文件,我们再运行下面的命令将临时pdf文件转为eps文件:
gswin64c.exe -q -dNOPAUSE -dBATCH -dNOCACHE -sDEVICE=epswrite -sOutputFile=yyyy.eps temp.pdf
其中yyyy.eps就是嵌入字体后的eps文件,通过这种方法,就可以将所有eps实现字体嵌入了。这样做固然方便,但是如果有很多文件需要处理,那手工运行命令还是挺复杂的。这里我提供一段简单的Java代码,我们可以将需要处理的eps文件都放在一个文件夹内,将文件夹拷贝到刚才说的bin目录下,在cmd方式下运行这段Java代码,可以批量实现转换(转换后的eps文件就在bin目录下,和原始文件文件名相同,但位置不同,这样可以方便LaTeX不进行任何修改就可以重新生成PDF)
import java.io.File; import java.io.IOException; public class gsBatch { public static void main(String[] args) { if(args.length!=1) { System.out.println("Usage: java gsBatch *Floder-to-handle*"); System.exit(0); } String absoluteStartPath = System.getProperty("user.dir"); File file = new File(absoluteStartPath+"\\"+args[0]); gsBatch t = new gsBatch(); t.dotGenerator(file); } private void dotGenerator(File file) { // TODO Auto-generated method stub File[] fileList = file.listFiles(); int i=0; while(i<fileList.length){ if (fileList[i].isDirectory()==true){ dotGenerator(fileList[i]);//使用递归方法对所有子目录分析 } else if (fileList[i].getName().contains(".eps")){ String relativePath = file.getPath(); String commandConvertPDF = new String("cmd /c gswin64c.exe -dNOPAUSE -dBATCH -dEPSCrop -q -sDEVICE=pdfwrite -dCompatibilityLevel#1.3 -dPDFSETTINGS=/prepress -dSubsetFonts=true -dEmbedAllFonts=true -sOutputFile=temp.pdf \""+relativePath+"\"\\"+fileList[i].getName()); System.out.println(commandConvertPDF); String commandConvertEPS = new String("cmd /c gswin64c.exe -q -dNOPAUSE -dBATCH -dNOCACHE -sDEVICE=epswrite -sOutputFile="+fileList[i].getName()+" temp.pdf"); try { Runtime.getRuntime().exec(commandConvertPDF); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } try{Thread.sleep(1000);} catch(Exception e){} try { Runtime.getRuntime().exec(commandConvertEPS); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } try{Thread.sleep(1000);} catch(Exception e){} } i++; } } }
通过这种方法,就可以批量处理eps文件了(如果不会编译Java,则不用去考虑这种方法),最终生成的PDF文件可以用Acrobat等软件打开——文件——属性——字体,如果所有字体都显示“已嵌入子集”,则说明已经成功嵌入所有字体了。
我们在开发视频直播或者监控类项目的时候,如场馆监控、学校监控、车载监控等等,往往首先希望的是形成一个项目的雏形,然后再在这个框架的基础上进行不断的完善和扩展工作,那么我们今天要给大家介绍的就是,如何形成一个这样的框架:
采集本地音视频数据(Win) -->视频分发服务器-->客户端随意接入
大致流程:我们首先通过DShow采集Windows(XP、Win7经过测试)主机的视频设备(Camera)和音频设备(Mic)的音视频资源,经过live555的RTSP推送流程和RTP封包过程,将直播数据推送给Darwin分发服务器,Darwin分发服务器接收live555的推送数据并做相应的缓存(超过缓存时间的数据将会被移除),同时响应客户端的接入,将推送来的直播数据转发给客户端。
设备采集端:采集端是以live555为基础框架,以DarwinInjector做为与Darwin交互的接口,再在live555 Source端分别实现CamH264VideoStreamFramer(H264视频)和AudioInputMicDevice(AAC音频)的数据源。
当然,在采集和发送数据之前,我们需要进行的是与Darwin服务器之间的信令通道交互,这里我们采用的是RTSP标准的Announce(SDP payload)、Setup、Play过程,让Darwin服务器端建立转发类(主要是在QTSSReflectorModule中),等待RTP数据的推送。
设备采集端代码:http://pan.baidu.com/share/link?shareid=2213287549&uk=3693441883
转发服务器:转发服务器是RTSP服务器Darwin Streaming Server,在之前的博客:基于DSS的推送式转发已经描述了RTSP标准推送流程,这里只说明一点小小的修改,就是在Darwin中,当设备端意外断线,也就是不经过标准的RTSP Teardown流程就与服务器断开的话,服务器端将会等待设备推送超时才会释放转发资源,那么对于这一点,我们做了一个小小的更改,这个在:Darwin推送端断开的处理问题中已经描述了。那么最新代码的下载可以到EasyDarwin开源项目中去获取:https://github.com/xiejiashu/EasyDarwin,后续对Darwin的扩展,如分布式RTSP服务器、RTSP直播服务器、服务器端录像、Hint模块等功能,都会在这个开源项目中加入,希望有兴趣的朋友加入到这个开源项目组中来。
客户端端:客户端当然不用太多描述,标准的RTSP流播放器都能播放Darwin视频,不过如果有想开发RTSP客户端的朋友,也可以加入到讨论群中(288214068)。
框架扩展:在上述的流程中,我们是在采集程序一开启时,就开始向Darwin服务器推送数据,那么在通常情况下,点播或者直播通常都是On Demand的形式,就是说,只有有需要的时候,我们才推送视频给服务器,没有需要的时候,设备处在空闲状态的,那么我们可不可以在上述的框架上做到这一点呢?当然可以!
如上图,我们可以先在设备端,开启一条tcp通道,连接到Darwin服务器,Darwin服务器中扩展一个管理模块,专门管理与设备的通信与接入,这样,在服务器不需要设备数据的时候,只与设备保持信令通道的连接和畅通就可以了,当有需要设备当前音视频数据的时候,就通过这条信令通道发送开启命令,采集设备收到命令(自定义命令),就开始本地采集、编码、打包和RTP传输流程,RTP通道可以与信令通道公用也可以单独建立,不过建议还是单独建立的好。当服务器端对此设备分发的客户端数量为0或者其他更高级的需求来到时,可以通过信令通道,发送停止命令到采集设备,这样采集设备就停止本地采集、编码等工作,进入最开始时候的空闲等待状态。如此,就实现了实时视频的点播效果。当然,
本篇博客由hibernate核心接口说起,把它当做引子,从而引出自己对接口的亲身感受。
业务逻辑层
是hibernate2.0的东西,因为有侵入性,所以逐渐被淘汰或者说是另辟蹊径。如果想要Lifecycle的功能,完全可以使用Interceptor取而代之。
侵入性也就是要求我们必须继承些hibernate的东西,而java是单继承,所以具有侵入性的类扩展性不好,这就是常说的,鼓励pojo(plain ordinary java object)编程。
Configuration
概述:Configuration 类负责管理Hibernate 的配置信息。它包括如下内容:
Hibernate运行的底层信息:数据库的URL、用户名、密码、JDBC驱动类,数据库Dialect,数据库连接池等。
Hibernate映射文件(*.hbm.xml)。
Hibernate配置的两种方法:
属性文件(hibernate.properties),原始。
调用代码:Configuration cfg = new Configuration();
Xml文件(hibernate.cfg.xml)。
调用代码:Configuration cfg = new Configuration().configure();
SessionFactory
概述:
应用程序从SessionFactory(会话工厂)里获得Session(会话)实例。它在多个应用线程间进行共享。通常情况下,SessionFactory的创建非常消耗资源,整个应用一般只要一个SessionFactory就够了,只有多个数据库的时候才会使用多个SessionFactory。
会话工厂缓存了生成的SQL语句和Hibernate在运行时使用的映射元数据。
调用代码:
SessionFactory sessionFactory = cfg.buildSessionFactory();
说明:SessionFactory由Configuration对象创建,所以每个Hibernate配置文件,实际上是对SessionFactory的配置
Session(会话)
概述:
Session不是线程安全的,所以一般一线程一session。它代表与数据库之间的一次操作。
Session也称为持久化管理器,因为它是与持久化有关的操作接口。
Session通过SessionFactory打开,事务提交后就该关闭,否则再使用可能会发生问题。
它与Web层的HttpSession没有任何关系。
Session和事务应该能够统一管理。(Spring为Hibernate提供了非常好的支持)
调用代码
Session session = sessionFactory.openSession();
Query(查询)
允许你在数据库上执行查询并控制查询如何执行。
Configuration、SessionFactory、Session、Transaction接口配合使用实现jdbc中的insert操作。
这是在上篇博客——学习ORM框架—hibernate(一):初识hibernate基础之上进行的,上篇博客已经由Object映射到了Relation,也就是说数据库表已经建立。
public static void testSave(String[] args) { //读取hibernate.cfg.xml文件 Configuration cfg = new Configuration().configure(); //建立SessionFactory SessionFactory factory = cfg.buildSessionFactory(); //取得session Session session = null; try { session = factory.openSession(); //开启事务 session.beginTransaction(); User user = new User(); user.setName("张三"); user.setPassword("123"); user.setCreateTime(new Date()); user.setExpireTime(new Date()); //保存User对象 session.save(user); //提交事务 session.getTransaction().commit(); }catch(Exception e) { e.printStackTrace(); //回滚事务 session.getTransaction().rollback(); }finally { if (session != null) { if (session.isOpen()) { //关闭session session.close(); } } } } }
其中Session session = factory.openSession();
watch下factory.openSession()的结果为:"factory.openSession()"= SessionImpl (id=63)。
可见得到的结果为session接口的实现SessionImpl,也就是父类引用指向了子类对象。
Session接口可以有多种实现,其中SessionImpl就是hibernate做的实现,如果想要使用SessionImpl2,只需修改配置文件这么简单,这就是最常用的抽象工厂,如果这点不清楚,请参见反射机制剖析(一):谈谈工厂家族、反射机制剖析(二): 利用抽象工厂实现BeanFactory。
当时几乎所有要厂商都推出了、或是正在赶制自己的应用服务器产品,但这个“应用服务器”究竟应该是什么东西,竞争者们又各有表述、莫衷一是。而sun‘公司却制定了j2ee规范,从而各项分支技术在这个领域中的地位和作用得到了客观、准确的定义。所以,sun非常具有远见卓识的,值得钦佩和学习。
一个java程序既可以部署在jboss,也可以部署在bean weblogic,因为他们都实现j2ee规范,或者说实现了相同的接口。
一个老生常谈的例子就是JDBC。
很多人费解:既然我每连接一种数据库(如mysql)都要事先部署驱动程序,那我直接访问驱动程序不就行了?还
要JDBC干吗?
实际上,JDBC已经起了至关重要的作用了:正因为驱动程序是按照JDBC所规定的方法编写的,你才可以按照