一、实验目的
1.理解不同体系结构风格的具体内涵。
2.学习体系结构风格的具体实践。
二、实验环境
硬件: (依据具体情况填写)
软件:Java或任何一种自己熟悉的语言
三、实验内容
“上下文关键字”KWIC(Key Word in Context,文本中的关键字)检索系统接受有序的行集合:每一行是单词的有序集合;每一个单词又是字母的有序集合。通过重复地删除航中第一个单词,并把它插入行尾,每一行可以被“循环地移动”。KWIC检索系统以字母表的顺序输出一个所有行循环移动的列表。
四、实验步骤:
1、体系结构图:
2、
a.主程序子程序风格
b.简述体系结构各部件的主要功能,实现思想。
上述的主程序/子程序的方法,将问题分解为输入(InputStore)、移动(CircleShifter)、按字母表排序(Alphabetizer)、输出(Outputer)。
InputStore : 该类处理读取文件数据,并输出到控制台。
CircleShifter : 该类实现循环移位。
Alphabetizer : 主该类对行数据进行按字母顺序排序
Outputer: 主函数调用该方法,输出到控制台
c.代码:
//InputStore输入类 package edu.nju.eureka; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; /** * * 输入 */ public class InputStore { private ArrayList<String> textLines; //对textLines进行初始化 public InputStore(String filePath) { textLines = new ArrayList<String>(); String line = new String(); BufferedReader reader; try{ reader = new BufferedReader(new FileReader(filePath)); while((line=reader.readLine())!=null){ textLines.add(line); } reader.close(); }catch(IOException e){ System.out.println("Input File Does Not Exsit!"); } } //对外提供的接口 public ArrayList<String> getTextLines(){ return this.textLines; } }
/** * CircularShifter 循环移位类 */ package edu.nju.eureka; import java.util.ArrayList; /** * * 循环移位 */ public class CircularShifter { private ArrayList<String> shirtedLines; public CircularShifter() { shirtedLines = new ArrayList<String>(); } private ArrayList<Integer> getShiftPosition(InputStore inputStore) { ArrayList<Integer> shiftedLineIndexes = new ArrayList<Integer>(); //用来计数左移一次开始单词的position int counter = 0; for(int i=0;i<inputStore.getTextLines().size();i++){ //每行开头需要记录 shiftedLineIndexes.add(counter); for(int j=0;j<inputStore.getTextLines().get(i).length();j++){ if((inputStore.getTextLines().get(i).charAt(j)==' ')&&(inputStore.getTextLines().get(i).charAt(j+1)!=' ')){ shiftedLineIndexes.add(counter+1); } counter++; } } return shiftedLineIndexes; } public void shift(InputStore inputStore) { ArrayList<Integer> shiftedLineIndexes = getShiftPosition(inputStore); int lengthCounter = 0; int j = 0; for(int i=0;i<inputStore.getTextLines().size();i++){ lengthCounter = lengthCounter + inputStore.getTextLines().get(i).length(); while(shiftedLineIndexes.get(j)<lengthCounter){ char[] newStr = new char[inputStore.getTextLines().get(i).length()+1]; int charSet = 0; //赋值 for(int x = shiftedLineIndexes.get(j) - lengthCounter + inputStore.getTextLines().get(i).length();x<inputStore.getTextLines().get(i).length();x++){ newStr[charSet] = inputStore.getTextLines().get(i).charAt(x); charSet++; } if(inputStore.getTextLines().get(i).length()- lengthCounter + shiftedLineIndexes.get(j)!=0){ newStr[charSet] = ' '; charSet++; } for(int x = 0; x <(inputStore.getTextLines().get(i).length()- lengthCounter + shiftedLineIndexes.get(j));x++){ newStr[charSet] = inputStore.getTextLines().get(i).charAt(x); charSet++; } shirtedLines.add(new String(newStr)); j++; //如果所有位置记录都已经被遍历,则跳出 if(j>=shiftedLineIndexes.size()){ break; } } } } public ArrayList<String> getShiftedLines() { return this.shirtedLines; } }
/** * Alphabetizer 字母排序类 */ package edu.nju.eureka; import java.util.ArrayList; import java.util.Collections; /** * * 按字母排序 */ public class Alphabetizer { private ArrayList<String> sortedLines; public Alphabetizer() { sortedLines = new ArrayList<String>(); } public void sort(CircularShifter circularShifter) { Collections.sort(circularShifter.getShiftedLines()); for(int x = 0;x<circularShifter.getShiftedLines().size();x++) { sortedLines.add(circularShifter.getShiftedLines().get(x)); } } public ArrayList<String> getSortedLines(){ return sortedLines; } }
/** * Outputer 输出类 */ package edu.nju.eureka; /** * 输出类 * */ public class Outputer { public void printKWIC(Alphabetizer alphabetizer) { for(int x = 0;x<alphabetizer.getSortedLines().size();x++){ System.out.println(alphabetizer.getSortedLines().get(x)); } } }
/** * MainTest 主程序类 */ package edu.nju.eureka; /** * * 主程序类 */ public class MainTest { public static void main(String[] args) { InputStore inputStore = new InputStore("Text.txt"); CircularShifter circularShifter = new CircularShifter(); circularShifter.shift(inputStore); Alphabetizer alphabetizer = new Alphabetizer(); alphabetizer.sort(circularShifter); Outputer outputer = new Outputer(); outputer.printKWIC(alphabetizer); } }
3.
a.管道-过滤器模式
b.代码
/** * Filter 过滤器 */ package pipestyle; /** * 过滤器有输入管道和输出管道两个组件。 * 过滤器将输入管道的数据转换成要求的数据,并将转换好的数据写到输出管道。 * 输入管道和输出管道是相对的,即在某个阶段输出管道接收数据,在下一阶段, * 输出管道便提供数据,成为输入管道,输入管道同理。每个过滤器在它的线程 * 空间中运行 */ public abstract class Filter implements Runnable { protected Pipe input; protected Pipe output; private boolean is_started = false; /** * 默认构造器 * @param input 输入管道 * @param output 输出管道 */ public Filter(Pipe input, Pipe output) { this.input = input; this.output = output; } /** * 调用之后则线程开始执行 */ public void start() { if(!is_started) { //防止多次调用 is_started = true; Thread thread = new Thread(this); thread.start(); } } /** * 线程的run方法 */ public void run() { transform(); } /** * 该方法将输入管道的数据转换成要求的数据,并将转换好的数据写到输出管道 * 子类实现该抽象方法 */ abstract protected void transform(); }
/** * Input 输入 */ package pipestyle; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; /** * 按行读取数据,传递给下一模块 * */ public class Input extends Filter { private FileReader fr; public Input(File fInput, Pipe output) { super(null, output); try { fr = new FileReader(fInput); } catch (FileNotFoundException e) { e.printStackTrace(); } } /** * 按行从输入文件fr中读取数据,并将数据写到输出管道output中 */ @Override protected void transform() { BufferedReader br = new BufferedReader(fr); try { String line; while((line = br.readLine()) != null) { output.write(line + '\n'); //加入换行是以便下个模块的处理 } br.close(); fr.close(); output.closeWriter(); } catch (IOException e) { e.printStackTrace(); } } }
/** * Pipe管道 */ package pipestyle; import java.io.IOException; import java.io.PipedReader; import java.io.PipedWriter; /** * 一个管道对象将两个读写数据流连接起来,写数据流可以向管道中写入数据, * 读数据流则可以在管道中有可用数据的时候读出数据 */ public class Pipe { private PipedWriter pipedWriter; private PipedReader pipedReader; /** * 默认构造器,初始化读和写管道,并建立它们之间的连接 * @throws IOException 如不能建立连接则抛出IO异常 */ public Pipe() throws IOException { pipedReader = new PipedReader(); pipedWriter = new PipedWriter(); pipedReader.connect(pipedWriter); } /** * 从管道中读一个字符 * @return 读取到的一个字符 * @throws IOException 如不能从管道中读则抛出异常 */ public int read() throws IOException { return pipedReader.read(); } /** * 向管道写一个字符 * @param c 要写入的字符 * @throws IOException 如不能向管道写则抛出异常 */ public void write(int c) throws IOException { pipedWriter.write(c); } /** * 写入字符串的某一部分 * @param s 要写入的字符串 * @param off 开始读取字符处的偏移量 * @param len 要写入的总字符数 * @throws IOException 如不能写入数据则抛出异常 */ public void write(String s, int off, int len) throws IOException { pipedWriter.write(s.toCharArray(), off, len); } /** * 写入整个字符串 * @param s 要写入的字符串 * @throws IOException 如不能写入数据则抛出异常 */ public void write(String s) throws IOException { pipedWriter.write(s.toCharArray()); } /** * 将读管道关闭,调用该方法后,不能再从管道中读数据 * @throws IOException 如不能关闭则抛出异常 */ public void closeReader() throws IOException { pipedReader.close(); } /** * 将写管道关闭,调用该方法后,不能向管道中写数据 * @throws IOException 如不能关闭则抛出异常 */ public void closeWriter() throws IOException { pipedWriter.flush(); pipedWriter.close(); } }
/** * CircularShift 循环移位 */ package pipestyle; import java.io.CharArrayWriter; import java.io.IOException; /** * 第一行数据到来后开始运作 * 把原始数据行循环移位,将原始行和新的移位后的行输出给下一模块 */ public class CircularShift extends Filter { private static final String ignore = "a#$an#$and#$as#$is#$the#$of#$"; //一些噪音词汇 public CircularShift(Pipe input, Pipe output) { super(input, output); } /** * */ @Override protected void transform() { try { CharArrayWriter writer= new CharArrayWriter(); //缓冲当前行 int c = -1; while((c = input.read()) != -1) { if(c == 10) { //回车,表示writer中取得了一行数据 String curLine = writer.toString();//存储从输入管道中取得的当前行 String[] words = curLine.split(" +|\t+"); //将当前行分解成多个单词 for(int i = 0; i < words.length; i++) { if(ignore.indexOf((words[i] + "#$").toLowerCase()) != -1)//去掉噪音词汇打头的行 continue; String shift = ""; for(int j = i; j < (words.length + i); j++) { shift += words[j % words.length]; if (j < (words.length + i - 1)) shift += " "; } shift += "\r\n"; output.write(shift); writer.reset(); } } else writer.write(c); } input.closeReader(); output.closeWriter(); } catch (IOException e) { e.printStackTrace(); } } }
/** * Alphabetizer 按字母排序 */ package pipestyle; import java.io.CharArrayWriter; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class Alphabetizer extends Filter { public Alphabetizer(Pipe input, Pipe output) { super(input, output); } /** * */ @Override protected void transform() { List<String> lines = new ArrayList<String>(); CharArrayWriter writer = new CharArrayWriter(); try { int c = -1; while((c = input.read()) != -1) { writer.write(c); // System.out.print((char) c); if(c == 10) { String curLine = writer.toString(); lines.add(curLine); writer.reset(); } } sort(lines); for(String s : lines) { output.write(s); } input.closeReader(); output.closeWriter(); } catch (IOException e) { e.printStackTrace(); } } private void sort(List<String> lines) { //堆排序 int size = lines.size(); for (int i = (size / 2 - 1); i >= 0; i--) siftDown(lines, i, size); for (int i = (size - 1); i >= 1; i--) { Object tmp = lines.get(0); lines.set(0, lines.get(i)); lines.set(i, (String) tmp); siftDown(lines, 0, i); } } private void siftDown(List<String> lines, int root, int bottom) { int max_child = root * 2 + 1; while (max_child < bottom) { if ((max_child + 1) < bottom) if (((String) lines.get(max_child + 1)) .compareTo((String) lines.get(max_child)) > 0) max_child++; if (((String) lines.get(root)).compareTo((String) lines .get(max_child)) < 0) { Object tmp = lines.get(root); lines.set(root, lines.get(max_child)); lines.set(max_child, (String) tmp); root = max_child; max_child = root * 2 + 1; } else break; } } }
/** * Output 输出 */ package pipestyle; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; /** * */ public class Output extends Filter { private FileWriter fw; /** * @param input 输入管道 * @param output 输出文件 */ public Output(Pipe input, File fOutput) { super(input, null); try { fw = new FileWriter(fOutput); } catch (IOException e) { e.printStackTrace(); } } /** * */ @Override protected void transform() { BufferedWriter bw = new BufferedWriter(fw); try { int c = -1; while((c = input.read()) != -1) { bw.write(c); } input.closeReader(); bw.flush(); bw.close(); fw.close(); } catch (IOException e) { e.printStackTrace(); } } }
/** * PipeKwic */ package pipestyle; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; /** * 用管道/过滤器风格设计KWIC */ public class PipeKwic { public static boolean is_completed = false; /** * @param args */ public static void main(String[] args) { try { File fInput = new File(System.getProperty("user.dir") + "\\input.txt"); File fOutput = new File("output.txt"); // System.out.println(System.getProperty("user.dir")); Pipe in_cs = new Pipe(); Pipe cs_al = new Pipe(); Pipe al_ou = new Pipe(); Input input = new Input(fInput, in_cs); CircularShift shift = new CircularShift(in_cs, cs_al); Alphabetizer alpha = new Alphabetizer(cs_al, al_ou); Output output = new Output(al_ou, fOutput); input.start(); // run it ! shift.start(); alpha.start(); output.start(); // 将结果直接输出 FileReader frInput = new FileReader(fInput); FileReader frOutput = new FileReader(fOutput); BufferedReader brInput = new BufferedReader(frInput); BufferedReader brOutput = new BufferedReader(frOutput); System.out.println("-----------------------Solution 1: Pipe/Filter------------------------"); System.out.println("---------------Input---------------"); while(brInput.ready()) { System.out.println(brInput.readLine()); } System.out.println("--------------Output---------------"); try { Thread.sleep(5000); } catch (Exception e) { e.printStackTrace(); } while(brOutput.ready()) { System.out.println(brOutput.readLine()); } brInput.close(); brOutput.close(); frInput.close(); frOutput.close(); } catch (Exception e) { e.printStackTrace(); } } }