问候,
最后两篇文章介绍了该工具的设计和实现
文本处理器,将文本段落输入到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