管道--过滤器之千年虫问题
来源:互联网 发布:淘宝返利机器人多少钱 编辑:程序博客网 时间:2024/05/16 02:06
/*
管道–过滤器之千年虫问题
//////////////////////////千年虫”问题的根源始于60年代。当时计算机存储器的成本很高,如果用四位数字表示年 份,就要多占用存储器空间,就会使成本增加,因此为了节省存储空间,计算机系统的编程 人员采用两位数字表示年份。随着计算机技术的迅猛发展,虽然后来存储器的价格降低了, 但在计算机系统中使用两位数字来表示年份的做法却由于思维上的惯性势力而被沿袭下来, 年复一年,直到新世纪即将来临之际,大家才突然意识到用两位数字表示年份将无法正确辨 识公元2000年及其以后的年份。*************///////////////////////
*InputFilter->Y2kFixFilter->AnnotFilter->OutputFilter\*
*/////
AnnotFilter
import java.io.IOException;import java.io.CharArrayWriter;import java.lang.Character;import java.util.Calendar;public class AnnotFilter extends Filter { public AnnotFilter (Pipe input, Pipe output){ super(input, output); } /*-----------------------------------------------------------------------*/ /* Read characters from the input pipe, form a line, /* add some annotations to the line and then write /* the line as chars into outpipe /*-----------------------------------------------------------------------*/ protected void processData(){ try{ CharArrayWriter writer = new CharArrayWriter(); int c = inPipe.read(); while(c != -1){ //not end of file if(((char) c) == '\n'){ //got a complete line String aLine = getALine(writer); String lineAnnotated = addAnnotations(aLine); writeALineOfCharsToDownStream(lineAnnotated); writer.reset(); } else{ writer.write(c); // write chars to the data holder writer } c = inPipe.read(); } outPipe.closePipedOutputStream(); inPipe.closePipedInputStream(); } catch(IOException exc){ exc.printStackTrace(); System.err.println("Error: failed to make annotation update"); System.exit(1); } } private String getALine(CharArrayWriter writer){ String line = writer.toString(); return line; } private String addAnnotations(String line1){ String strline = line1; String time = getExecutionTime(); strline = strline + " Checked at " + time + "\n" ; return strline; } private void writeALineOfCharsToDownStream(String aLine) throws java.io.IOException{ int len = aLine.length(); char[] chars = aLine.toCharArray(); for(int j = 0; j < chars.length; j++){ outPipe.write(chars[j]); } } private String getExecutionTime(){ Calendar now = Calendar.getInstance(); String time = "time " + now.get(Calendar.YEAR)+ "-" +(now.get(Calendar.MONTH) + 1)+ "-" + now.get(Calendar.DATE)+ "-" + now.get(Calendar.HOUR)+ "-" + now.get(Calendar.MINUTE)+ "-" + now.get(Calendar.SECOND)+ "-" + now.get(Calendar.MILLISECOND); return time; }}
/**************************************************************/
AssemblyOfPipeLines
import java.io.FileInputStream;import java.io.IOException;import javax.swing.*;public class AssemblyOfPipeLines { private String option; public AssemblyOfPipeLines(String pipelineOpt) throws IOException{ option= pipelineOpt; } public void assembly(String inFile, JTextArea orig, JTextArea destn) throws IOException { if(option.compareTo(PipeFilterTestGui.PIPELINE1)==0){ try{ //Create 4 pipe objects Pipe p1 = new Pipe(); Pipe p2 = new Pipe(); Pipe p3 = new Pipe(); //Input from source stream FileInputStream in = new FileInputStream(PipeFilterTestGui.LEGACYFILES + inFile); //Create 5 filter objects InputFilter input = new InputFilter(in, p1,orig); Y2kFixFilter y2k = new Y2kFixFilter(p1, p2); AnnotFilter annot= new AnnotFilter(p2, p3 ); //SortingFilter sbc = new SortingFilter(p2, p3 ); OutputFilter output = new OutputFilter(p3, destn,inFile); //Start all the filter threads input.start(); y2k.start(); annot.start(); ///sbc.start(); output.start(); } catch(IOException exc) { exc.printStackTrace(); } } // Switch the order of SortingFilter and Y2kFixFilter objects else if(option.compareTo(PipeFilterTestGui.PIPELINE2)==0){ // Students add code here } }}
/********************************************************************/
Filter
/*--------------------------------------------------------------------*//* This abstract class encapsulates two pipes, *//* one input pipe and the other output pipe. *//* This calss also implements runable, and thus *//* any of its subclass will run an independent *//* thread. *//*--------------------------------------------------------------------*/abstract public class Filter implements Runnable{ protected Pipe inPipe; protected Pipe outPipe; private boolean isStarted = false; //thread flag public Filter(Pipe input, Pipe output) { inPipe = input; outPipe = output; } //Start a new thread public void start(){ if(!isStarted) { isStarted = true; Thread thread = new Thread(this); thread.start(); } } //Stop the current running thread public void stop(){ isStarted = false; } /*-----------------------------------*/ /* Run the threas, run() will be */ /* invoked automatically by start() */ /*-----------------------------------*/ public void run(){ processData(); } /*-------------------------------------*/ /* This method will be implemented */ /* by its subclasses to get different */ /* functionaslities */ /*-------------------------------------*/ abstract protected void processData();}
/****************************************************************/
InputFilter
import java.io.IOException;import java.io.InputStream;import javax.swing.*;public class InputFilter extends Filter{ private InputStream inStream; private JTextArea inputTxt; public InputFilter(InputStream in, Pipe output,JTextArea orig) { super(null, output); inStream = in; //接通数据源 inputTxt = orig; }/*-----------------------------------------------*//* This method reads and parses an input file. *//* The parsed data is written to the output pipe.*//*-----------------------------------------------*/ protected void processData() { try{ boolean isNewLine = false; boolean isNewWord = false; boolean isLineStarted = false; //read data from source file int c = inStream.read(); while(c != -1){ switch((byte) c){ case '\n': isNewLine = true; break; case ' ': isNewWord = true; break; case '\t': isNewWord = true; break; case '\r': break; default: if(isNewLine) { outPipe.write('\n'); isNewLine = false; isLineStarted = false; } if(isNewWord) { if(isLineStarted) outPipe.write(' '); isNewWord = false; } outPipe.write(c); //写到"output"中 isLineStarted = true; break; } c = inStream.read(); inputTxt.append(""+(char)c); } outPipe.write('\n'); outPipe.closePipedOutputStream(); }catch(IOException exc){ exc.printStackTrace(); System.err.println("Error: Could not read the input file."); System.exit(1); } }}
/********************************************************/
OutputFilter
import java.io.IOException;import javax.swing.*;import java.io.CharArrayWriter;import java.io.PrintWriter;import java.io.BufferedOutputStream;import java.io.FileOutputStream;public class OutputFilter extends Filter{ private JTextArea resultTextArea; //String file = "NewFiles/UpdatedFile.txt"; String inputFileNM; public OutputFilter(Pipe input, JTextArea resultTxtA, String inFile) { super(input, null); resultTextArea = resultTxtA; inputFileNM = inFile; } /*--------------------------------------------------*/ /* Read chars from the input pipe, and then write */ /* the resultant data into a file and console */ /*--------------------------------------------------*/ protected void processData() { resultTextArea.append("\n"); try { String file = "UpdatedFiles/"+ "New" + inputFileNM; readCharsFromUpperStreamAndWriteToFileAndOutputToConsol(file); } catch(IOException exc){ exc.printStackTrace(); System.err.println("Output Error"); System.exit(1); } }//end transform method private void readCharsFromUpperStreamAndWriteToFileAndOutputToConsol(String file) throws IOException { CharArrayWriter writer = new CharArrayWriter(); PrintWriter prWriter = new PrintWriter(new BufferedOutputStream(new FileOutputStream(file))); int c = inPipe.read(); while(c != -1){ writer.write(c); if(((char) c) == '\n'){ // got a complete line String line = writer.toString(); prWriter.println(line); writer.reset(); //clear the writer } resultTextArea.append(""+(char)c); c = inPipe.read(); } resultTextArea.append("\n"); prWriter.close(); inPipe.closePipedInputStream(); }}
/**************************************************************************/
Pipe
import java.io.IOException;import java.io.PipedInputStream;import java.io.PipedOutputStream;/*---------------------------------------*//* This Pipe class encapsulates piped *//* reader and piped writer *//*---------------------------------------*/public class Pipe{ private PipedOutputStream pOut; private PipedInputStream pIn; /*-------------------------------------------*/ /* The constructor connects input character */ /* stream with output character stream. */ /*-------------------------------------------*/ public Pipe() throws IOException{ pOut = new PipedOutputStream(); pIn = new PipedInputStream(pOut); } public void write(int c) throws IOException{ pOut.write(c); } public int read() throws IOException{ return pIn.read(); } /*---------------------------------------------*/ // Flush of the output stream will cause the */ // contents that have already been written */ // by the pOut.write(c) returning back to the */ // buffer privided by the object "pIn" of */ // PipedInputStream */ /*---------------------------------------------*/ public void closePipedOutputStream() throws IOException{ pOut.flush(); pOut.close(); } public void closePipedInputStream() throws IOException{ pIn.close(); }}
/****************************************************88/
PipeFilterTestGui
import javax.swing.*;import java.awt.event.*;import java.awt.*;import java.io.File;import java.io.IOException;public class PipeFilterTestGui extends JPanel{ private JScrollPane btnPane; private JSplitPane splitPane; private JSplitPane rightSplitPane; private JTextArea originalTxt; private JTextArea resultTxt; private JScrollPane originPane; private JScrollPane resultPane; private JLabel filelbl; private JLabel pipelinelbl; private JPanel buttonPanel; private JComboBox cmbFileList; private JComboBox pipelines; static final String PROCESS = "Process"; static final String EXIT = "Exit"; static final String LEGACYFILES = "LegacyFiles/"; static final String PIPELINE1 = "Pipeline1"; static final String PIPELINE2 = "Pipeline2"; static final String PIPELINE3 = "Pipeline3"; static final Dimension minimumSize = new Dimension(230, 200); public PipeFilterTestGui(){ super(new GridLayout(1,0)); resultTxt = new JTextArea("Processed File Text\n\n", 6, 20); originalTxt = new JTextArea("Original File Text: \n\n", 6, 20); buildUpScrollGUI(); } private void buildUpScrollGUI(){ // Setup buttonPanel, which contains all buttons and // will be used in btnPane below setUpButtonPanel(); btnPane = new JScrollPane(buttonPanel); btnPane.setMinimumSize(minimumSize); resultPane = new JScrollPane(resultTxt); originPane = new JScrollPane(originalTxt); rightSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); rightSplitPane.setLeftComponent(originPane); rightSplitPane.setRightComponent(resultPane); rightSplitPane.setDividerLocation(190); splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); splitPane.setLeftComponent(btnPane); splitPane.setRightComponent(rightSplitPane); splitPane.setDividerLocation(220); splitPane.setPreferredSize(new Dimension(600, 250)); add(splitPane); setSize(new Dimension(600, 400)); setVisible(true); } private void setUpButtonPanel(){ cmbFileList = new JComboBox(); String[] cl = extractFileList(); setupFileList(cmbFileList,cl); filelbl = new JLabel("Files:"); pipelinelbl = new JLabel("Pipelines:"); pipelines = new JComboBox(); pipelines.addItem(PIPELINE1); pipelines.addItem(PIPELINE2); pipelines.addItem(PIPELINE3); //Create buttons JButton srchButton = new JButton(PROCESS); srchButton.setMnemonic(KeyEvent.VK_S); JButton exitButton = new JButton(EXIT); exitButton.setMnemonic(KeyEvent.VK_X); ButtonListener btnListener = new ButtonListener(); // add action Listener srchButton.addActionListener(btnListener); exitButton.addActionListener(btnListener); buttonPanel = new JPanel(); GridBagLayout gridbag = new GridBagLayout(); buttonPanel.setLayout(gridbag); GridBagConstraints gbc = new GridBagConstraints(); buttonPanel.add(filelbl); buttonPanel.add(cmbFileList); buttonPanel.add(pipelinelbl); buttonPanel.add(pipelines); buttonPanel.add(srchButton); buttonPanel.add(exitButton); gbc.insets.top = 5; gbc.insets.bottom = 5; gbc.insets.left = 5; gbc.insets.right = 5; gbc.anchor = GridBagConstraints.EAST; gbc.gridx = 0; gbc.gridy = 0; gridbag.setConstraints(filelbl, gbc); gbc.anchor = GridBagConstraints.WEST; gbc.gridx = 1; gbc.gridy = 0; gridbag.setConstraints(cmbFileList, gbc); gbc.anchor = GridBagConstraints.EAST; gbc.gridx = 0; gbc.gridy = 1; gridbag.setConstraints(pipelinelbl, gbc); gbc.anchor = GridBagConstraints.WEST; gbc.gridx = 1; gbc.gridy = 1; gridbag.setConstraints(pipelines, gbc); gbc.anchor = GridBagConstraints.EAST; gbc.gridx = 0; gbc.gridy = 1; gbc.insets.left = 2; gbc.insets.right = 2; gbc.insets.top = 25; gbc.anchor = GridBagConstraints.EAST; gbc.gridx = 0; gbc.gridy = 3; gridbag.setConstraints(srchButton, gbc); gbc.anchor = GridBagConstraints.WEST; gbc.gridx = 1; gbc.gridy = 3; gridbag.setConstraints(exitButton, gbc); } /*=========================================*/ /* Get a selected file name from User GUI */ /*=========================================*/ public String getSelectedFile() { return (String) cmbFileList.getSelectedItem(); } /*=================================================*/ /* Get a selected pipeline name from from User GUI */ /*=================================================*/ public String getSelectedPipeline() { return (String) pipelines.getSelectedItem(); } /*================================================*/ /* Extract file names from a diectory on your */ /* computer */ /*================================================*/ public String[] extractFileList(){ File f = new File(LEGACYFILES); String [] fileNames = f.list(); return fileNames; } /*==============================================*/ /* Add car list to combox cmbFileList. Both */ /* objects cmbFileList and files are passed */ /* in from parameters. */ /*==============================================*/ public void setupFileList(JComboBox cmbFileList,String[] files){ for(int k=0; k<files.length; k++){ cmbFileList.addItem(files[k]); } } class ButtonListener implements ActionListener{ String carPrice; public void actionPerformed(ActionEvent e){ String searchResult = null; if (e.getActionCommand().equals(EXIT)){ System.exit(1); } if (e.getActionCommand().equals(PROCESS)){ String selectedFile = getSelectedFile(); String selectedPipeline = getSelectedPipeline(); try{ originalTxt.append("File Name: " + selectedFile+"\n\n"); resultTxt.append("From file: " + selectedFile + "\n"); AssemblyOfPipeLines apline = new AssemblyOfPipeLines(selectedPipeline); apline.assembly(selectedFile, originalTxt, resultTxt); } catch (IOException ex) { } } } } // End of class ButtonListener private static void createAndShowGUI(){ JFrame.setDefaultLookAndFeelDecorated(true); JFrame frame = new JFrame("Pipes and Filters Architecture demo- Legacy File Update"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); PipeFilterTestGui newContentPane = new PipeFilterTestGui(); newContentPane.setOpaque(true); frame.setContentPane(newContentPane); frame.pack(); frame.setVisible(true); } static public void main(String argv[]) { javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } }); }}
/*******************************************************************************/
PipeFilterTestGui
import javax.swing.*;import java.awt.event.*;import java.awt.*;import java.io.File;import java.io.IOException;public class PipeFilterTestGui extends JPanel{ private JScrollPane btnPane; private JSplitPane splitPane; private JSplitPane rightSplitPane; private JTextArea originalTxt; private JTextArea resultTxt; private JScrollPane originPane; private JScrollPane resultPane; private JLabel filelbl; private JLabel pipelinelbl; private JPanel buttonPanel; private JComboBox cmbFileList; private JComboBox pipelines; static final String PROCESS = "Process"; static final String EXIT = "Exit"; static final String LEGACYFILES = "LegacyFiles/"; static final String PIPELINE1 = "Pipeline1"; static final String PIPELINE2 = "Pipeline2"; static final String PIPELINE3 = "Pipeline3"; static final Dimension minimumSize = new Dimension(230, 200); public PipeFilterTestGui(){ super(new GridLayout(1,0)); resultTxt = new JTextArea("Processed File Text\n\n", 6, 20); originalTxt = new JTextArea("Original File Text: \n\n", 6, 20); buildUpScrollGUI(); } private void buildUpScrollGUI(){ // Setup buttonPanel, which contains all buttons and // will be used in btnPane below setUpButtonPanel(); btnPane = new JScrollPane(buttonPanel); btnPane.setMinimumSize(minimumSize); resultPane = new JScrollPane(resultTxt); originPane = new JScrollPane(originalTxt); rightSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); rightSplitPane.setLeftComponent(originPane); rightSplitPane.setRightComponent(resultPane); rightSplitPane.setDividerLocation(190); splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); splitPane.setLeftComponent(btnPane); splitPane.setRightComponent(rightSplitPane); splitPane.setDividerLocation(220); splitPane.setPreferredSize(new Dimension(600, 250)); add(splitPane); setSize(new Dimension(600, 400)); setVisible(true); } private void setUpButtonPanel(){ cmbFileList = new JComboBox(); String[] cl = extractFileList(); setupFileList(cmbFileList,cl); filelbl = new JLabel("Files:"); pipelinelbl = new JLabel("Pipelines:"); pipelines = new JComboBox(); pipelines.addItem(PIPELINE1); pipelines.addItem(PIPELINE2); pipelines.addItem(PIPELINE3); //Create buttons JButton srchButton = new JButton(PROCESS); srchButton.setMnemonic(KeyEvent.VK_S); JButton exitButton = new JButton(EXIT); exitButton.setMnemonic(KeyEvent.VK_X); ButtonListener btnListener = new ButtonListener(); // add action Listener srchButton.addActionListener(btnListener); exitButton.addActionListener(btnListener); buttonPanel = new JPanel(); GridBagLayout gridbag = new GridBagLayout(); buttonPanel.setLayout(gridbag); GridBagConstraints gbc = new GridBagConstraints(); buttonPanel.add(filelbl); buttonPanel.add(cmbFileList); buttonPanel.add(pipelinelbl); buttonPanel.add(pipelines); buttonPanel.add(srchButton); buttonPanel.add(exitButton); gbc.insets.top = 5; gbc.insets.bottom = 5; gbc.insets.left = 5; gbc.insets.right = 5; gbc.anchor = GridBagConstraints.EAST; gbc.gridx = 0; gbc.gridy = 0; gridbag.setConstraints(filelbl, gbc); gbc.anchor = GridBagConstraints.WEST; gbc.gridx = 1; gbc.gridy = 0; gridbag.setConstraints(cmbFileList, gbc); gbc.anchor = GridBagConstraints.EAST; gbc.gridx = 0; gbc.gridy = 1; gridbag.setConstraints(pipelinelbl, gbc); gbc.anchor = GridBagConstraints.WEST; gbc.gridx = 1; gbc.gridy = 1; gridbag.setConstraints(pipelines, gbc); gbc.anchor = GridBagConstraints.EAST; gbc.gridx = 0; gbc.gridy = 1; gbc.insets.left = 2; gbc.insets.right = 2; gbc.insets.top = 25; gbc.anchor = GridBagConstraints.EAST; gbc.gridx = 0; gbc.gridy = 3; gridbag.setConstraints(srchButton, gbc); gbc.anchor = GridBagConstraints.WEST; gbc.gridx = 1; gbc.gridy = 3; gridbag.setConstraints(exitButton, gbc); } /*=========================================*/ /* Get a selected file name from User GUI */ /*=========================================*/ public String getSelectedFile() { return (String) cmbFileList.getSelectedItem(); } /*=================================================*/ /* Get a selected pipeline name from from User GUI */ /*=================================================*/ public String getSelectedPipeline() { return (String) pipelines.getSelectedItem(); } /*================================================*/ /* Extract file names from a diectory on your */ /* computer */ /*================================================*/ public String[] extractFileList(){ File f = new File(LEGACYFILES); String [] fileNames = f.list(); return fileNames; } /*==============================================*/ /* Add car list to combox cmbFileList. Both */ /* objects cmbFileList and files are passed */ /* in from parameters. */ /*==============================================*/ public void setupFileList(JComboBox cmbFileList,String[] files){ for(int k=0; k<files.length; k++){ cmbFileList.addItem(files[k]); } } class ButtonListener implements ActionListener{ String carPrice; public void actionPerformed(ActionEvent e){ String searchResult = null; if (e.getActionCommand().equals(EXIT)){ System.exit(1); } if (e.getActionCommand().equals(PROCESS)){ String selectedFile = getSelectedFile(); String selectedPipeline = getSelectedPipeline(); try{ originalTxt.append("File Name: " + selectedFile+"\n\n"); resultTxt.append("From file: " + selectedFile + "\n"); AssemblyOfPipeLines apline = new AssemblyOfPipeLines(selectedPipeline); apline.assembly(selectedFile, originalTxt, resultTxt); } catch (IOException ex) { } } } } // End of class ButtonListener private static void createAndShowGUI(){ JFrame.setDefaultLookAndFeelDecorated(true); JFrame frame = new JFrame("Pipes and Filters Architecture demo- Legacy File Update"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); PipeFilterTestGui newContentPane = new PipeFilterTestGui(); newContentPane.setOpaque(true); frame.setContentPane(newContentPane); frame.pack(); frame.setVisible(true); } static public void main(String argv[]) { javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } }); }}
/*******************************************************************/
Y2kFixFilter
import java.io.IOException;import java.io.CharArrayWriter;import java.lang.Character;public class Y2kFixFilter extends Filter{ public Y2kFixFilter(Pipe input, Pipe output){ super(input, output); } /*-------------------------------------------*/ /* Read from the input pipe, fix Y2k problem,*/ /* e.g, change 96-12-09 into 1996-12-09 */ /* and then write as chars into outpipe */ /*-------------------------------------------*/ protected void processData(){ try{ CharArrayWriter writer = new CharArrayWriter(); int c = inPipe.read(); while(c != -1){ //not end of file if(((char) c) == '\n'){ //got a complete line String[] words = getALine(writer); words = fixY2kInALine(words); writeALineOfCharsToDownStream(words); writer.reset(); } else{ writer.write(c); } c = inPipe.read(); } outPipe.closePipedOutputStream(); inPipe.closePipedInputStream(); } catch(IOException exc){ exc.printStackTrace(); System.err.println("Error: failed to make y2k update"); System.exit(1); } } private String[] getALine(CharArrayWriter writer){ String line = writer.toString(); String[] words = line.split("\\s"); for(int m=0;m<words.length;m++) System.out.println("Line = "+ words[m]); return words; } private String[] fixY2kInALine(String[] words){ for(int k=0; k< words.length; k++){ //One line if(words[k].length()==8) words[k] = fixY2kInAWord(words[k]); } return words; } private String fixY2kInAWord(String oneWord){ char[] wdArray = oneWord.toCharArray(); char[] wdArray2= new char[10]; String word = null; if((Character.isDigit(wdArray[0])) && (Character.isDigit(wdArray[1])) && (wdArray[2] == '-') && (Character.isDigit(wdArray[3])) && (Character.isDigit(wdArray[4])) && (wdArray[5] == '-') && (Character.isDigit(wdArray[6])) && (Character.isDigit(wdArray[7])) ){ wdArray2[0] = '1'; wdArray2[1] = '9'; wdArray2[2] = wdArray[0]; wdArray2[3] = wdArray[1]; wdArray2[4] = '-'; wdArray2[5] = wdArray[3]; wdArray2[6] = wdArray[4]; wdArray2[7] = '-'; wdArray2[8] = wdArray[6]; wdArray2[9] = wdArray[7]; word = new String(wdArray2); } else{ word = oneWord; } return word; } private void writeALineOfCharsToDownStream(String[] aLine) throws java.io.IOException{ int len = aLine.length; String y2kStr = ""; for(int m=0; m<len; m++){ y2kStr = y2kStr + " " + aLine[m]; } y2kStr += '\n'; char[] chars = y2kStr.toCharArray(); for(int j = 0; j < chars.length; j++){ outPipe.write(chars[j]); } }}
/***************************************************************************/
- 管道--过滤器之千年虫问题
- 千年虫的问题
- 千年虫
- 千年虫
- 千年虫
- 管道过滤器
- **管道---过滤器*
- 问题之--过滤器
- 设计模式之管道和过滤器的应用
- 新一篇: 设计模式之管道和过滤器的应用
- 过滤器 输入输出 管道
- 管道和过滤器
- Linux管道和过滤器
- 批处理与管道-过滤器
- Linux管道和过滤器
- Linux管道和过滤器
- KWIC:管道-过滤器模式.
- 管道-过滤器软件架构
- Android Studio 小技巧/快捷键 合集
- 经典SQL语句——提升篇
- (004)Andriod基本控件
- Adobe AIR提示不允许安转,请与管理员联系解决方案
- writer
- 管道--过滤器之千年虫问题
- 安装python redis模块
- ORACLE数据库ARCHIVELOG,NOARCHIVELOG模式转换简单总结,Redo Log(重做日志)Archive Log(归档日志)
- PHOTON基础入门
- MFC调用win32窗口显示调试信息,使用AllocConsole 函数
- solr6管理页面访问地址
- android使用shape来绘制控件
- 读取android根目录下的文件或文件夹
- JavaScript学习笔记--03