文档章节

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

 脚本爱好者
发布于 2012/06/25 11:42
字数 527
阅读 183
收藏 1

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


public class WordExtractor {
   
    public static StringBuilder logBytes = new StringBuilder();
   
    public static String bytesToString(byte[] ogiBytes, int start, int length, int fc)
    {
        StringBuilder content = new StringBuilder();
        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 content.toString();
                }
               
                String a = Integer.toHexString(bytes[i+1] & 0xFF);
                String b = Integer.toHexString(bytes[i] & 0xFF);
                if(a.length() == 1)
                {
                    a = "0"+ a;
                }
               
                if(b.length() == 1)
                {
                    b = "0"+ b;
                }
               
                String hexStr = a + b;
                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 );
            }
        }
       
        return content.toString();
    }
   
    public static void bytesToString(byte[] ogiBytes, StringBuilder content, int start, int length, int fc)
    {
        content.append( bytesToString(ogiBytes, start, length, fc) );
    }
   
    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:ytes.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: oolsoletest est-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

本文转载自:http://www.xiaomeiti.com

共有 人打赏支持
粉丝 1
博文 2
码字总数 0
作品 0
东城
程序员
私信 提问
ecplise常用的快捷键(汇总)

不多说,直接奉上: Ctrl+1 快速修复(最经典的快捷键,就不用多说了) Ctrl+D: 删除当前行 Ctrl+Alt+↓ 复制当前行到下一行(复制增加) Ctrl+Alt+↑ 复制当前行到上一行(复制增加) Alt+↓ 当前行和...

爱幻想的螃蟹
2014/08/06
0
0
Eclipse平台快捷键,开发必备!

学习Android开发,eclipse的使用是少不了的,今天找了一些eclipse的快捷键跟大家分享一下,后续还会有更多资料和大家分享,呵呵,一起努力吧! Ctrl+1 快速修复(最经典的快捷键,就不用多说了...

铂金小猪
2011/08/17
0
0
Eclipse cdt安装与使用

Eclipse cdt安装与使用 基于Window 7 Ultimate X64 + Eclipse SDK3.5.2 + cdt + MinGW-5.1.6 + gdb-6.6 + MSYS-1.0.11 1、启动Eclipse SDK,选择Help->"Install New Software...","Work wit......

DB_Terrill
2011/08/05
0
0
1.5.1 编辑java源代码

编辑 java 源代码可以使用任何无格式的文本编辑器,在Windows操作系统上可以使用记事本(NotePad)、EditPlus 等程序,在Linux平台上可以使用VI工具等。 注意:编写java程序不要使用写字板,...

Gooiem
2015/08/25
0
0
java.io几种读写文件的方式

一、Java把这些不同来源和目标的数据都统一抽象为数据流。   Java语言的输入输出功能是十分强大而灵活的。   在Java类库中,IO部分的内容是很庞大的,因为它涉及的领域很广泛:标准输入输...

知止内明
08/06
0
0

没有更多内容

加载失败,请刷新页面

加载更多

利用cefSharp实现网页自动注册登录的需要注册的一些事项

最近朋友有个需要自动注册登录点击的事,我帮着写了写,好久没写过这东西了,在写的过程中总结了需要注意的一些事项。 一、换IP之后要测试一下速度,我目前用的最简单的测试方法就是20-30秒加...

我退而结网
16分钟前
1
0
Go语言中使用 BoltDB数据库

boltdb 是使用Go语言编写的开源的键值对数据库,Github的地址如下: https://github.com/boltdb/bolt boltdb 存储数据时 key 和 value 都要求是字节数据,此处需要使用到 序列化和反序列化。...

Oo若离oO
17分钟前
1
0
zookeeper分布式锁

//lock 锁 定义分布式锁public interface Lock {//获取锁public void getLock();//释放锁public void unLock();} public abstract class ZookeeperAbstractLock implements Loc......

熊猫你好
24分钟前
0
0
mysql_事务隔离机制

事务隔离机制 事务就是要保证一组数据库操作,要么全部成功,要么全部失败。在mysql中,事务支持是在引擎层实现的。mysql是一个支持多引擎的系统,但并不是所有引擎都支持事务,比如mysql...

grace_233
27分钟前
0
0
不学无数——Java中IO和NIO

JAVA中的I/O和NIO I/O 问题是任何编程语言都无法回避的问题,可以说 I/O 问题是整个人机交互的核心问题,因为 I/O 是机器获取和交换信息的主要渠道。在当今这个数据大爆炸时代,I/O 问题尤其...

不学无数的程序员
33分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部