文本检索系统-4A:图书馆

本文深入探讨了一种文本检索系统中的图书馆管理模块,详细介绍了LibraryBuilder工具如何组织、清理和存储文本,以及Library对象如何通过多种方法实现文本的检索、存储和管理,包括书签功能、元数据生成和文本段落的处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问候,

最后两篇文章介绍了该工具的设计和实现

文本处理器,将文本段落输入到LibraryBuilder。

后一个对象组织,清理和存储输入给它的文本。

最终,LibrayBuilder能够产生一个以主题为主题的库

这部分的内容。

介绍

图书馆管理书籍组。 每本书都包含以下章节:

文字段落。 对象可以按照给定的压缩方式存储自身

任何OutputStream。 给定任何Input-,静态方法可以加载Library对象-

再次流。 图书馆可以产生整段书本或

章节或单个文本段落。

图书馆还可以产生“元”数据列表,即它可以产生一个列表

书名或章标题的组名; 它也可以产生简单的统计数据

例如图书馆的书籍数量等。

基本上,图书馆可以产生清单。 列表是纯列表

文本(字符串)或书签列表。 书签代表一个段落

文字,并具有其他功能。

让我们看看它是如何完成的。

库对象

在本文的上一部分中,我们已经看到一个Library构造函数

由LibraryBuikder调用; 这是数据的部分和de的构造函数

库对象:


protected String    title;
protected WordMap   wordMap;
protected Section[] groups;    
protected Section[] books;
protected Section[] chapters;
protected String[]  paragraphs;
protected String[]  words;
protected String[]  punctuation; 
protected NotesMap  notesMap; 
public Library(String    title,
           WordMap   wordMap,
           Section[] groups,
           Section[] books, 
           Section[] chapters,
           String[]  paragraphs, 
           String[]  words, 
           String[]  punctuation) {  
    this.title        = title;
    this.wordMap    = wordMap; 
    this.groups        = groups;
    this.books      = books;
    this.chapters   = chapters;
    this.paragraphs = paragraphs;
    this.words      = words;
    this.punctuation= punctuation; 
    this.notesMap   = new NotesMap();
} 
这是很多代码,但这只是简单的东西。 的所有参数

构造函数存储在成员变量中。 如前所述,

是小组,书籍和章节的章节。 段落和标点

是字符串。 有一个用于唯一单词的String []数组,

WordMap将所有内容粘合在一起。 请参阅上一篇文章的内容

这些数组和对象的说明。

另外,NotesMap也被初始化。 NoteMap用于为每个附加文本

文本中的单个段落。 这是它的定义:


class NotesMap extends HashMap<Integer, String> { 
    private static final long serialVersionUID = 4627674436919142999L; 
    private boolean modified= false; 
    public void setModified(boolean modified) {this.modified= modified; }
    public boolean isModified() { return modified; } 
    public void put(int paragraph, String note) { 
        String oldNote= get(paragraph); 
        note= (note != null)?note.trim():"";
        note= (note.length() == 0)?null:note; 
        if (note == null) 
            modified|= remove(paragraph) != null;
        else {
            put(paragraph, note);
            modified|= !note.equals(oldNote);
        }
    }
} 
基本上,NotesMap是一个简单的Map,它映射Integers(

一个段落)到一个简单的字符串,该字符串存储该段落的注释。

它应用了一些智能功能来检查地图是否被修改。

空文本被视为完全没有文本。 修改后的标志可用于检查

是否在不需要时再次保存Library对象

不再。

Library对象实现了一些方便的方法,因此您永远不会

直接自己处理NoteMap对象:


public boolean isModified() { return notesMap.isModified(); } 
NotesMap不是一个非常复杂也不是一个非常有趣的类,除了

一方面:它实现了Serializable接口,因为其父类

实现此接口。 这是必需的,因为必须保存此类或

与Library对象本身一起加载。

稍后我们将看到Library类本身也实现了Serializable

接口。

书签

如简介中所述,图书馆使用书签来表示

一段文字。 这是它的接口定义:


