Java文件讀寫IO/NIO及性能比較詳細(xì)代碼及總結(jié)
干Java這么久,一直在做WEB相關(guān)的項(xiàng)目,一些基礎(chǔ)類差不多都已經(jīng)忘記。經(jīng)常想得撿起,但總是因?yàn)橐恍┰?,不能如愿?/p>
其實(shí)不是沒有時(shí)間,只是有些時(shí)候疲于總結(jié),今得空,下定決心將丟掉的都給撿起來。
文件讀寫是一個(gè)在項(xiàng)目中經(jīng)常遇到的工作,有些時(shí)候是因?yàn)榫S護(hù),有些時(shí)候是新功能開發(fā)。我們的任務(wù)總是很重,工作節(jié)奏很快,快到我們不能停下腳步去總結(jié)。
文件讀寫有以下幾種常用的方法
1、字節(jié)讀寫(InputStream/OutputStream)
2、字符讀?。‵ileReader/FileWriter)
3、行讀?。˙ufferedReader/BufferedWriter)
代碼(以讀取為例):
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
/**
* <b>文件讀取類</b><br />
* 1、按字節(jié)讀取文件內(nèi)容<br />
* 2、按字符讀取文件內(nèi)容<br />
* 3、按行讀取文件內(nèi)容<br />
* @author qin_xijuan
*
*/
public class FileOperate {
private static final String FILE_PATH = "d:/work/the List of Beautiful Music.txt";
/**
* 以字節(jié)為單位讀取文件內(nèi)容
* @param filePath:需要讀取的文件路徑
*/
public static void readFileBybyte(String filePath) {
File file = new File(filePath);
// InputStream:此抽象類是表示字節(jié)輸入流的所有類的超類。
InputStream ins = null ;
try{
// FileInputStream:從文件系統(tǒng)中的某個(gè)文件中獲得輸入字節(jié)。
ins = new FileInputStream(file);
int temp ;
// read():從輸入流中讀取數(shù)據(jù)的下一個(gè)字節(jié)。
while((temp = ins.read())!=-1){
System.out.write(temp);
}
}
catch(Exception e){
e.getStackTrace();
}
finally{
if (ins != null){
try{
ins.close();
}
catch(IOException e){
e.getStackTrace();
}
}
}
}
/**
* 以字符為單位讀取文件內(nèi)容
* @param filePath
*/
public static void readFileByCharacter(String filePath){
File file = new File(filePath);
// FileReader:用來讀取字符文件的便捷類。
FileReader reader = null;
try{
reader = new FileReader(file);
int temp ;
while((temp = reader.read()) != -1){
if (((char) temp) != '\r') {
System.out.print((char) temp);
}
}
}
catch(IOException e){
e.getStackTrace();
}
finally{
if (reader != null){
try {
reader.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 以行為單位讀取文件內(nèi)容
* @param filePath
*/
public static void readFileByLine(String filePath){
File file = new File(filePath);
// BufferedReader:從字符輸入流中讀取文本,緩沖各個(gè)字符,從而實(shí)現(xiàn)字符、數(shù)組和行的高效讀取。
BufferedReader buf = null;
try{
// FileReader:用來讀取字符文件的便捷類。
buf = new BufferedReader(new FileReader(file));
// buf = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
String temp = null ;
while ((temp = buf.readLine()) != null ){
System.out.println(temp);
}
}
catch(Exception e){
e.getStackTrace();
}
finally{
if(buf != null){
try{
buf.close();
}
catch (IOException e) {
e.getStackTrace();
}
}
}
}
public static void main(String args[]) {
readFileBybyte(FILE_PATH);
readFileByCharacter(FILE_PATH);
readFileByLine(FILE_PATH);
}
}
//-----------------------------------------------------------------分割線-----------------------------------------------------------------------------
再經(jīng)過兩位同行的提點(diǎn)下,我對(duì)之前寫的文件做了點(diǎn)修改,并通過讀寫一個(gè)1.2M的文本文件來測試各方法的性能。從多次測試結(jié)果來看,行讀寫卻是是Java.nio更有效率。
經(jīng)過修改之后的代碼如下:
package com.waddell.basic;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/**
* <b>文件讀取類</b><br />
* 1、按字節(jié)讀取文件內(nèi)容<br />
* 2、按字符讀取文件內(nèi)容<br />
* 3、按行讀取文件內(nèi)容<br />
*
* @author qin_xijuan
*
*/
public class FileOperate {
private static final String FILE_PATH = "d:/work/jipinwodi.txt";
/**
* 以字節(jié)為單位讀寫文件內(nèi)容
*
* @param filePath
* :需要讀取的文件路徑
*/
public static void readFileBybyte(String filePath) {
File file = new File(filePath);
// InputStream:此抽象類是表示字節(jié)輸入流的所有類的超類。
InputStream ins = null;
OutputStream outs = null;
try {
// FileInputStream:從文件系統(tǒng)中的某個(gè)文件中獲得輸入字節(jié)。
ins = new FileInputStream(file);
outs = new FileOutputStream("d:/work/readFileByByte.txt");
int temp;
// read():從輸入流中讀取數(shù)據(jù)的下一個(gè)字節(jié)。
while ((temp = ins.read()) != -1) {
outs.write(temp);
}
}
catch (Exception e) {
e.getStackTrace();
}
finally {
if (ins != null && outs != null) {
try {
outs.close();
ins.close();
}
catch (IOException e) {
e.getStackTrace();
}
}
}
}
/**
* 以字符為單位讀寫文件內(nèi)容
*
* @param filePath
*/
public static void readFileByCharacter(String filePath) {
File file = new File(filePath);
// FileReader:用來讀取字符文件的便捷類。
FileReader reader = null;
FileWriter writer = null;
try {
reader = new FileReader(file);
writer = new FileWriter("d:/work/readFileByCharacter.txt");
int temp;
while ((temp = reader.read()) != -1) {
writer.write((char)temp);
}
}
catch (IOException e) {
e.getStackTrace();
}
finally {
if (reader != null && writer != null) {
try {
reader.close();
writer.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 以行為單位讀寫文件內(nèi)容
*
* @param filePath
*/
public static void readFileByLine(String filePath) {
File file = new File(filePath);
// BufferedReader:從字符輸入流中讀取文本,緩沖各個(gè)字符,從而實(shí)現(xiàn)字符、數(shù)組和行的高效讀取。
BufferedReader bufReader = null;
BufferedWriter bufWriter = null;
try {
// FileReader:用來讀取字符文件的便捷類。
bufReader = new BufferedReader(new FileReader(file));
bufWriter = new BufferedWriter(new FileWriter("d:/work/readFileByLine.txt"));
// buf = new BufferedReader(new InputStreamReader(new
// FileInputStream(file)));
String temp = null;
while ((temp = bufReader.readLine()) != null) {
bufWriter.write(temp+"\n");
}
}
catch (Exception e) {
e.getStackTrace();
}
finally {
if (bufReader != null && bufWriter != null) {
try {
bufReader.close();
bufWriter.close();
}
catch (IOException e) {
e.getStackTrace();
}
}
}
}
/**
* 使用Java.nio ByteBuffer字節(jié)將一個(gè)文件輸出至另一文件
*
* @param filePath
*/
public static void readFileByBybeBuffer(String filePath) {
FileInputStream in = null;
FileOutputStream out = null;
try {
// 獲取源文件和目標(biāo)文件的輸入輸出流
in = new FileInputStream(filePath);
out = new FileOutputStream("d:/work/readFileByBybeBuffer.txt");
// 獲取輸入輸出通道
FileChannel fcIn = in.getChannel();
FileChannel fcOut = out.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (true) {
// clear方法重設(shè)緩沖區(qū),使它可以接受讀入的數(shù)據(jù)
buffer.clear();
// 從輸入通道中將數(shù)據(jù)讀到緩沖區(qū)
int r = fcIn.read(buffer);
if (r == -1) {
break;
}
// flip方法讓緩沖區(qū)可以將新讀入的數(shù)據(jù)寫入另一個(gè)通道
buffer.flip();
fcOut.write(buffer);
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
if (in != null && out != null) {
try {
in.close();
out.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static long getTime(){
return System.currentTimeMillis();
}
public static void main(String args[]) {
long time1 = getTime() ;
// readFileByByte(FILE_PATH);// 8734,8281,8000,7781,8047
// readFileByCharacter(FILE_PATH);// 734, 437, 437, 438, 422
// readFileByLine(FILE_PATH);// 110, 94, 94, 110, 93
readFileByBybeBuffer(FILE_PATH);
// 125, 78, 62, 78, 62
long time2 = getTime() ;
System.out.println(time2-time1);
}
}
在main方法中,調(diào)用各方法之后,有五組數(shù)據(jù),分辨是我5次讀寫文件測試出來的時(shí)間(毫秒)。
關(guān)于Java.nio請(qǐng)參考:http://www.dbjr.com.cn/article/131338.htm
個(gè)人測試:
public static void main(String args[]) {
long time1 = getTime() ;
// readFileByByte(FILE_PATH); //2338,2286
// readFileByCharacter(FILE_PATH);//160,162,158
// readFileByLine(FILE_PATH); //46,51,57
// readFileByBybeBuffer(FILE_PATH);//19,18,17
// readFileByBybeBuffer(FILE_PATH);//2048: 11,13
// readFileByBybeBuffer(FILE_PATH);//1024*100 100k,711k: 6,6
// readFileByBybeBuffer(FILE_PATH);//1024*100 100k,1422k: 7
// readFileByBybeBuffer(FILE_PATH);//1024*100 100k,9951k: 49,48
// readFileByBybeBuffer(FILE_PATH);//1024*1000 1M,711k: 7,7
// readFileByBybeBuffer(FILE_PATH);//1024*1000 1M,1422k: 7,8
// readFileByBybeBuffer(FILE_PATH);//1024*1000 1M,9951k: 48,49
// readFileByBybeBuffer(FILE_PATH);//1024*10000 10M,711k: 21,13,17
// readFileByBybeBuffer(FILE_PATH);//1024*10000 10M,1422k: 16,17,14,15
// readFileByBybeBuffer(FILE_PATH);//1024*10000 10M,9951k:64,60
long time2 = getTime() ;
System.out.println(time2-time1);
}
總結(jié)
以上就是本文關(guān)于Java文件讀寫IO/NIO及性能比較詳細(xì)代碼及總結(jié)的全部內(nèi)容,希望對(duì)大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關(guān)專題,如有不足之處,歡迎留言指出。感謝朋友們對(duì)本站的支持!
相關(guān)文章
Java基礎(chǔ)知識(shí)之CharArrayReader流的使用
這篇文章主要介紹了Java基礎(chǔ)知識(shí)之CharArrayReader流的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
java8 利用reduce實(shí)現(xiàn)將列表中的多個(gè)元素的屬性求和并返回操作
這篇文章主要介紹了java8 利用reduce實(shí)現(xiàn)將列表中的多個(gè)元素的屬性求和并返回操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-08-08
RestTemplate響應(yīng)中如何獲取輸入流InputStream
這篇文章主要介紹了RestTemplate響應(yīng)中如何獲取輸入流InputStream問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01
Springboot集成Ehcache3實(shí)現(xiàn)本地緩存的配置方法
EhCache是一個(gè)純Java的進(jìn)程內(nèi)緩存框架,是 Hibernate 中默認(rèn)的 CacheProvider,同Redis一樣,EhCache 不是純內(nèi)存緩存,它支持基于內(nèi)存和磁盤的二級(jí)緩存,本文介紹Springboot集成Ehcache3實(shí)現(xiàn)本地緩存的配置方法,感興趣的朋友一起看看吧2024-04-04
Java中Velocity快速對(duì)變量中的引號(hào)特殊字符進(jìn)行轉(zhuǎn)義
Velocity是一個(gè)基于Java的模板引擎,與Freemarker類似,這篇文章主要介紹了Java中Velocity如何對(duì)變量中的引號(hào)特殊字符進(jìn)行轉(zhuǎn)義,主要記錄一下在使用中碰到的要對(duì)引號(hào)特殊字符進(jìn)行轉(zhuǎn)義的問題,需要的朋友可以參考下2023-07-07
java?String到底有多長?String超出長度該如何解決
在Java中,由于字符串常量池的存在,String常量長度限制取決于String常量在常量池中的存儲(chǔ)大小,下面這篇文章主要給大家介紹了關(guān)于java?String到底有多長?String超出長度該如何解決的相關(guān)資料,需要的朋友可以參考下2023-01-01
Trie樹(字典樹)的介紹及Java實(shí)現(xiàn)
Trie樹,又稱字典樹或前綴樹,關(guān)于它的結(jié)構(gòu)就不詳細(xì)介紹了。Trie樹在單詞統(tǒng)計(jì)、前綴匹配等很多方面有很大用處。下面這篇文章主要介紹了Trie樹,以及Java實(shí)現(xiàn)如何Trie樹,有需要的朋友可以參考借鑒,下面來一起看看吧。2017-02-02

