Java實現(xiàn)文件操作方式有很多,這里寫了幾個小工具,需要的話可以直接拷貝使用,或者優(yōu)化后使用。
基本概念
FileChannel是一個用讀寫,映射和操作一個文件的通道,也是Java NIO對應(yīng)于磁盤等存儲設(shè)備文件操作的通道。除了讀寫操作之外,還有裁剪特定大小文件truncate(),強(qiáng)制在內(nèi)存中的數(shù)據(jù)刷新到硬盤中去force(),對通道上鎖lock()等功能。
RandomAccessFile類的主要功能是完成隨機(jī)讀取功能,可以讀取指定位置的內(nèi)容。
之前的File類只是針對文件本身進(jìn)行操作的,而如果要想對文件內(nèi)容進(jìn)行操作,則可以使用RandomAccessFile類,此類屬于隨機(jī)讀取類,可以隨機(jī)讀取一個文件中指定位置的數(shù)據(jù)。在使用FileChannel之前,必須先打開它。但是,我們無法直接打開一個FileChannel,需要通過使用一個InputStream、OutputStream或RandomAccessFile來獲取一個FileChannel實例。
寫文件操作
/**
* 寫文件
* @param fileName
* @throws IOException
*/
public void doWrite(String fileName) throws IOException {
outFile = new RandomAccessFile(fileName, "rw");
outChannel = outFile.getChannel();
String newData = "New String to write to file... \n";
buf.clear();
buf.put(newData.getBytes());
buf.flip();
while (buf.hasRemaining()){
outChannel.write(buf);
}
outChannel.close();
System.out.println("Write Over!\n");
}
讀文件操作
/**
* 讀文件
* @param fileName
* @throws IOException
*/
public void doRead(String fileName) throws IOException {
inFile = new RandomAccessFile(fileName, "rw");
inChannel = inFile.getChannel();
int bytesRead = inChannel.read(buf);
while (bytesRead != -1) {
System.out.println("Read " + bytesRead);
buf.flip();
while (buf.hasRemaining()){
System.out.print((char) buf.get());
}
buf.clear();
bytesRead = inChannel.read(buf);
}
inFile.close();
}
文件拷貝操作
/**
* 拷貝文件
* @param sourceFile
* @param targetFile
* @throws IOException
*/
public void doCopy(String sourceFile, String targetFile) throws IOException {
inFile = new RandomAccessFile(sourceFile, "rw");
inChannel = inFile.getChannel();
RandomAccessFile bFile = new RandomAccessFile(targetFile, "rw");
FileChannel outChannel = bFile.getChannel();
inChannel.transferTo(0, inChannel.size(), outChannel);
System.out.println("Copy over");
inChannel.close();
}
/**
* 按照行讀文件
* @param fileName
* @throws IOException
*/
public void doReadLine(String fileName) throws IOException {
inFile = new RandomAccessFile(fileName, "rw");
int lineNum = 0;
inFile.seek(lineNum);
String line = "";
while((line = inFile.readLine())!=null){
line = new String(line.getBytes("UTF-8"), "UTF-8");
System.out.println(line);
}
inFile.close();
}
特殊情況下倒序拷貝文件操作
/**
* 倒序拷貝文件
* @param sourceFile
* @param targetFile
* @throws IOException
*/
public void reverseCopy(String sourceFile, String targetFile) throws IOException {
inFile = new RandomAccessFile(sourceFile, "r");
inChannel = inFile.getChannel();
outFile = new RandomAccessFile(targetFile, "rw");
outChannel = outFile.getChannel();
// 文件長度
long len = inFile.length();
System.out.println("文件開始指針為"+0);
//指針是從0到length-1
long nextEnd = len - 1;
String line;
//seek到最后一個字符
inFile.seek(nextEnd);
int c = -1;
while (nextEnd >= 0) {
c = inFile.read();
//只有行與行之間才有\(zhòng)r\n,這表示讀到每一行上一行的末尾的\n,而執(zhí)行完read后,指針指到了這一行的開頭字符
if (c == '\n')
{
line = new String(inFile.readLine().getBytes("UTF-8"), "UTF-8");
System.out.println(line);
writeLine(line, outChannel);
}
// 當(dāng)文件指針退至文件開始處,輸出第一行
if (nextEnd == 0) {
//不需要為下次做準(zhǔn)備了,但是因為read()方法指針從0到了1,需重置為0
inFile.seek(0);
line = new String(inFile.readLine().getBytes("UTF-8"), "UTF-8");
System.out.println(line);
writeLine(line, outChannel);
} else {
//為下一次循環(huán)做準(zhǔn)備
inFile.seek(nextEnd-1);
}
nextEnd--;
}
System.out.println("Reverse Copy over");
outChannel.close();
inChannel.close();
}
private void writeLine(String line, FileChannel outChannel)throws IOException{
// 寫入文件
line += "\n";
buf.clear();
buf.put(line.getBytes());
buf.flip();
while (buf.hasRemaining()){
outChannel.write(buf);
}
}
完整代碼
小技巧
文件按照行倒序輸出可以使用這個命名
perl -e 'print reverse <>' filename