现在的位置: 首页 > 综合 > 正文

Latex 书签中文乱码解决方案

2012年12月24日 ⁄ 综合 ⁄ 共 2016字 ⁄ 字号 评论关闭

Latex 书签中文乱码解决方案

作者:playerc

本文链接:http://www.cnblogs.com/playerc/archive/2013/05/20/latex_utf8_bookmark_c.html

最近使用 pdflatex 写文档的时候,发现 utf8 书签中文出现乱码,网上搜索,发现一个有价值的解决方案。

他使用一个 python 实现的转码方案。下文中简称 方案1

http://www.thinkemb.com/wordpress/?p=260

我就照着写了个 c 语言的。程序的原理在 方案1 中说的很明白,就是  pdflatex 生成含有 书签或目录 的pdf文件时,需要执行两次,第一次先生成一些准备文件,比如  *.out ,这个文件就是储存了书签信息。第二次再根据第一次生成的文件生成 含有书签或目录的 pdf 文件,也就是说,第一次执行时,生成的pdf文件不包含书签或目录。

关于书签乱码的原因,就是当pdf阅读器读取书签时,只能识别 UNICODE 编码,当我们使用的tex文本环境是utf8或gbk 编码时,生成的 *.out 也就使用了 utf8或gbk编码,生成的pdf也同样保留了编码。所以pdf书签中包含的非 ascii 字符就出现乱码了。

这个 转换工具 所做的工作,就是把 *.out 中书签名字符串由 utf8编码转换成unicode 编码。需要用到 utf8 编码知识,和 unicode编码知识。

使用gcc 或 vs 编译后,使用命令行,运行

  utf82uni  <  src.out  > dst .out

src.out 是准备转换的文件,dst.out是转换后的文件。

/**
 * utf82uni.c -- translate bookmark names  in Latex's .out file,Utf8 encoded to Unicode; 
* compile: cc -o utf82uni utf82uni.c
*/ #include<stdio.h> #define UNICODE_PREFIX "\\376\\377" #define UTF8_MAX_BYTES (6) #define UTF8_THREE (14) void init_int_array(int * array, int length){ while(length>0){ *(array+(--length)) = 0; } }//eo init_int_array int main(int argc,char *argv[]){ int bi; //byte number int str[UTF8_MAX_BYTES]={0}; //all byte int gb[2]={0}; int i; int is_begin = 0; //is begin translate int count_brace = 0; int is_brace_begin = 0; int is_brace_end = 0; int is_line_end = 0; while(!feof(stdin)){ i=0; init_int_array(str,UTF8_MAX_BYTES); bi = fread(&str[0],1,1,stdin); is_brace_begin = ((str[0]&0x7f) == '{') ? 1:0; is_brace_end = (str[0]&0x7f) =='}' ? 1:0; is_line_end = (str[0]&0x7f)=='\n' ? 1:0; if(is_brace_begin||is_brace_end){ count_brace ++; }else if(is_line_end){ count_brace=0; } if((count_brace !=3) || is_brace_begin ||is_brace_end){ fwrite(&str[0],bi,1,stdout); is_begin = 0; continue; } // count_brace == 3 ,translate Utf8 code to Unicode with \ooo format; if(is_begin == 0){ printf(UNICODE_PREFIX); is_begin = 1; } if(((str[0]>>4)&0xff)== UTF8_THREE ){ bi = 3; for(i=1; (i< bi) && (!feof(stdin)); i++){ fread(&str[i], 1, 1, stdin); } init_int_array(gb, 2); /** * 1110xxxx , 10 xxxx xx , 10 xxxxxx */ gb[0] = ((str[0]<<4)&0xF0)|((str[1]>>2)&0x0F); gb[1] = ((str[1]<<6)& 0xF0) | ((str[2])& 0x3F); printf("\\%03o\\%03o",gb[0],gb[1]); }else{ printf("\\%03o\\%03o",0,(str[0])&0x7f); } }//eof while return 0; }//eof main

 

抱歉!评论已关闭.