1. 程式人生 > >使用IO流寫檔案的一些騷操作

使用IO流寫檔案的一些騷操作

序言

當需要對檔案進行操作時,使用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();
            }
        }
    }
}