使用Java基于数据流直接抽取word文本

标签: Java资料 | 发表时间:2012-05-23 08:00 | 作者:Administrator
出处:http://www.scriptlover.com

如下代码是直接基于数据流进行文本抽取,支持word97-word2003版本,之后的版本实际都是xml,抽取文本非常简单,因此在此处不再说明,代码仅供研究学习使用,禁止用于商业用途。


public class WordExtractor {
   
    public static StringBuilder logBytes = new StringBuilder();
   
    public static void bytesToString(byte[] ogiBytes, StringBuilder content, int start, int length, int fc)
    {
        byte[] bytes = new byte[length];
        System.arraycopy(ogiBytes, start, bytes, 0, length);
        if(fc == 0)
        {
            for(int i=0;i<bytes.length;i++)
            {
                if(i == bytes.length - 1)
                {
                    return;
                }
               
                String hexStr = Integer.toHexString(bytes[i+1] & 0xFF) + Integer.toHexString(bytes[i] & 0xFF);
                int ch = Integer.valueOf(hexStr, 16);
                content.append( (char)ch );
                i++;
            }
        }
        else
        {
            for(int i=0;i<bytes.length;i++)
            {
                int ch = bytes[i] & 0xFF;
                content.append( (char)ch );
            }
        }
       
    }
   
    public static void printLogBytes(List<Byte> legaled) throws Exception
    {
        logBytes = new StringBuilder();
       
        logBytes.append(" ========================================================");
        for(int a=0;a<legaled.size();a++)
        {
            if(a % 16 == 0)
            {
                logBytes.append(" ");
            }
            logBytes.append(Integer.toHexString(legaled.get(a) & 0xFF) +" ");
        }
        logBytes.append(" ========================================================");
       
        FileUtil.writeAscFile("E:\bytes.txt", logBytes.toString());
    }
   
    public static int getOneTable(byte[] ogiBytes, Stream stream, int dirSect1)
    {
        for(int i=0;i<8;i++)
        {
            int offsetEntry = (dirSect1 + 1)*512 + i*128;
            StringBuilder content = new StringBuilder();
            bytesToString(ogiBytes, content, offsetEntry, 64, 0);
            if(content.toString().indexOf("1Table") > -1)
            {
                return offsetEntry;
            }
        }
       
        return 0;
    }
   
    public static void main(String[] args) throws Exception
    {
        byte[] ogiBytes = FileUtil.readBinFile("D:\tools\oletest\test-old.doc");
       
        System.out.println("Total bytes: "+ ogiBytes.length);
        if(
                ogiBytes.length < 8         ||
                (ogiBytes[0] & 0xFF) != 208 ||
                (ogiBytes[1] & 0xFF) != 207 ||
                (ogiBytes[2] & 0xFF) != 17     ||
                (ogiBytes[3] & 0xFF) != 224 ||
                (ogiBytes[4] & 0xFF) != 161 ||
                (ogiBytes[5] & 0xFF) != 177 ||
                (ogiBytes[6] & 0xFF) != 26     ||
                (ogiBytes[7] & 0xFF) != 225
        ){
            System.out.println("Not the doc file!");
            return;
        }
       
        StringBuilder content = new StringBuilder();
       
        Stream stream = new Stream(ogiBytes);
        int[] offset = new int[1];
       
        offset[0] = 48;
        int dirSect1 = stream.getInteger(offset);
        int oneTable = getOneTable(ogiBytes, stream, dirSect1);
       
        offset[0] = oneTable + 116;
        int startSect = stream.getInteger(offset);
        int tableStream = (startSect + 1)*512;
       
        offset[0] = 930;
        int fcClx = stream.getInteger(offset);
        if(fcClx == -1)
        {
            System.out.println("This version of doc can not be parsed!");
            return;
        }
       
        int offsetClx = tableStream + fcClx;
       
        offset[0] = offsetClx + 1;
        int lcb = stream.getInteger(offset);
      
        int countPcd = (lcb - 4)/12;
        int countCp = (lcb - countPcd*8)/4;
        int offsetPlcpcd = offsetClx + 5;
      
        for(int i=0;i<countPcd;i++)
        {
            int offsetPcd = offsetPlcpcd + countCp*4 + i*8;
           
            offset[0] = offsetPcd + 2;
            int start = stream.getInteger(offset);
            int fc = start >> 30;
            start = (start << 2) >> 2;
      
            offset[0] = offsetPlcpcd + i*4;
            int cpPre = stream.getInteger(offset);
            int cpNext = stream.getInteger(offset);
            int length = cpNext - cpPre -1;
            if(fc == 0)
            {
                length *= 2;
            }
            else
            {
                start = start/2;
            }
           
            start += 512;
            bytesToString(ogiBytes, content, start, length, fc);
       
            System.out.println(start +", "+ length);
        }
       
        FileUtil.writeAscFile("E:\output.txt", content.toString(), false);
       
        System.out.println("Done!");
       
    }
}

