使用IO流寫檔案的一些騷操作
阿新 • • 發佈:2019-01-04
序言
當需要對檔案進行操作時,使用IO流是不能避免的操作;比如業務中需要儲存一些請求的響應結果中的一些內容。當所需處理的檔案過大時,如果頻繁的關閉檔案流,會造成很大的開銷,何時關閉?往往會造成比較大的困擾。那麼如何才能比較優雅的處理檔案呢?
使用案例
情景
儲存資料時,行與行之間使用回車符隔開;一行的資料欄位之間使用Tab
鍵隔開
程式碼地址
https://github.com/mmzsblog/IO-demo
解決方案一:
使用apache提供的工具類IOUtil
可以方便快捷的處理這個問題,這個工具類封裝了很多方法
- 引入apache工具類
IOUtil
的依賴包
<dependencies> <!-- apache提供的一個IO工具類 --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency> </dependencies> <repositories> <repository> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>
- 主要程式碼如下:
public static void main(String[] args) { List<String> list = new ArrayList(); list.add("hello"); list.add("third"); list.add("method"); list.add("io"); list.add("util"); OutputStream os = null; File filePath = new File("d:\\" + DateUtil.getCurrentDate("yyyyMMdd") + ".txt"); try { os = new FileOutputStream(filePath, true); //一行中的欄位用tab隔開 IOUtils.writeLines(list,"\t",os); //行與行之間用回車隔開 IOUtils.write("\n", os); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
解決方案二:
- 主要程式碼如下:
public static void main(String[] args) { File filePath = new File("d:\\" + DateUtil.getCurrentDate("yyyyMMdd") + ".txt"); //將資料儲存到StringBuffer中後再儲存到檔案中 List<String> list = new ArrayList(); list.add("hello"); list.add("second"); list.add("method"); list.add("io"); list.add("util"); //因為此處不涉及執行緒安全問題,所以用了StringBuilder StringBuilder sb = new StringBuilder(); Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String item = iterator.next(); sb.append(item).append("\t"); } String newTxt = sb.deleteCharAt(sb.length()-1).append("\n").toString(); BufferedWriter bw = null; try { //true表示檔案寫入方式為追加;flase表示是覆蓋 bw = new BufferedWriter(new FileWriter(filePath, true)); bw.write(newTxt); } catch (IOException e) { e.printStackTrace(); }finally { if (null != bw) { try { bw.flush(); bw.close(); } catch (IOException e) { e.printStackTrace(); } } } }
解決方案三:
- 主要程式碼如下:
public class IOFirst {
/**
* description: 最複雜,但也是比較考驗基本功的寫法
* author: mmzsit
* date: 2018/12/27 17:45
*/
public static void main(String[] args)
{
File log=new File("d:\\"+DateUtil.getCurrentDate("yyyyMMdd") +".txt");
List<String> list = new ArrayList();
list.add("hello");
list.add("first");
list.add("method");
list.add("io");
list.add("util");
//因為此處不涉及執行緒安全問題,所以用了StringBuilder
StringBuilder sb = new StringBuilder();
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
sb.append(item).append("\t");
}
String newLog = sb.deleteCharAt(sb.length()-1).toString();
//呼叫appendLog方法執行檔案寫入操作
appendLog(log,newLog);
}
/**
* description: 此種方式是自己寫的類,想怎麼操作按自己的意思來
* author: mmzsit
* date: 2018/12/27 17:42
*/
public static void appendLog(File filePath,String newTxt)
{
Scanner sc=null;
PrintWriter pw=null;
try{
isExists(filePath);
sc=new Scanner(filePath);
StringBuilder sb=new StringBuilder();
//先讀出舊檔案內容,並暫存sb中;
while(sc.hasNextLine())
{
sb.append(sc.nextLine());
//換行符作為間隔,掃描器讀不出來,因此要自己新增.
sb.append("\t\n");
}
if (0 != sb.length()) {
//解決每次多餘的空行
sb.deleteCharAt(sb.length()-1);
}
sc.close();
pw=new PrintWriter(new FileWriter(filePath),true);
//A、寫入舊檔案內容.
pw.println(sb.toString());
//B、寫入新檔案內容
pw.println(newTxt);
/*
* 如果先寫入A,最近寫入在檔案最後.
* 如是先寫入B,最近寫入在檔案最前.
*/
pw.close();
}
catch(IOException ex)
{
ex.printStackTrace();
}
}
/**
* description: 保證資料夾的存在
* author: mmzsit
* date: 2018/12/27 17:42
*/
public static void isExists(File filePath){
//如果檔案不存在,則新建.
if(!filePath.exists())
{
File parentDir=new File(filePath.getParent());
//如果所在目錄不存在,則新建.
if(!parentDir.exists()) {
parentDir.mkdirs();
}
try {
filePath.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}