使用IO流写文件的一些骚操作
序言
当需要对文件进行操作时,使用IO流是不能避免的操作;比如业务中需要存储一些请求的响应结果中的一些内容。当所需处理的文件过大时,如果频繁的关闭文件流,会造成很大的开销,何时关闭?往往会造成比较大的困扰。那么如何才能比较优雅的处理文件呢?
使用案例
情景
存储数据时,行与行之间使用回车符隔开;一行的数据字段之间使用Tab
键隔开
代码地址
https://github.com/mmzsblog/IO-demo
解决方案一:
使用apache提供的工具类IOUtil
可以方便快捷的处理这个问题,这个工具类封装了很多方法;
更多使用方法请参考IOUtils使用总结
官方文档请参考:官方Api
- 引入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();
}
}
}
}