public interface BookMark { 
    public String  getGroup();
    public String  getBook();
    public String  getChapter();
    public String  getParagraph(); 
    public int     getGroupNumber();
    public int     getBookNumber();
    public int     getChapterNumber();
    public int     getParagraphNumber(); 
    public int     getRelativeBook();
    public int     getRelativeChapter();
    public int     getRelativeParagraph(); 
    public void    putNote(String note);
    public String  getNote();
} 
如果库为您生成了一个BookMark对象,则可以查询该对象

对于该文本的几个方面,即您可以获取该章的名称

该段是; 您还可以获取该段落的书名

可以找到,并且您可以找到存储书的组的名称。

您当然也可以获取该段落的文本。

段落,章节,书籍和组都有一个数字,从零开始。

有一些方法可以检索那些绝对索引号。 那里

还有一些方法可用于检索这些实体的相对编号。

假设第一本书有两章,一本书中有三章,

第二本书。 绝对章节编号为0、1、2、3、4,相对章节编号为

章节编号为0、1、0、1、2,即相对章节编号开头

每本书为零。 类似的推理也适用于书籍和段落。

请注意,出于明显的原因,没有可用的相对组号。

最后两个方法设置并获得给定段落的可选附加文本

由该书签表示。 这两种方法与库一起

委托人isModified()方法完全屏蔽了NotesMap类,

即,您无需自己处理。

加载和保存库

如果要加载给定InputStream的库,则没有该对象

可用(尚未加载)。 这就是为什么Library类实现

两种静态便利方法:一种方法可以加载给定文件名的Library,

另一个方法采用InputStream,从该InputStream加载Library对象。

他们来了:


public static Library read(String name) 
            throws IOException, ClassNotFoundException { 
    FileInputStream fis= null; 
    try {
        return read(fis= new FileInputStream(name));
    }
    finally {
        try { fis.close(); } catch (IOException ioe) { }
    }
} 
public static Library read(InputStream is) 
            throws IOException, ClassNotFoundException { 
    return (Library)new ObjectInputStream(new InflaterInputStream(is)).
            readObject();
} 
第一个方法只是尝试打开给定文件名的FileInputStream,然后

将困难的部分委托给第二种方法。 第二种方法包装两个

给定InputStream周围的其他InputStreams。 第一个包装器/装饰器

扩大输入流。 膨胀的输入由ObjectInputStream使用

实际对象构造的包装器。 两种方法都可以简单地抛出

IOExceptios当某些读取失败并且可以抛出ClassNotFoundExceptions时

如果InputStream没有任何意义。

第二种方法不会关闭传递给它的流,因为它不拥有

它,也就是说,此方法的调用者对此流有不同的计划,

并关闭它会禁止它。 第一种方法创建了OutputStrem

本身,因此它拥有它,因此它自己关闭流。

当然,只有拥有一个Library对象,您才能保存它。 因此

写方法不是静态方法。 这些方法的逻辑没有区别

从静态加载方法中获得很大帮助。 他们来了:


public void write(String name) throws IOException { 
    FileOutputStream fos= null; 
    try {
        fos= new FileOutputStream(name);
        write(fos);
    }
    finally {
        try { fos.close(); } catch (IOException ioe) { }
    }
} 
public void write(OutputStream os) throws IOException { 
    DeflaterOutputStream dos;
    ObjectOutputStream oos= new ObjectOutputStream(dos= new DeflaterOutputStream(os)); 
    oos.writeObject(this);
    oos.flush();
    dos.finish();
} 
第一种方法只是创建一个给定文件名和委托的FileOutputStream。

第二种方法的辛苦工作。 将此与静态加载方法进行比较。

另一种方法将DeflaterOutputStream包裹在OutputStream参数周围。

该DeflaterOutputStream再次包装在ObjectOutputStream中,并且

整个库均已编写。

还要注意,第二种方法不会关闭相同的流

加载方法说明的原因(再次比较逻辑)。

我注意到本文的内容再次变得很长,因此我在下面看到您

本文部分的续集。

亲切的问候,

乔斯

From: https://bytes.com/topic/java/insights/684854-text-retrieval-systems-4a-library

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值