`
<>++<
  • 浏览: 16423 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

Java中各种IOStream以及NIO Chanel的性能比较

阅读更多

      当前流行的JDK版本还是1.5和1.6,拿JDK1.6为例,共有202个包,3777个类(当然加上非Java的这三个类 javax.servlet,javax.servlet.http,javax.servlet.jsp)就是205个包,3817个类以及32043 个方法。但其中大部分的类和方法都是在IO包和图形界面包中,其中SWING和AWT更是占了近1/3的类和方法数,可见Java语言对IO和GUI的重 视程度(尽管GUI的图形界面和性能辜负了SUN和众多的Javaer)。

     回到主题,在IO包中有着众多甚至繁杂的类和方法,来两个 图先:

字节流部分的类层次结构:



 字符流部分的类层次结构:



      那么既然IO里有这么多个操作流,究竟哪一个的性能是最优的呢?其实答案大家都知道,没有最优,只能通过经验和实际情况来选择最适合的流以完成我们的需求。

      其实在IO包里,真正能够称得上“流”的却只有字节流的InputStream和OutputStream以及字符流的Reader和Writer。除此4个基本流以外,其余的类在严格意义上说都不是流 只是在4个基本流的基础上,根据各自的特性进行了特定的封装。接下来本文就拿拷贝文件为例,通过GUI来直观的体现一下几个常有流的性能,因为源文件不是文本文件,所以选择的4个流分别是FileInputStream,BufferedInputStream(系统缓存类),自定义缓冲类以及在JDK1.4中才出现的FileChanel。

1.首先看FileInputStream的例子:

		InputStream fis = null;
		OutputStream fos = null;
		try {
			fis = new FileInputStream(strFileFrom);
			fos = new FileOutputStream(strFileTo, true);
			while (true) {
				int iEOF = fis.read();
				if (iEOF == -1) {
					break;
				}
				fos.write(iEOF);
			}
		} finally {
			if (fis != null) {
				fis.close();
			}
			if (fos != null) {
				fos.close();
			}
		}

FileInputStream类的特点: 从JRE源代码来看该类从文件系统中的某个文件中获得输入字节 ,哪些文件可以取决于定义的主机环境,该类也可以用于读取图像数据之类的原始字节流。也就是说此类还是以每次读取一个字节的形式进行的数据读取,在性能上并没有什么提升。

2.再看BufferedInputStream(系统缓冲类)

		InputStream bis = null;
		OutputStream bos = null;
		try {
			InputStream in = new FileInputStream(strFileFrom);
			bis = new BufferedInputStream(in);
			OutputStream out = new FileOutputStream(strFileTo);
			bos = new BufferedOutputStream(out);
			int iEOF = -1;
			while ((iEOF = bis.read()) != -1) {
				bos.write(iEOF);
			}
		} finally {
			if (bis != null) {
				bis.close();
			}
			if (bos != null) {
				bos.close();
			}
		}

       虽然从以上代码来看,和例子1的实现并没有什么区别,不过这个系统缓冲类在FileInputStream类的基础上进行了Buffered的封装。如下图,buffer size为8192个字节。

    /**
     * Creates a new buffered output stream to write data to the
     * specified underlying output stream.
     *
     * @param   out   the underlying output stream.
     */
    public BufferedOutputStream(OutputStream out) {
	this(out, 8192);
    } 

Java 语言中一般的输出流和输入流(例子1)都是采用的单字节的读取办法,进行数据的IO操作,也就是说每次只能读取一个字节的数据,这种方法显然烦琐而且效率比较低下。 当程序需要读取或者写入一个比较大的文件的时候,比如10M甚至更大,如果每次都是读取或者写入一个字节,那么完成这个操作的次数就会增加了,比如10M 那么就需要10MB次这样的操作了。所以Java语言本身在IO读写的时候已经提供了系统缓冲类来进行此部分的操作,众所周知使用缓冲区进行读写操作的时 候会使得性能有大大的提高。

3.自定义缓冲类:

虽然Java为我们提供了一个缓冲类,但在读取一些文件的时候就未必显得合理从而其性能优势就没法体现,所以根据实际情况写一个自定义的缓冲类来对文件进行读写操作,会进一步的提升性能。将我们的程序的执行时间进一步缩短以给用户良好的相应效果。

		InputStream in = null;
		OutputStream out = null;
		try {
			in = new FileInputStream(strFileFrom);
			out = new FileOutputStream(strFileTo);
			int availableLength = in.available();
			byte[] totalBytes = new byte[availableLength];
			int bytedata = in.read(totalBytes);
			out.write(totalBytes);
		} finally {
			if (in != null) {
				in.close();
			}
			if (out != null) {
				out.close();
			}
		}

 从代码中可以看出,这个自定义的缓冲方法将缓冲size设置成了一个可变的大小来提升性能,当然若已知的文件大小是相对固定的,也可以将缓冲区size设置成固定的长度。例如: byte [] buffer =  new byte [4096 ];

PS:因为本地的JDK环境是1.6的 所以对文件流还是进行了显式关闭的操作。

4.NIO包中的FileChanel

		FileInputStream fin = new FileInputStream(strFileFrom);
		FileOutputStream fout = new FileOutputStream(strFileTo);
		FileChannel inChannel = fin.getChannel();
		FileChannel outChannel = fout.getChannel();
		ByteBuffer buffer = ByteBuffer.allocate(1024);
		while (true) {
			int ret = inChannel.read(buffer);
			if (ret == -1) {
				break;
			}
			buffer.flip();
			outChannel.write(buffer);
			buffer.clear(); 
		}

 FileChanel的好处是:以下引自戒子的博文

【多个并发线程可安全地 使用文件通道,可随时调用关闭方法 ,正如Channel接口中所指定,对于涉及通道位置或者可以更改文件大小的操作,在任意给定时间只能进行一个这样的操作 ,如果尝试在第一操作仍在进行时发起第二个操作,则会导致在第一个操作完成之前阻塞 第二个操作。可以并发处理其他操作,特别是采用显示位置的操作,但是否并发处理则取决于系统,因此是未指定的。 确保此类的实例所提供的文件视图与同一程序中其他实例所提供的相同文件视图是一致的。但是,此类的实例所提供的视图不一定与其他并发运行的程序所看到的视图一致,这取决于底层操作系统所执行的缓冲策略和各种网络文件系统协议所引入的延迟。 不管其他程序是以何种语言编写的,而且也不管是运行在相同机器 还是不同机器 上都是如此。此种不一致的确切性质取决于系统 ,因此是未指定的。此类没有定义打开现有文件或创建新文件的方法,以后的版本中可能添加这些方法。在此版本中,可从现有的  FileInputStream、FileOutputStream 或 RandomAccessFile   对象获得文件通道,方法是调用该对象的 getChannel 方法,这会返回一个连接到相同底层文件的文件通道。 文件通道的状态与其 getChannel 返回该通道的对象密切相关 。显式或者通过读取或写入字节来更改通道的位置将更改发起对象的文件位置,反之亦然。通过文件通道更改此文件的长度将更改通过发起对象看到的长度,反之亦然。通过写入字节更改此文件的内容将更改发起对象所看到的内容,反之亦然。 此类在各种情况下指定要求“允许读取操作”“允许写入操作”“允许读取和写入操作” 的某个实例。通过  FileInputStream  实例的 getChannel 方法所获得的通道将允许进行读取操作。通过  FileOutputStream  实例的 getChannel 方法所获得的通道将允许进行写入操作。最后,如果使用模式  "r"  创建  RandomAccessFile  实例,则通过该实例的 getChannel 方法所获得的通道将允许进行读取操作,如果使用模式  "rw"  创建实例,则获得的通道将允许进行读取和写入操作。 如果从文件输出流中获得了允许进行写入操作的文件通道,并且该输出流是通过调用  FileOutputStream (File, boolean ) 构造方法且为第二个参数传入  true  来创建的,则该文件通道可能处于添加模式 。在此模式中,每次调用相关的写入操作都会首先将位置移到文件的末尾,然后再写入请求的数据。在单个原子操作中是否移动位置和写入数据是与系统相关的,因此是未指定的。 】

最近翻看了一下NIO包中的方法。发现大部分方法都没有Java语言实现IO操作,而是用的C语言。那在性能上就不言而喻了。

接下来试着拷贝一个5MB的文件,看看其性能如何?



 可以看出, 没有任何封装的FileInputStream的效率是很差的吧?

再对一个33MB的文件进行拷贝,试试后三种流的性能.



 可以看出系统的缓冲流与自定义的缓冲流的性能还是有些区别的,但后两者的差距不是很大,最后来个512MB的文件(当然因为这个文件比较大,所以自定义的缓冲流的size设置成了默认大小8192的100倍):



 能够看出,适当的调整缓冲区的size会给性能带来一些提升,而新IO包的FileChanel类的性能优势也会随着源文件不断变大而逐渐明显。当然不排除一些测试环境的问题,但大致的差距应该如图所示。大家可以自行做个比较,下面把源代码附上供大家参考:

package ui;

import java.awt.BorderLayout;
import java.awt.Checkbox;
import java.awt.Container;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JSplitPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

public class StreamTest implements ActionListener {

	// define
	private JFrame jfMain;
	private Container ct;
	private JPanel jpSelect, jpOpration, jpProcessBars, jpResults, jpProcessFIS,
			jpProcessNIO, jpProcessBIS, jpProcessUDB;
	private JSplitPane jspMain;
	private JMenuBar jmbMain;
	private JMenu jmTheme, jmExit;
	private JMenuItem jmiWindows, jmiWindowsClassic, jmiNimbus, jmiCDEMotif,
			jmiMetal, jmiGTK, jmiExit;
	private JFileChooser jfcSelect, jfcDirectory;

	private JTextField jtfSourceFile, jtfTargetDirectory;
	private JButton jbSourceFile, jbTargetDirectory, jbCopyStart, jbShowAnswer;

	private JLabel jlToolTips;
	private Checkbox cbFIS, cbNIO, cbBIS, cbUDB;

	private JProgressBar jpbFIS, jpbNIO, jpbBIS, jpbUDB;

	private final int nLeft = 10;
	private final int nTop = 10;
	private final int nHeight = 30;
	private final int nWidth = 500;

	private int nTime1Lasts;
	private int nTime2Lasts;
	private int nTime3Lasts;
	private int nTime4Lasts;
	private int nMaxTimeLasts;

	private JTextField jtfFIS, jtfNIO, jtfBIS, jtfUDB;

	private static StreamTest rw;
	private String strFileName;
	private String strSuffix;

	private static final String CDEMOTIF = "com.sun.java.swing.plaf.motif.MotifLookAndFeel";
	private static final String GTK = "com.sun.java.swing.plaf.gtk.GTKLookAndFeel";
	private static final String METAL = "javax.swing.plaf.metal.MetalLookAndFeel";
	private static final String NIMBUS = "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel";
	private static final String WINDOWS = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
	private static final String WINDOWSCLASSIC = "com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel";

	public StreamTest() {

		// initComponent
		initComponent();

		// initLayout
		initLayout();

		// addListener
		addListener();
	}

	private void initComponent() {
		jfMain = new JFrame("StreamPlus1.1_____by imp");
		ct = jfMain.getContentPane();

		jfcSelect = new JFileChooser();
		jfcSelect.setDialogTitle("choose a file which u want");
		jfcSelect.setFileSelectionMode(JFileChooser.FILES_ONLY);
		jfcDirectory = new JFileChooser();
		jfcDirectory
				.setDialogTitle("choose a directory where the file(s) copy to");
		jfcDirectory.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);

		jmbMain = new JMenuBar();
		jmTheme = new JMenu("Theme");
		jmExit = new JMenu("Exit");
		jmiCDEMotif = new JMenuItem("CDEMotif");
		jmiGTK = new JMenuItem("GTK");
		jmiMetal = new JMenuItem("Metal");
		jmiNimbus = new JMenuItem("Nimbus");
		jmiWindows = new JMenuItem("Windows");
		jmiWindowsClassic = new JMenuItem("WindowsClassic");

		jmiExit = new JMenuItem("Exit");

		jspMain = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true);
		jpSelect = new JPanel(null);

		jpOpration = new JPanel(new BorderLayout());
		jpProcessBars = new JPanel(new GridLayout(4, 1));
		jpResults = new JPanel(new GridLayout(4, 1));
		jpProcessFIS = new JPanel(new BorderLayout());
		jpProcessNIO = new JPanel(new BorderLayout());
		jpProcessBIS = new JPanel(new BorderLayout());
		jpProcessUDB = new JPanel(new BorderLayout());

		jtfSourceFile = new JTextField();
		jtfTargetDirectory = new JTextField();
		jbSourceFile = new JButton("Source File");
		jbSourceFile.setToolTipText("Choose Source File");
		jbTargetDirectory = new JButton("Target Directory");
		jbTargetDirectory.setToolTipText("Choose Target Directory");

		jlToolTips = new JLabel("Click Button[Copy] to copy files");
		jbCopyStart = new JButton("Copy");
		jbShowAnswer = new JButton("Show");

		cbFIS = new Checkbox("FileInputStream         ", false);
		cbNIO = new Checkbox("NIO[FileChannel]      ", true);
		cbBIS = new Checkbox("BufferedInputStream", true);
		cbUDB = new Checkbox("User-defined Buffer  ", true);

		jpbFIS = new JProgressBar();
		jpbNIO = new JProgressBar();
		jpbBIS = new JProgressBar();
		jpbUDB = new JProgressBar();

		jtfFIS = new JTextField();
		jtfNIO = new JTextField();
		jtfBIS = new JTextField();
		jtfUDB = new JTextField();

		jtfFIS.setColumns(5);
		jtfFIS.setHorizontalAlignment(JLabel.RIGHT);
		jtfNIO.setHorizontalAlignment(JLabel.RIGHT);
		jtfBIS.setHorizontalAlignment(JLabel.RIGHT);
		jtfUDB.setHorizontalAlignment(JLabel.RIGHT);

		jtfFIS.setEditable(false);
		jtfNIO.setEditable(false);
		jtfBIS.setEditable(false);
		jtfUDB.setEditable(false);

		strFileName = new String("");
		strSuffix = new String("");
	}

	private void initLayout() {

		// set Layout
		ct.setLayout(new BorderLayout());
		ct.add(jmbMain, BorderLayout.NORTH);
		ct.add(jspMain, BorderLayout.CENTER);

		// add jmbMain
		jmbMain.add(jmTheme);
		jmbMain.add(jmExit);

		jmTheme.add(jmiCDEMotif);
		jmTheme.add(jmiGTK);
		jmTheme.add(jmiMetal);
		jmTheme.add(jmiNimbus);
		jmTheme.add(jmiWindows);
		jmTheme.add(jmiWindowsClassic);
		jmExit.add(jmiExit);

		// jspMain
		jspMain.setTopComponent(jpSelect);
		jspMain.setBottomComponent(jpOpration);
		jspMain.setResizeWeight(0.7);
		jspMain.setDividerSize(3);

		// jpSelect.add()
		jpSelect.add(jtfSourceFile);
		jpSelect.add(jbSourceFile);
		jpSelect.add(jtfTargetDirectory);
		jpSelect.add(jbTargetDirectory);

		jpSelect.add(jlToolTips);
		jpSelect.add(jbCopyStart);
		jpSelect.add(jbShowAnswer);
		jbShowAnswer.setEnabled(false);

		// jpOpration.add()
		jpOpration.add(jpProcessBars, BorderLayout.CENTER);
		jpOpration.add(jpResults, BorderLayout.EAST);
		jpProcessBars.add(jpProcessFIS);
		jpProcessBars.add(jpProcessBIS);
		jpProcessBars.add(jpProcessUDB);
		jpProcessBars.add(jpProcessNIO);

		jpResults.add(jtfFIS);
		jpResults.add(jtfBIS);
		jpResults.add(jtfUDB);
		jpResults.add(jtfNIO);

		// jpProcess1.add()
		jpProcessFIS.add(cbFIS, BorderLayout.WEST);
		jpProcessFIS.add(jpbFIS, BorderLayout.CENTER);

		jpProcessNIO.add(cbNIO, BorderLayout.WEST);
		jpProcessNIO.add(jpbNIO, BorderLayout.CENTER);

		jpProcessBIS.add(cbBIS, BorderLayout.WEST);
		jpProcessBIS.add(jpbBIS, BorderLayout.CENTER);

		jpProcessUDB.add(cbUDB, BorderLayout.WEST);
		jpProcessUDB.add(jpbUDB, BorderLayout.CENTER);

		// setBounds
		jtfSourceFile.setBounds(nLeft, nTop, nWidth, nHeight);
		jbSourceFile.setBounds(nWidth + 2 * nLeft, nTop, 140, nHeight);

		jtfTargetDirectory
				.setBounds(nLeft, nHeight + 2 * nTop, nWidth, nHeight);

		jbTargetDirectory.setBounds(nWidth + 2 * nLeft, nHeight + 2 * nTop,
				140, nHeight);

		jlToolTips.setBounds(nLeft, 2 * nHeight + 3 * nTop, 350, nHeight);

		jbCopyStart.setBounds(new Rectangle(nWidth / 2 + 12 * nLeft, 2
				* nHeight + 3 * nTop, 140, nHeight));

		jbShowAnswer.setBounds(new Rectangle(nWidth + 2 * nLeft, 2 * nHeight
				+ 3 * nTop, 140, nHeight));

		// set size and visible
		jfMain.setSize(700, 380);
		jfMain.setResizable(false);
		jfMain.setVisible(true);
	}

	private void addListener() {
		jbCopyStart.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {

				// init
				jtfFIS.setText("");
				jtfNIO.setText("");
				jtfBIS.setText("");
				jtfUDB.setText("");
				nTime1Lasts = 0;
				nTime2Lasts = 0;
				nTime3Lasts = 0;
				nTime4Lasts = 0;

				File fileSource = new File(jtfSourceFile.getText());
				File fileTarget = new File(jtfTargetDirectory.getText());
				if (null != fileSource && fileSource.isFile()
						&& null != fileTarget && fileTarget.isDirectory()) {
					jlToolTips.setText("Copying Files...");
					int nIndex = jtfSourceFile.getText().lastIndexOf(".");
					int nIndexS = jtfSourceFile.getText().lastIndexOf("\\");
					strFileName = jtfSourceFile.getText().substring(
							nIndexS + 1, nIndex);
					System.out.println(strFileName);
					strSuffix = jtfSourceFile.getText().substring(nIndex);
					try {
						// setEnabled
						jbCopyStart.setEnabled(false);

						if (cbFIS.getState()) {
							// readByFileStream
							rw.readByFileInputStream(jtfSourceFile.getText(),
									jtfTargetDirectory.getText().concat(
											"/" + strFileName + "_FIS").concat(
											strSuffix));
						}

						if (cbBIS.getState()) {
							// readByBufferedInputStream
							rw.readByBufferedInputStream(jtfSourceFile
									.getText(), jtfTargetDirectory.getText()
									.concat("/" + strFileName + "_BIS").concat(
											strSuffix));
						}

						if (cbUDB.getState()) {
							// readByUserDefinedBuffer
							rw.readByUserDefinedBuffer(jtfSourceFile.getText(),
									jtfTargetDirectory.getText().concat(
											"/" + strFileName + "_UDB").concat(
											strSuffix));
						}

						if (cbNIO.getState()) {
							// readByNIO
							rw.readByNIO(jtfSourceFile.getText(),
									jtfTargetDirectory.getText().concat(
											"/" + strFileName + "_BR").concat(
											strSuffix));
						}
						// setEnabled
						jbCopyStart.setEnabled(true);
						jbShowAnswer.setEnabled(true);
					} catch (IOException e1) {
						e1.printStackTrace();
					}
					jlToolTips
							.setText("Copy Files Successed, Click Button[Show] To Show Results");
				}
			}
		});

		jbShowAnswer.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				jbShowAnswer.setEnabled(false);
				jtfFIS.setText(String.valueOf(nTime1Lasts).concat("ms"));
				jtfNIO.setText(String.valueOf(nTime2Lasts).concat("ms"));
				jtfBIS.setText(String.valueOf(nTime3Lasts).concat("ms"));
				jtfUDB.setText(String.valueOf(nTime4Lasts).concat("ms"));

				showAnswer();
				jbShowAnswer.setEnabled(true);
			}
		});

		jbSourceFile.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				jfcSelect.showOpenDialog(jfMain);
				File f = jfcSelect.getSelectedFile();
				if (null != f) {
					String strPath = f.getPath();
					jtfSourceFile.setText(strPath);
					int nIndex = strPath.lastIndexOf(".");
					strSuffix = strPath.substring(nIndex);
				}
			}
		});

		jbTargetDirectory.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				jfcDirectory.showOpenDialog(jfMain);
				File f = jfcDirectory.getSelectedFile();
				if (null != f) {
					String strPath = f.getPath();
					jtfTargetDirectory.setText(strPath);
				}
			}
		});

		jmiCDEMotif.addActionListener(this);
		jmiGTK.addActionListener(this);
		jmiMetal.addActionListener(this);
		jmiNimbus.addActionListener(this);
		jmiWindows.addActionListener(this);
		jmiWindowsClassic.addActionListener(this);

		jmiExit.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				jfMain.setVisible(false);
				jfMain.dispose();
				System.exit(0);
			}
		});
	}

	private void showAnswer() {
		jpbFIS.setMinimum(0);
		jpbNIO.setMinimum(0);
		jpbBIS.setMinimum(0);
		jpbUDB.setMinimum(0);
		nMaxTimeLasts = Math.max(Math.max(nTime1Lasts, nTime2Lasts), Math.max(
				nTime3Lasts, nTime4Lasts)) / 100;
		jpbFIS.setMaximum(nMaxTimeLasts);
		jpbNIO.setMaximum(nMaxTimeLasts);
		jpbBIS.setMaximum(nMaxTimeLasts);
		jpbUDB.setMaximum(nMaxTimeLasts);

		// show the percent
		jpbFIS.setStringPainted(true);
		jpbNIO.setStringPainted(true);
		jpbBIS.setStringPainted(true);
		jpbUDB.setStringPainted(true);

		Thread thread = new Thread(new Runnable() {
			public void run() {
				try {
					for (int i = 0; i <= nTime1Lasts / 100; i++) {
						jpbFIS.setValue(i);
						Thread.sleep(100);
					}

					for (int i = 0; i <= nTime3Lasts / 100; i++) {
						jpbBIS.setValue(i);
						Thread.sleep(100);
					}

					for (int i = 0; i <= nTime4Lasts / 100; i++) {
						jpbUDB.setValue(i);
						Thread.sleep(100);
					}
					
					for (int i = 0; i <= nTime2Lasts / 100; i++) {
						jpbNIO.setValue(i);
						Thread.sleep(100);
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		});
		thread.start();
	}

	/**
	 * Read file by FileInputStream 不使用缓冲区直接读写
	 * 
	 * @param strFileFrom
	 * @param strFileTo
	 * @throws IOException
	 */
	private void readByFileInputStream(String strFileFrom, String strFileTo)
			throws IOException {
		long lStartTime = System.currentTimeMillis();

		InputStream fis = null;
		OutputStream fos = null;
		try {
			fis = new FileInputStream(strFileFrom);
			fos = new FileOutputStream(strFileTo, true);
			while (true) {
				int iEOF = fis.read();
				if (iEOF == -1) {
					break;
				}
				fos.write(iEOF);
			}
		} finally {
			if (fis != null) {
				fis.close();
			}
			if (fos != null) {
				fos.close();
			}
		}

		long lEndTime = System.currentTimeMillis();
		System.out.println("readByFileStream() time: "
				+ (lEndTime - lStartTime) + "ms");
		nTime1Lasts = (int) (lEndTime - lStartTime);
	}

	/**
	 * Read file by readByNIO
	 * 
	 * @param strFileFrom
	 * @param strFileTo
	 * @throws IOException
	 */
	private void readByNIO(String strFileFrom, String strFileTo)
			throws IOException {
		long lStartTime = System.currentTimeMillis();
		FileInputStream fin = new FileInputStream(strFileFrom);
		FileOutputStream fout = new FileOutputStream(strFileTo);
		FileChannel inChannel = fin.getChannel();
		FileChannel outChannel = fout.getChannel();
		ByteBuffer buffer = ByteBuffer.allocate(1024);
		while (true) {
			int ret = inChannel.read(buffer);
			if (ret == -1) {
				break;
			}
			buffer.flip(); // 该方法为父类Buffer的方法
			outChannel.write(buffer);
			buffer.clear(); // 该方法为父类Buffer的方法
		}

		long lEndTime = System.currentTimeMillis();
		System.out.println("readByNIO() time: "
				+ (lEndTime - lStartTime) + "ms");
		nTime2Lasts = (int) (lEndTime - lStartTime);
	}

	/**
	 * Read file by BufferedInputStream 使用系统自带缓冲类读写
	 * 
	 * @param strFileFrom
	 * @param strFileTo
	 * @throws IOException
	 */
	private void readByBufferedInputStream(String strFileFrom, String strFileTo)
			throws IOException {
		long lStartTime = System.currentTimeMillis();

		InputStream bis = null;
		OutputStream bos = null;
		try {
			InputStream in = new FileInputStream(strFileFrom);
			bis = new BufferedInputStream(in);
			OutputStream out = new FileOutputStream(strFileTo);
			bos = new BufferedOutputStream(out);
			int iEOF = -1;
			while ((iEOF = bis.read()) != -1) {
				bos.write(iEOF);
			}
		} finally {
			if (bis != null) {
				bis.close();
			}
			if (bos != null) {
				bos.close();
			}
		}

		long lEndTime = System.currentTimeMillis();
		System.out.println("readByBufferedInputStream() time: "
				+ (lEndTime - lStartTime) + "ms");
		nTime3Lasts = (int) (lEndTime - lStartTime);
	}

	/**
	 * Read file by buffer array(user-defined buffer) 通过自定义缓冲区读写文件方法
	 * 
	 * @param strFileFrom
	 * @param strFileTo
	 * @throws IOException
	 */
	private void readByUserDefinedBuffer(String strFileFrom, String strFileTo)
			throws IOException {
		long lStartTime = System.currentTimeMillis();

//		InputStream in = null;
//		OutputStream out = null;
//		try {
//			in = new FileInputStream(strFileFrom);
//			out = new FileOutputStream(strFileTo);
//			int availableLength = in.available();
//			byte[] totalBytes = new byte[availableLength];
////			byte[] totalBytes = new byte[];
//			int bytedata = in.read(totalBytes);
//			out.write(totalBytes);
//		} finally {
//			if (in != null) {
//				in.close();
//			}
//			if (out != null) {
//				out.close();
//			}
//		}

		// TODO 512MB
		InputStream bis = null;
		OutputStream bos = null;
		try {
			InputStream in = new FileInputStream(strFileFrom);
			bis = new BufferedInputStream(in, 819200);
			OutputStream out = new FileOutputStream(strFileTo);
			bos = new BufferedOutputStream(out);
			int iEOF = -1;
			while ((iEOF = bis.read()) != -1) {
				bos.write(iEOF);
			}
		} finally {
			if (bis != null) {
				bis.close();
			}
			if (bos != null) {
				bos.close();
			}
		}
		//TODO
		
		
		long lEndTime = System.currentTimeMillis();
		System.out.println("readByBufferArray() time: "
				+ (lEndTime - lStartTime) + "ms");
		nTime4Lasts = (int) (lEndTime - lStartTime);
	}

	public void actionPerformed(ActionEvent e) {
		try {
			Object source = e.getSource();
			if (source == jmiCDEMotif) {
				UIManager.setLookAndFeel(CDEMOTIF);
				SwingUtilities.updateComponentTreeUI(jfMain);
			} else if (source == jmiGTK) {
				UIManager.setLookAndFeel(GTK);
				SwingUtilities.updateComponentTreeUI(jfMain);
			} else if (source == jmiMetal) {
				UIManager.setLookAndFeel(METAL);
				SwingUtilities.updateComponentTreeUI(jfMain);
			} else if (source == jmiNimbus) {
				UIManager.setLookAndFeel(NIMBUS);
				SwingUtilities.updateComponentTreeUI(jfMain);
			} else if (source == jmiWindows) {
				UIManager.setLookAndFeel(WINDOWS);
				SwingUtilities.updateComponentTreeUI(jfMain);
			} else {
				UIManager.setLookAndFeel(WINDOWSCLASSIC);
				SwingUtilities.updateComponentTreeUI(jfMain);
			}
		} catch (Exception ex) {
		}
	}

	public static void main(String args[]) {

		try {
			UIManager.setLookAndFeel(NIMBUS);
		} catch (Exception e) {
		}
		rw = new StreamTest();
	}
}

  欢迎讨论指正!^_^

 

 

  • 大小: 269.2 KB
  • 大小: 109.3 KB
  • 大小: 26.7 KB
  • 大小: 27.9 KB
  • 大小: 27.1 KB
分享到:
评论
5 楼 wayne0332 2016-04-15  
最近在学习NIO,找到了这篇文章,所以想问一下楼主,这个测试程序是在一个Java进程里跑的吧,有考虑到底层操作系统对io的优化吗,段时间内对同一个文件进行读取,系统内核可能会对某些文件内容进行缓存,导致第一次进行了实际的磁盘io而后续的使用内核缓存,所以大部分情况下第一次读取文件会比较慢,楼主有试过换一下测试顺序吗,比如将NIO放在第一个
4 楼 wv1124 2013-01-06  
如果复制600M文件,JVM就挂了
int availableLength = in.available();
返回文件大小,你要创建这么大的缓冲区么?
3 楼 <>++< 2011-05-10  
windloverain 写道
不错不错。刚学搞不清楚到底该用哪个。

大家能用上就好
2 楼 windloverain 2011-04-29  
不错不错。刚学搞不清楚到底该用哪个。
1 楼 aspnetdb 2011-04-07  
文章写的不错。

相关推荐

    c++中<iostream>库的底层实现

    c++中&lt;iostream&gt;库的底层实现 c++中&lt;iostream&gt;库的底层实现 c++中&lt;iostream&gt;库的底层实现 c++中&lt;iostream&gt;库的底层实现 c++中&lt;iostream&gt;库的底层实现 c++中&lt;iostream&gt;库的底层实现 c++中&lt;iostream&gt;库的底层实现 c++...

    iostream 和 iostream.h的区别

    在C++编程语言中,`iostream`与`iostream.h`之间的差异是理解标准输入输出流库的关键之一。本文将深入探讨这两个概念的区别,并通过详细解释它们的背景、用途以及在现代C++编程中的地位,帮助读者更好地理解这些基础...

    C语言头文件 IOSTREAM.H

    C语言头文件 IOSTREAM.HC语言头文件 IOSTREAM.HC语言头文件 IOSTREAM.HC语言头文件 IOSTREAM.HC语言头文件 IOSTREAM.HC语言头文件 IOSTREAM.HC语言头文件 IOSTREAM.HC语言头文件 IOSTREAM.HC语言头文件 IOSTREAM.HC...

    C语言头文件 IOSTREAM

    C语言头文件 IOSTREAMC语言头文件 IOSTREAMC语言头文件 IOSTREAMC语言头文件 IOSTREAMC语言头文件 IOSTREAMC语言头文件 IOSTREAMC语言头文件 IOSTREAMC语言头文件 IOSTREAMC语言头文件 IOSTREAMC语言头文件 IOSTREAM...

    头文件iostream 与iostream.h区别

    在C++编程中,`iostream`和`iostream.h`是两个重要的头文件,它们对于输入输出流的操作至关重要。本文将深入探讨这两个头文件之间的区别及其对C++程序的影响。 #### 1. C++标准库的发展 - **C++98**:在早期的C++...

    Test_IOStream.java

    Test_IOStream.java

    C++Iostream的实例

    C++ Iostream 是C++标准库中的一个核心部分,它为输入输出操作提供了强大的支持。在C++中,iostream库取代了C语言中的stdio库,提供了面向对象的输入输出处理方式,使得输入输出操作更加直观和易用。下面将详细讨论...

    java IO stream

    Java IO流是Java平台中处理输入输出操作的核心机制。它允许程序与外部设备(如硬盘、网络、内存等)进行数据传输。...通过理解不同类型的流以及它们之间的关系,开发者可以有效地在Java程序中处理数据传输。

    vc++2008编译不了#include头文件

    最初,在 C++ 的早期版本中,标准 I/O 库文件被命名为 `&lt;iostream.h&gt;`,但随着 C++98 标准的发布,C++ 标准库进行了重大的结构调整和命名空间的引入,从而 `&lt;iostream.h&gt;` 被 `&lt;iostream&gt;` 替代,并且所有的标准...

    C++中iostream.h和iostream的区别共3页

    在C++编程语言中,`iostream.h`和`iostream`都是与输入输出流相关的头文件,但它们在C++的不同版本和标准中有着显著的区别。理解这些差异对于编写兼容不同编译器和遵循不同标准的代码至关重要。 首先,`iostream.h`...

    详解iostream

    我们从一开始就一直在利用C++的输入输出在做着各种练习,输入输出是由iostream库提供的,所以讨论此标准库是有必要的,它与C语言的stdio库不同,它从一开始就是用多重继承与虚拟继承实现的面向对象的层次结构,作为...

    C++ iostream

    C++的`iostream`库是C++标准库的一部分,它提供了强大的输入输出功能,使得程序能够与用户交互,处理文件,以及控制数据流。本文将深入解析`iostream`库的关键概念,包括基本的输入输出流操作,标准流对象,以及文件...

    POJ 1751 求最小生成树prim算法(JAVA)

    总的来说,POJ 1751挑战要求程序员用Prim算法解决求解最小生成树的问题,这涉及到对图论的理解,以及在Java环境中实现和测试该算法的能力。对于想要提升数据结构和算法技能的开发者来说,这是一个很好的实践题目。...

    Android IOStream实例操作源代码.rar

    在Android开发中,IOStream(输入/输出流)是一个重要的概念,它用于处理设备、文件、网络等数据传输。这个“Android IOStream实例操作源代码”压缩包是为初学者提供的一系列示例,帮助他们理解和掌握Android环境下...

    java调用c c++程序实例

    本实例探讨了如何在Java中调用C/C++编写的程序,以实现两者之间的交互。 首先,Java调用C/C++程序的主要技术是通过Java Native Interface (JNI)。JNI是Java平台的一部分,允许Java代码和其他语言写的代码进行交互。...

    c++ iostream 教程 PPT

    C++ solution is a set of classes defined in the iostream and fstream header files.

    vc++iostream.h&fstream;.h.rar

    在C++编程中,`iostream.h` 和 `fstream.h` 是两个旧的头文件,它们在C++标准库的发展过程中逐渐被更新的标准头文件所替代。`iostream.h` 主要包含输入/输出流的基本功能,而`fstream.h` 用于处理文件流。然而,这两...

    IOSTREAM.H

    IOSTREAM.H文件VS2003后没的

    iostream.h头文件

    解决部分源文件无法打开的问题,在VS2015的环境下,部分源文件无法打开,可能是源文件库中的源文件缺失了.h后缀,从程序的安装路径中找到文集库,给对应的源文件加上后缀就可以了

Global site tag (gtag.js) - Google Analytics