概述

基于Java,将pdf转成单一的tiff文件。

MAVEN依赖

以下是依赖在maven中心仓库中可以找到

<groupId>com.sun.media</groupId>
    <artifactId>jai_codec</artifactId>
    <version>1.1-mr</version>
</dependency>
<dependency>
    <groupId>javax.media</groupId>
    <artifactId>jai_core</artifactId>
    <version>1.1-mr</version>
</dependency>
<dependency>
    <groupId>com.sun.medialib</groupId>
    <artifactId>mlibwrapper_jar</artifactId>
    <version>1.1</version>
</dependency>
<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>2.0.0-RC2</version>
</dependency>

实现

类图

https和http

类属性和方法简介

  • Pdf2TiffConstant

IMG_FORMAT :默认的图片格式

DPI :默认的转换精度

  • Pdf2TiffUtil

public static pdf2Tiff (is: InputStream, os: OutputStream): void

将指定的pdf转成单一tiff文件,写到指定的输出流。参数is提供pdf文档的内容,参数os指定输出流。

代码

  • Pdf2TiffConstant
package cn.ljl.javaweb.demo.pdf2tiff;
public class Pdf2TiffConstant {
    /** 图片格式 */
    public static final String IMG_FORMAT = "tiff";
    /** 打印精度设置 */
    public static final int DPI = 160; //图片的像素
}
  • Pdf2TiffUtil
import static cn.ljl.javaweb.demo.pdf2tiff.Pdf2TiffConstant.DPI;
import static cn.ljl.javaweb.demo.pdf2tiff.Pdf2TiffConstant.IMG_FORMAT;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import javax.media.jai.JAI;
import javax.media.jai.PlanarImage;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import com.sun.media.jai.codec.ImageCodec;
import com.sun.media.jai.codec.ImageEncoder;
import com.sun.media.jai.codec.TIFFEncodeParam;

