基于Java回顧之I/O的使用詳解
工作后,使用的技術(shù)隨著項(xiàng)目的變化而變化,時(shí)而C#,時(shí)而Java,當(dāng)然還有其他一些零碎的技術(shù)??傮w而言,C#的使用時(shí)間要更長(zhǎng)一些,其次是Java。我本身對(duì)語(yǔ)言沒有什么傾向性,能干活的語(yǔ)言,就是好語(yǔ)言。而且從面向?qū)ο蟮慕嵌葋砜?,我覺得C#和Java對(duì)我來說,沒什么區(qū)別。
這篇文章主要回顧Java中和I/O操作相關(guān)的內(nèi)容,I/O也是編程語(yǔ)言的一個(gè)基礎(chǔ)特性,Java中的I/O分為兩種類型,一種是順序讀取,一種是隨機(jī)讀取。
我們先來看順序讀取,有兩種方式可以進(jìn)行順序讀取,一種是InputStream/OutputStream,它是針對(duì)字節(jié)進(jìn)行操作的輸入輸出流;另外一種是Reader/Writer,它是針對(duì)字符進(jìn)行操作的輸入輸出流。
下面我們畫出InputStream的結(jié)構(gòu)
FileInputStream:操作文件,經(jīng)常和BufferedInputStream一起使用
PipedInputStream:可用于線程間通信
ObjectInputStream:可用于對(duì)象序列化
ByteArrayInputStream:用于處理字節(jié)數(shù)組的輸入
LineNumberInputStream:可輸出當(dāng)前行數(shù),并且可以在程序中進(jìn)行修改
下面是OutputStream的結(jié)構(gòu)
PrintStream:提供了類似print和println的接口去輸出數(shù)據(jù)
下面我們來看如何使用Stream的方式來操作輸入輸出
使用InputStream讀取文件
使用FileInputStream讀取文件信息
public static byte[] readFileByFileInputStream(File file) throws IOException
{
ByteArrayOutputStream output = new ByteArrayOutputStream();
FileInputStream fis = null;
try
{
fis = new FileInputStream(file);
byte[] buffer = new byte[1024];
int bytesRead = 0;
while((bytesRead = fis.read(buffer, 0, buffer.length)) != -1)
{
output.write(buffer, 0, bytesRead);
}
}
catch(Exception ex)
{
System.out.println("Error occurs during reading " + file.getAbsoluteFile());
}
finally
{
if (fis !=null) fis.close();
if (output !=null) output.close();
}
return output.toByteArray();
}
使用BufferedInputStream讀取文件
public static byte[] readFileByBufferedInputStream(File file) throws Exception
{
FileInputStream fis = null;
BufferedInputStream bis = null;
ByteArrayOutputStream output = new ByteArrayOutputStream();
try
{
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
byte[] buffer = new byte[1024];
int bytesRead = 0;
while((bytesRead = bis.read(buffer, 0, buffer.length)) != -1)
{
output.write(buffer, 0, bytesRead);
}
}
catch(Exception ex)
{
System.out.println("Error occurs during reading " + file.getAbsoluteFile());
}
finally
{
if (fis != null) fis.close();
if (bis != null) bis.close();
if (output != null) output.close();
}
return output.toByteArray();
}
使用OutputStream復(fù)制文件
使用FileOutputStream復(fù)制文件
public static void copyFileByFileOutputStream(File file) throws IOException
{
FileInputStream fis = null;
FileOutputStream fos = null;
try
{
fis = new FileInputStream(file);
fos = new FileOutputStream(file.getName() + ".bak");
byte[] buffer = new byte[1024];
int bytesRead = 0;
while((bytesRead = fis.read(buffer,0,buffer.length)) != -1)
{
fos.write(buffer, 0, bytesRead);
}
fos.flush();
}
catch(Exception ex)
{
System.out.println("Error occurs during copying " + file.getAbsoluteFile());
}
finally
{
if (fis != null) fis.close();
if (fos != null) fos.close();
}
}
使用BufferedOutputStream復(fù)制文件
public static void copyFilebyBufferedOutputStream(File file)throws IOException
{
FileInputStream fis = null;
BufferedInputStream bis = null;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
try
{
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
fos = new FileOutputStream(file.getName() + ".bak");
bos = new BufferedOutputStream(fos);
byte[] buffer = new byte[1024];
int bytesRead = 0;
while((bytesRead = bis.read(buffer, 0, buffer.length)) != -1)
{
bos.write(buffer, 0, bytesRead);
}
bos.flush();
}
catch(Exception ex)
{
System.out.println("Error occurs during copying " + file.getAbsoluteFile());
}
finally
{
if (fis != null) fis.close();
if (bis != null) bis.close();
if (fos != null) fos.close();
if (bos != null) bos.close();
}
}
這里的代碼對(duì)異常的處理非常不完整,稍后我們會(huì)給出完整嚴(yán)謹(jǐn)?shù)拇a。
下面我們來看Reader的結(jié)構(gòu)
這里的Reader基本上和InputStream能夠?qū)?yīng)上?! ?/P>
Writer的結(jié)構(gòu)如下
下面我們來看一些使用Reader或者Writer的例子
使用Reader讀取文件內(nèi)容
使用BufferedReader讀取文件內(nèi)容
public static String readFile(String file)throws IOException
{
BufferedReader br = null;
StringBuffer sb = new StringBuffer();
try
{
br = new BufferedReader(new FileReader(file));
String line = null;
while((line = br.readLine()) != null)
{
sb.append(line);
}
}
catch(Exception ex)
{
System.out.println("Error occurs during reading " + file);
}
finally
{
if (br != null) br.close();
}
return sb.toString();
}
使用Writer復(fù)制文件
使用BufferedWriter復(fù)制文件
public static void copyFile(String file) throws IOException
{
BufferedReader br = null;
BufferedWriter bw = null;
try
{
br = new BufferedReader(new FileReader(file));
bw = new BufferedWriter(new FileWriter(file + ".bak"));
String line = null;
while((line = br.readLine())!= null)
{
bw.write(line);
}
}
catch(Exception ex)
{
System.out.println("Error occurs during copying " + file);
}
finally
{
if (br != null) br.close();
if (bw != null) bw.close();
}
}
下面我們來看如何對(duì)文件進(jìn)行隨機(jī)訪問,Java中主要使用RandomAccessFile來對(duì)文件進(jìn)行隨機(jī)操作。
創(chuàng)建一個(gè)大小固定的文件
創(chuàng)建大小固定的文件
public static void createFile(String file, int size) throws IOException
{
File temp = new File(file);
RandomAccessFile raf = new RandomAccessFile(temp, "rw");
raf.setLength(size);
raf.close();
}
向文件中隨機(jī)寫入數(shù)據(jù)
向文件中隨機(jī)插入數(shù)據(jù)
public static void writeFile(String file, byte[] content, int startPos, int contentLength) throws IOException
{
RandomAccessFile raf = new RandomAccessFile(new File(file), "rw");
raf.seek(startPos);
raf.write(content, 0, contentLength);
raf.close();
}
接下里,我們來看一些其他的常用操作
移動(dòng)文件
移動(dòng)文件
public static boolean moveFile(String sourceFile, String destFile)
{
File source = new File(sourceFile);
if (!source.exists()) throw new RuntimeException("source file does not exist.");
File dest = new File(destFile);
if (!(new File(dest.getPath()).exists())) new File(dest.getParent()).mkdirs();
return source.renameTo(dest);
}
復(fù)制文件
復(fù)制文件
public static void copyFile(String sourceFile, String destFile) throws IOException
{
File source = new File(sourceFile);
if (!source.exists()) throw new RuntimeException("File does not exist.");
if (!source.isFile()) throw new RuntimeException("It is not file.");
if (!source.canRead()) throw new RuntimeException("File cound not be read.");
File dest = new File(destFile);
if (dest.exists())
{
if (dest.isDirectory()) throw new RuntimeException("Destination is a folder.");
else
{
dest.delete();
}
}
else
{
File parentFolder = new File(dest.getParent());
if (!parentFolder.exists()) parentFolder.mkdirs();
if (!parentFolder.canWrite()) throw new RuntimeException("Destination can not be written.");
}
FileInputStream fis = null;
FileOutputStream fos = null;
try
{
fis = new FileInputStream(source);
fos = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int bytesRead = 0;
while((bytesRead = fis.read(buffer, 0, buffer.length)) != -1)
{
fos.write(buffer, 0, bytesRead);
}
fos.flush();
}
catch(IOException ex)
{
System.out.println("Error occurs during copying " + sourceFile);
}
finally
{
if (fis != null) fis.close();
if (fos != null) fos.close();
}
}
復(fù)制文件夾
復(fù)制文件夾
public static void copyDir(String sourceDir, String destDir) throws IOException
{
File source = new File(sourceDir);
if (!source.exists()) throw new RuntimeException("Source does not exist.");
if (!source.canRead()) throw new RuntimeException("Source could not be read.");
File dest = new File(destDir);
if (!dest.exists()) dest.mkdirs();
File[] arrFiles = source.listFiles();
for(int i = 0; i < arrFiles.length; i++)
{
if (arrFiles[i].isFile())
{
BufferedReader reader = new BufferedReader(new FileReader(arrFiles[i]));
BufferedWriter writer = new BufferedWriter(new FileWriter(destDir + "/" + arrFiles[i].getName()));
String line = null;
while((line = reader.readLine()) != null) writer.write(line);
writer.flush();
reader.close();
writer.close();
}
else
{
copyDir(sourceDir + "/" + arrFiles[i].getName(), destDir + "/" + arrFiles[i].getName());
}
}
}
刪除文件夾
刪除文件夾
public static void del(String filePath)
{
File file = new File(filePath);
if (file == null || !file.exists()) return;
if (file.isFile())
{
file.delete();
}
else
{
File[] arrFiles = file.listFiles();
if (arrFiles.length > 0)
{
for(int i = 0; i < arrFiles.length; i++)
{
del(arrFiles[i].getAbsolutePath());
}
}
file.delete();
}
}
獲取文件夾大小
獲取文件夾大小
public static long getFolderSize(String dir)
{
long size = 0;
File file = new File(dir);
if (!file.exists()) throw new RuntimeException("dir does not exist.");
if (file.isFile()) return file.length();
else
{
String[] arrFileName = file.list();
for (int i = 0; i < arrFileName.length; i++)
{
size += getFolderSize(dir + "/" + arrFileName[i]);
}
}
return size;
}
將大文件切分為多個(gè)小文件
將大文件切分成多個(gè)小文件
public static void splitFile(String filePath, long unit) throws IOException
{
File file = new File(filePath);
if (!file.exists()) throw new RuntimeException("file does not exist.");
long size = file.length();
if (unit >= size) return;
int count = size % unit == 0 ? (int)(size/unit) : (int)(size/unit) + 1;
String newFile = null;
FileOutputStream fos = null;
FileInputStream fis =null;
byte[] buffer = new byte[(int)unit];
fis = new FileInputStream(file);
long startPos = 0;
String countFile = filePath + "_Count";
PrintWriter writer = new PrintWriter(new FileWriter( new File(countFile)));
writer.println(filePath + "\t" + size);
for (int i = 1; i <= count; i++)
{
newFile = filePath + "_" + i;
startPos = (i - 1) * unit;
System.out.println("Creating " + newFile);
fos = new FileOutputStream(new File(newFile));
int bytesRead = fis.read(buffer, 0, buffer.length);
if (bytesRead != -1)
{
fos.write(buffer, 0, bytesRead);
writer.println(newFile + "\t" + startPos + "\t" + bytesRead);
}
fos.flush();
fos.close();
System.out.println("StartPos:" + i*unit + "; EndPos:" + (i*unit + bytesRead));
}
writer.flush();
writer.close();
fis.close();
}
將多個(gè)小文件合并為一個(gè)大文件
將多個(gè)小文件合并成一個(gè)大文件
public static void linkFiles(String countFile) throws IOException
{
File file = new File(countFile);
if (!file.exists()) throw new RuntimeException("Count file does not exist.");
BufferedReader reader = new BufferedReader(new FileReader(file));
String line = reader.readLine();
String newFile = line.split("\t")[0];
long size = Long.parseLong(line.split("\t")[1]);
RandomAccessFile raf = new RandomAccessFile(newFile, "rw");
raf.setLength(size);
FileInputStream fis = null;
byte[] buffer = null;
while((line = reader.readLine()) != null)
{
String[] arrInfo = line.split("\t");
fis = new FileInputStream(new File(arrInfo[0]));
buffer = new byte[Integer.parseInt(arrInfo[2])];
long startPos = Long.parseLong(arrInfo[1]);
fis.read(buffer, 0, Integer.parseInt(arrInfo[2]));
raf.seek(startPos);
raf.write(buffer, 0, Integer.parseInt(arrInfo[2]));
fis.close();
}
raf.close();
}
執(zhí)行外部命令
執(zhí)行外部命令
public static void execExternalCommand(String command, String argument)
{
Process process = null;
try
{
process = Runtime.getRuntime().exec(command + " " + argument);
InputStream is = process.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line = null;
while((line = br.readLine()) != null)
{
System.out.println(line);
}
}
catch(Exception ex)
{
System.err.println(ex.getMessage());
}
finally
{
if (process != null) process.destroy();
}
}
相關(guān)文章
Java中回調(diào)函數(shù)?(callback)?及其實(shí)際應(yīng)用場(chǎng)景
在Java中回調(diào)函數(shù)(Callback)是一種常見的設(shè)計(jì)模式,用于實(shí)現(xiàn)異步操作或事件處理,這篇文章主要給大家介紹了關(guān)于Java中回調(diào)函數(shù)?(callback)?及其實(shí)際應(yīng)用場(chǎng)景的相關(guān)資料,需要的朋友可以參考下2024-02-02詳解如何為SpringBoot項(xiàng)目中的自定義配置添加IDE支持
這篇文章主要介紹了詳解如何為SpringBoot項(xiàng)目中的自定義配置添加IDE支持,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02Java中outer標(biāo)簽的用法實(shí)例代碼
這篇文章主要介紹了Java中outer標(biāo)簽的用法,在這里需要大家注意這里的outer并不是關(guān)鍵字,而僅僅是一個(gè)標(biāo)簽,本文結(jié)合實(shí)例代碼給大家詳細(xì)講解,需要的朋友可以參考下2023-01-01Mybatis?連接mysql數(shù)據(jù)庫(kù)底層運(yùn)行的原理分析
這篇文章主要介紹了Mybatis?連接mysql數(shù)據(jù)庫(kù)底層運(yùn)行的原理分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03java實(shí)現(xiàn)上傳網(wǎng)絡(luò)圖片到微信臨時(shí)素材
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)上傳網(wǎng)絡(luò)圖片到微信臨時(shí)素材,網(wǎng)絡(luò)圖片上傳到微信服務(wù)器,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07利用Java多線程技術(shù)導(dǎo)入數(shù)據(jù)到Elasticsearch的方法步驟
這篇文章主要介紹了利用Java多線程技術(shù)導(dǎo)入數(shù)據(jù)到Elasticsearch的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07Mybatis動(dòng)態(tài)sql超詳細(xì)講解
動(dòng)態(tài)SQL是MyBatis的強(qiáng)大特性之一,顧名思義就是會(huì)動(dòng)的SQL,即是能夠靈活的根據(jù)某種條件拼接出完整的SQL語(yǔ)句,下面這篇文章主要給大家介紹了關(guān)于Mybatis動(dòng)態(tài)sql的相關(guān)資料,需要的朋友可以參考下2023-04-04使用@ControllerAdvice同時(shí)配置過濾多個(gè)包
這篇文章主要介紹了使用@ControllerAdvice同時(shí)配置過濾多個(gè)包的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06