参考资料:
http://blog.csdn.net/hu0406/article/details/3157192
http://msdn.microsoft.com/zh-cn/library/gg615596.aspx

相关 [java 数据 word] 推荐:

使用Java基于数据流直接抽取word文本

- - 脚本爱好者
如下代码是直接基于数据流进行文本抽取,支持word97-word2003版本,之后的版本实际都是xml,抽取文本非常简单,因此在此处不再说明,代码仅供研究学习使用,禁止用于商业用途.

java导出word之freemarker导出

- - 企业架构 - ITeye博客
       一,简单模板导出(不含图片, 不含表格循环).          1, 新建一个word文档, 输入如下类容:.          2, 将该word文件另存为xml格式(注意是另存为,不是直接改扩展名).          3, 将xml文件的扩展名直接改为ftl.          4, 用java代码完成导出(需要导入freemarker.jar).

java中文分词组件-word分词

- - 研发管理 - ITeye博客
关键字:java中文分词组件-word分词. word分词器主页 :https://github.com/ysc/word. word分词是一个Java实现的中文分词组件,提供了多种基于词典的分词算法,并利用ngram模型来消除歧义. 能准确识别英文、数字,以及日期、时间等数量词,能识别人名、地名、组织机构名等未登录词.

word wrap 解惑

- 大狗 - Taobao UED Team
我们经常需要“修复”一个老生常谈的“bug”,那就是文本的自动换行问题. 在专业术语上,这种期望得到的渲染现象被称作“word wrap”,即文本处理器有能力把超出页边的整个词自动传到下一行. 在现实项目中,尤其是在测试阶段,鉴于测试使用非常极端的测试用例,我们经常需要“修复”如图所示的这个问题:.

Struts导出word

- - CSDN博客Web前端推荐文章
 * @param tableSize 多少列(列数). // 设置 Table 表格. aTable.setWidths(width);// 设置每列所占比例. aTable.setWidth(100); // 占页面宽度 90%. aTable.setAlignment(Element.ALIGN_CENTER);// 居中显示.

freemarker生成word

- - 开源软件 - ITeye博客
freemarker生成word.          利用freemarker生成word,在项目中有用到,就单独写个测试以及用法列出来,欢迎圈错,共同学习.       一、应用场景和效果图.             1.应用场景:.                    a.xx项目里面需要定期生成xx报告,记录最近xx情况.

java 数据存储 bit

- - zzm
大家都知道在Java 数据存储方式. 定1 int = 4 byte, 1 byte = 8 bit. 以此推理那么1个int在计算机中就是以4 * 8 = 32位(bit)的方式存储的. 内存大小为一个1G的空间,有 8*1024*1024*1024=8.58*10^9bit;85亿长度. 用1位来表示一个数据是否出现过,0为没有出现过,1表示出现过.

Word操作技巧(一)

- Gene - 完美Excel
上周在分部内为同事进行了一场Word操作技巧培训,引起了大家比较强烈的反响,很多人都惊讶于每天使用的Word有如此多的技巧和功能,对Word又有了重新的认识. 通过这次培训,也使我认识到,虽然大家经常使用Word,但对其的了解还远远不够,以致于如此一款优秀的软件,没有得到很好的使用,甚至得到了许多误解.

POI读写Word docx文件

- - 开源软件 - ITeye博客
使用 POI 读写 word docx 文件. 1     读docx文件. 1.1     通过XWPFWordExtractor读. 1.2     通过XWPFDocument读. 2     写docx文件. 2.1     直接通过XWPFDocument生成. 2.2     以docx文件作为模板.

通过Java程序获取Dynatrace数据

- - Taobao QA Team
“dynaTrace Ajax是一个详细的底层追踪工具,它不仅可以显示所有请求和文件在网络中传输的时间,还会记录浏览器Render、CPU消耗、JavaScript解析和运行情况等详细的信息,而这些也只是dynaTrace Ajax的冰山一角. showslow平台同样采集了dynatrace的数据,所以做为kelude平台前端页面测试组件,同样要支持dynatrace数据的获取,该代码由云晰同学编写维护:.