public class Pdf2TiffUtil {
    /**
     * 从输入流读取pdf,转化为tiff后写入输出流.<br/>
     * 参考列表:
     * <ol>
     * <li><a href=
     * "http://www.coderanch.com/t/497492/java/java/Convert-PDF-files-Tiff-files"
     * >Convert PDF files to Tiff files</a></li>
     * <li><a href=
     * "http://www.oracle.com/technetwork/cn/java/javaee/downloads/readme-1-1-2-137176.html"
     * >Java(TM) Advanced Imaging API README</a></li>
     * </ol>
     *
     * @param is
     *            输入流,提供pfg内容.
     * @param os
     *            输出流.
     */
    public static void pdf2Tiff(InputStream is, OutputStream os) {
        PDDocument doc = null;
        try {
            doc = PDDocument.load(is);
            int pageCount = doc.getNumberOfPages();
            PDFRenderer renderer = new PDFRenderer(doc); // 根据PDDocument对象创建pdf渲染器

            List<PlanarImage> piList = new ArrayList<PlanarImage>(pageCount - 1);
            for (int i = 0 + 1; i < pageCount; i++) {
                BufferedImage image = renderer.renderImageWithDPI(i, DPI,
                        ImageType.RGB);
                PlanarImage pimg = JAI.create("mosaic", image);
                piList.add(pimg);
            }

            TIFFEncodeParam param = new TIFFEncodeParam();// 创建tiff编码参数类
            param.setCompression(TIFFEncodeParam.COMPRESSION_DEFLATE);// 压缩参数
            param.setExtraImages(piList.iterator());// 设置图片的迭代器

            BufferedImage fimg = renderer.renderImageWithDPI(0, DPI,
                    ImageType.RGB);
            PlanarImage fpi = JAI.create("mosaic", fimg); // 通过JAI的create()方法实例化jai的图片对象

            ImageEncoder enc = ImageCodec.createImageEncoder(IMG_FORMAT, os,
                    param);
            enc.encode(fpi);// 指定第一个进行编码的jai图片对象,并将输出写入到与此
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (doc != null)
                    doc.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

参考索引

  1. Convert PDF files to Tiff files

  2. Java(TM) Advanced Imaging API README

Https和Http

Https和Http的区别

1、Https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。

2、Http是超文本传输协议,信息是明文传输,Https则是具有安全性的ssl加密传输协议。

3、Http和Https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。

4、Http的连接很简单,是无状态的;Https协议是由SSL+Http协议构建的可进行加密传输、身份认证的网络协议,比Http协议安全。

网站是否需要采用Https加密

如果你的网站属于电子商务、金融、社交网络等领域的话,那最好是采用Https协议;如果是博客站点、宣传类网站、分类信息网站、或者是新闻网站之类的话,大可不必跟风而行,毕竟Https协议不仅耗钱,浪费精力,而且暂时也不利于网站的SEO工作。总而言之,切勿为了排名而盲目跟风,网站优化的首要目标是用户,用户喜欢,好排名就不会那么难了!

Http的误区

1.Https无法缓存

其实只要头命令中有Cache-Control: Public,缓存就会被写到硬盘上。

2.SSL证书很贵

如果你在网上搜一下,就会发现很多便宜的SSL证书,大概10美元一年,这和一个.com域名的年费差不多。而且事实上,还能找到免费的SSL证书。 在效力上,便宜的证书当然会比大机构颁发的证书差一点,但是几乎所有的主流浏览器都接受这些证书。

3.Https站点必须有独享的IP地址

由于IPv4将要分配完毕,所以很多人关心这个问题。但是,如果你使用子域名通配符SSL证书,就能在一个IP地址上部署多个Https子域名。比如,

Https://www.Httpwatch.com和Https://store.Httpwatch.com,就共享同一个IP地址。

4.转移服务器时要购买新证书

很多服务器,如IIS,也支持证书的导入导出,所以转移服务器时并不需要购买新证书

5.Https太慢

第一次打开网页的时候,Https协议会比Http协议慢一点,这是因为读取和验证SSL证书的时间。但是,一旦有效的Https连接建立起来,再刷新网页,两种协议的速度几乎没有区别。而且也有很多方法可以加快网页的速度,如:压缩文本内容。

6.有了Https,Cookie和查询字符串就安全了

虽然无法直接从Https数据中读取Cookie和查询字符串,但是仍然改变Cookie值从而劫持其他人的session id。至于查询字符串,也可以通过类似方式query-strings-over-Https/)泄漏。

7.只有注册登录页,才需要Https

以Twitter为例,它的登录页使用了Https,但是登录以后,其他页面就变成了Http。这时,它的cookie里的session值就暴露了。也就是说,这些cookie是在Https环境下建立的,但是却在Http环境下传输。如果有人劫持到这些cookie,那他就能以你的身份在Twitter上发言了。

参考资料

1.Https的七个误解 Http://blog.Httpwatch.com/2011/01/28/top-7-myths-about-Https/

2.Http与Https的区别 Http://www.mahaixiang.cn/internet/1522.html

如何看待算法

一个算法如果不会用,其实也不用学了,反正学完也会忘记。所以学习算法最关键的不是怎么写,而是为什么要用,什么时候用,什么时候不该用。等到需要用这个算法的时候,再去google、baidu查就可以了。

名词介绍

比较(Compare)和交换(Swap)

比较:两个字符的大小比较

交换:两个字符的位置交换

O(N)

N代表数据量

大O符号:代表上界

除此之外还有,

大Ω符号:代表下界

大Θ符号:代表上界跟下界刚好相等

但算法上我们通常只在乎 O (读音 Big O)。毕竟 Ω 这种最少需要花费多少时间/空间,并不是我们所关心的。

时间复杂度和空间复杂度

时间复杂度

算法的时间复杂度也就是算法的时间量度,记作T(n)=O(f(n)),T(n)是语句总的执行次数也可以称为执行时间,f(n)是问题规模n的某个函数,算法执行时间T(n)的增长率和f(n)的增长率相同

int i,sum=0,n=100 ;//执行1
for(int i=1;i<n;i++){//执行了n+1
    sum=sum+i; //执行n
}

以上总的执行次数:1+n+1+n可推导该时间复杂度为:O(n)

空间复杂度

计算除正常占用内存开销外的算法所需要的存储空间,记作S(n)=O(f(n)),n为问题的规模,f(n)语句关于n所占的存储空间的函数。

注意:O(N) 在超过一定规模时候,基本上这个算法花费的时间(或是空间)会跟数据量N成正相关。也就是说如果N增加 3 倍,花费的时间/空间也会增加3倍。

最坏(Worst)/平均(Average)情况

平均情况就是我们期望的合理运行时间

最坏情况就是出现最糟糕情况的运行时间

例如:查找一个有n个随机数字数组中的某个数字,最好的情况就是第一个数字,即O(1),最坏的情况就是最后一个数字,即O(n)。

稳定排序

待排序的记录序列中可能存在两个或两个以上关键字相等的记录。排序前的序列中Ri领先于Rj(即i<j),若在排序后的序列中Ri仍然领先于Rj,则称所用的方法是稳定的。

平均分布

数据平均在某个范围,数据的变动范围不大

常用算法的使用场景浅谈

排序算法

1.冒泡排序(Bubble sort):

时间复杂度: O(N2次方)

Bubble sort不适合的情况:

几乎所有的正常状况都不适合的情况

Bubble sort适合的情况:

也许小数据量,可以考虑用改良过的 Bubble sort

2.插入排序(Insertion sort):

时间复杂度: O(N2次方)

Insertion sort不适合的情况:

数据量稍大(或许超过100)

Insertion sort适合的情况:

  • 小数据量 (约几十个)直接用Insertion

  • 已经快要排好的 Array 可以接近 Best 情况 O(N)

3.选择排序(Selection sort):

时间复杂度: O(N2次方)

Selection sort不适合的情况:

数据量稍大(或许超过100)

Selection sort适合的情况:

  • Selection 是所有排序里面 swap 次数最少的,所以当 swap 代价很高的时候,例如:

    • 每次 swap 要刷新窗口或重新画图

    • 每次 swap 要 swap 数百Mb(兆)的 data

    • 每次 swap 要去 database 记录一次 log(日记)

注1:实际测试数据:如果N=200,且每次 swap 就要刷新,Selection sort 大概比 Quick sort 快 80% ~ 100%)

注2:但N 太大的时候可能抵消 Selection 的优势,要自行斟酌

4.快速排序(Quick sort):

没有其它排序算法适合的情况的情况下的选择

时间复杂度: O (NlgN)

quick sort不适合的情况:

