1.【问题背景】
1.1最近写了一个大数据的小练习,感觉那个有点用,就想导出PDF去打印
然后问题来了:导出的PDF不显示中文!!!(可惜那一块多钱)。然后探索的过程就开始了
1.2 一有问题当然是先问度娘了,找了一波后发现可以通过命令提示符(CMD)以命令的方式创建创建出pdf,这就很灵性了。
虽然直接在Jupyter Notebook里可以更简单地直接导出PDF,
但是对于希望在PDF里显示中文的同学来说,能够方便一点导出pdf文件的话,何乐而不为嘞
2.【基本过程】
2.1 我找的解决方案挺简单的,大概分三步:a): 一条命令通过source.ipynb文件生成source.tex文件
b): 用编辑器打开source.tex,在指定位置添加文本
c):一条命令通过source.tex文件生成一系列文件,这里面就包括了source.pdf
d):上面的处理方式都是通过Java实现,在控制台运行指令也是通过Java调用的(真好玩)
嘿嘿,听起来挺简单的,写着写着你会发现还真的挺简单的,还有一点瓜
3.【操作环境以及相关准备】
3.1 win10+IDEA+jdk8+anaconda+Jupyter Notebook+MikTeX+Pandoc+JavaFx(SceneBuilder)
3.2 要通过Jupyter Notebook转PDF的话要用MikTeX和Pandoc,MikTeX需要配置环境
3.3 MikTeX下载地址:https://miktex.org/download
Pandoc下载地址:https://github.com/jgm/pandoc/releases/tag/2.3.1
3.4 把MikTex添加到系统环境变量里
4.【Java控制台实现方式】
4.1 介绍:最初就是写了一个控制台程序,然后为了能够成功导出PDF就一直在堆代码,最后就是成功导出PDF
4.2 代码:因为一开始就是为了写功能而写代码,所以感觉把这个写死了,因为测试就是针对一个文件来写的,不过问题不大,后面我又写了一个JavaFx的
相关注释我都写在里面了
1 import java.io.*;
2
3 public class Main {
4
5 private static String path = "D:\\JupyterNotebook";
6 private static File sourceFile = new File("D:\\JupyterNotebook\\pandas_test.tex");
7
8 public static void main(String[] args) throws IOException, InterruptedException {
9 for (int i = 0; i < args.length; i++) {
10 System.out.println(args[i]);
11 }
12 change2Tex();
13 File bufferFile = createTexFile(); //获取创建的文件对象
14 delay() ; //延时
15 modifyTex(bufferFile); //修该Tex文件
16 change2PDF(); //将Tex文件转化成PDF文件
17 }
18
19
20 /**
21 * 延一个时,
22 * java建文件比命令提示符快
23 *
24 * @throws InterruptedException
25 */
26 public static void delay() throws InterruptedException {
27 for (int i = 0; i < 4; i++) {
28 Thread.sleep(1000);
29 }
30 }
31
32 /**
33 * 通过简单的命令
34 * 将文件转化为tex文件
35 * 执行cmd
36 *
37 * jupyter nbconvert --to latex yourNotebookName.ipynb
38 * 将文件里 \documentclass[11pt]{article}后面加上下面这三行
39 * \\usepackage{fontspec, xunicode, xltxtra}
40 * \\setmainfont{Microsoft YaHei}
41 * 将latex转化为pdf
42 * xelatex yourNotebookName.tex
43 */
44 public static void change2Tex() throws IOException {
45
46 Runtime runtime = Runtime.getRuntime();
47 String cmd = "cmd /k start jupyter nbconvert --to latex " + path + "\\pandas_test.ipynb"; //cmd指令,cmd /k start + 指令,运行五玩了指令就关闭cmd
48 System.out.println(cmd);
49 System.out.println(path);
50 runtime.exec(cmd);
51 }
52
53 /**
54 * 将tex文件转化成pdf文件
55 *
56 * @throws IOException
57 */
58 public static void change2PDF() throws IOException {
59 Runtime runtime = Runtime.getRuntime();
60 String cmd = "cmd /k start xelatex afterInsertText.tex";
61 runtime.exec(cmd, null, new File(path));//注意这里:exec里有三个参数,这个方法可以指定在path文件夹打开cmd,然后运行cmd指令
62 }
63
64 /**
65 * 创建Tex文件
66 *
67 * @return
68 * @throws IOException
69 */
70 public static File createTexFile() throws IOException {
71
72 File tempFile = new File("D:\\JupyterNotebook"); //判断这个文件夹在不在
73 if (!tempFile.exists()) {
74 tempFile.mkdir();
75 }
76
77 File bufferTopTex = new File("D:\\JupyterNotebook", "afterInsertText.tex"); //判断这个文件在不在
78 if (!bufferTopTex.exists()) { //不在的话创建文件,
79 bufferTopTex.createNewFile();
80 }
81 //在后面会把源.tex文件要修改的位置前面的数据写到下面这个文件(虽然下面是个对象,意思应该能懂)里面,
82 // 然后接着在后面添加文本,最后把源tex剩下的数据写到这个文件里
83 return bufferTopTex;
84 }
85
86 /**
87 * 文件读写,在文件后面添加需要添加的指令
88 *
89 * @throws IOException
90 */
91 public static void modifyTex(File file) throws IOException {
92
93 RandomAccessFile topTex = new RandomAccessFile(file, "rw"); //在本地创建的afterInsertText.tex文件
94
95 RandomAccessFile raf = new RandomAccessFile(sourceFile, "rw"); //获取源.tex文件
96
97 String line;
98
99 //在下面是对readLine()取到的数据进行转码,这是一个解决乱码的好方式
100 //注意在下面每用一次readLine(),那个指向行号的指针就会向下移动一次,和ResultSet里的rs.next()有点像
101 while ((line = new String(raf.readLine().getBytes("ISO-8859-1"), "utf-8")) != null) {
102 topTex.write(("\n" + line).getBytes());
103 if (line.equals("\\documentclass[11pt]{article}")) {
104 topTex.write((" \n\\usepackage{fontspec, xunicode, xltxtra}").getBytes());
105 topTex.write(("\n\\setmainfont{Microsoft YaHei}").getBytes());
106 topTex.write(("\n\\usepackage{ctex} ").getBytes());
107 break;
108 }
109 }
110
111 while (true) {
112 final String temp;
113 if ((temp = raf.readLine()) == null) {
114 break;
115 } else {
116 line = new String(temp.getBytes("ISO-8859-1"), "utf-8");
117 topTex.write(("\n" + line).getBytes());
118 }
119 }
120 }
121 }
4.3 运行结果:emmmmmmm,这个运行完了就自己关掉了,不好截图,看看其他的吧
4.3.1 只有一个.ipynb文件:
然后运行一下程序:
先是Java程序生成的afterInsertText.tex文件
然后接着运行到结束就会生成这些文件,可以看到pdf自动生成了
最后看一眼有没有中文:
-----------------可以看出,上面的pdf是有中文的,成功-----------------
Tip_1:在这里给出要用到的cmd命令:
1.jupyter nbconvert --to latex yourNotebookName.ipynb
2.将文件里 \documentclass[11pt]{article}后面加上下面这三行
\usepackage{fontspec, xunicode, xltxtra}
\setmainfont{Microsoft YaHei}
\usepackage{ctex}
3.将latex转化为pdf: xelatex yourNotebookName.tex
Tip_2:
在Java里输出反斜杠要用两个,英文点号 ......要用 \\.