  • 几乎已经排好序的数组

  • Array data 接近反向排列

  • 需要保证稳定排序的状况

quick sort适合的情况:

  • 绝大部分的状况

  • 多种编程语言提供了quick sort的方法,如:java中Arrays.sort()对基本类型排序时如果数量大于7则就是使用快速排序

5.堆排序(Heap sort):

正常情况下比基本上比 Quick sort 要慢

时间复杂度: O (NlgN)

Heap sort不适合的情况:

  • 需要保证稳定排序的状况

Heap sort适合的情况:

建议在优先队列里使用,原因如下:

  • Heap 建立好之后,取出一个 max/min 只需要 O(lgN) 的时间

  • Insert 一次也只需要 O(lgN) 的时间

  • 在常变动的环境下,随时想要取得【目前最大 K 个 value】

6.归并排序(Merge sort)

对大数据量进行排序,数据量大到不能全部读进内存里,必须在内存和外存间换进换出进行排序。Merge sort 速度仅次于 Quick sort

时间复杂度: O (NlgN)

空间复杂度: O (N)

Merge sort不适合的情况:

在内存紧缺情况同时数据量不多

Merge sort适合的情况:

  • 需要稳定排序

  • 需要要 merge 两个/多个 sorted list (有序列表)

  • 数据量极大,内存一定不够时 ,Merge sort 可以当作外部排序,每次只读取两个 lists 的前面一小段

  • 平行运算(同时使用多台计算资源解决计算问题的过程)

7.基数排序(Radix sort):

K表示最大的数的位数,N表示多少个数

时间复杂度: O(KN)

空间复杂度 O(K+N)

Radix sort不适合的情况:

  • K 没有比 N 小多少 (例如:排序 DNA / RNA就不适合了)

  • 位数(长度)变动太大的 data

  • Data 每个位数变化太多 ,如:中文姓名

  • 数字排序运算上有太多的 % 跟 *

Radix sort适合的情况:

  • 数据量多,且固定格式的文字数字 (例如身份证号,邮编,手机号码)

  • 数据量多,长度差不多的文字、数字 (英文单字)

8.桶子排序(Bucket sort):

用 N 个数字,K 个桶子表示

Best & Average 情况: O(K+N)

Worst 情况: O(N2次方)

Bucket 不适合的情况:

  • 分布很不平均 (例如:学生成绩为就是平均分布)

  • 对空间要求较高 (Bucket sort 非常耗费控件)

  • M 型分布

Bucket 适合的情况:

  • 分类 (例如要把 e-mail 按照 domain 分开),但这好像不算排序

  • 平均分布时速度极快

9.计数排序(Counting sort):

花费时间为: O(N+K)

Counting 不适合的情况:

  • 非数字

  • 大范围数字 (需要超大的 counting array)

  • 对空间要求较高 (需要额外 array 储存 counting 以及排序结果)

Counting 适合的情况:

  • 小范围数字

实战例子:

例子 选择的排序
50个 e-mail address 选insertion sort或现成的qsort,才50个没必要浪费时间写复杂的算法
5000万个 e-mail address 选merge sort,感觉上memory是不够的
100万个 高考成绩 选counting sort,数字范围不大(0-150)
3000 个地址 选现成的 qsort,如果是 300万的地址我才选 bucket sort(县、城市)
50000 个身份证号 还是选现成的 qsort,数量更多些我才选 radix sort
Swap 代价很高 数量不大的话,选 Selection sort;数量大的话,我选现成的 qsort

查找算法

Average 情况: O(N)

quential search 适合的情况:

小数据量(几十、几百)

Average 情况: O(lgN)

binary search适合的情况:

  • 大数据量(几千万以下),且已经排序好

  • 不经常变动而查找频繁

分块查找是折半查找和顺序查找的一种改进方法,需要对数组进行分块,分块查找需要建立一个“索引表”。索引表分为m块,每块含有N/m个元素,块内是无序的,块间是有序的,例如块2中最大元素小于块3中最小元素。

Average 情况: O(log(m)+N/m)

block search适合的情况:

  • 大数据量(几千万以下),且块间是有序

  • 节点动态变化(当增加或减少节以及节点的关键码改变时,只需将该节点调整到所在的块即可),但变化不频繁。

Average 情况: O(1)

hash search适合的情况:

  • 大数据量(几千万以下),且杂乱无排序
5.数据库(Database)

数据库主要是存储数据用,在数据库查找数据主要是通过sql来筛选

Database适合的情况:

  • 结构化的数据,数据量最好不要超过百万
6.搜索引擎(Search engine)

Search engine适合的情况:

  • 极大的数据量(几千万,几亿)

常见的时间复杂度

时间复杂度

文章所提及的算法的baidu地址

排序算法插入排序选择排序

快速排序堆排序归并排序

基数排序桶排序计数排序

哈希查找顺序查找二分查找分块查找

参考资料

1.翁嘉颀-Algorithm算法精讲视频