文章目录
一、文件基本操作
1、创建文件
public static boolean createFile(String path) throws IOException {
File file = new File(path);
// 文件不存在则创建
if (!file.exists()) {
return file.createNewFile();
}
return true;
}
调用createFile如:createFile(“D:\test.csv”);即可在D盘下创建了test.csv文件。
2、写入数据到文件
csv文件写入特性,以字符写入用英文逗号(”,“)分隔即是单元格分离,如写入数据为"test11,test22,test33,test44,test55”,得到的文件是以”,"分隔的单元格数据:
代码实现:
public static boolean writeDataToCsv(String path, String data) {
File file = new File(path);
if (!file.exists()) {
return false;
}
// true:追加写入;不填(默认)或false为 覆盖写入
try(BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file, true))) {
bufferedWriter.write(data);
bufferedWriter.newLine();
bufferedWriter.flush();
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
代码调用:
String data = "test11,test22,test33,test44,test55";
writeDataToCsv("D:\\test.csv", data);
追加写入调用两次后的文件内容如下:
3、写入多行数据(批量)到文件
代码实现:
public static boolean writeBatchDataToCsv(String path, List<String[]> data) {
File file = new File(path);
if (!file.exists()) {
return false;
}
try(BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file))) {
for (String[] strings : data) {
writeRow(strings, bufferedWriter);
}
bufferedWriter.newLine();
bufferedWriter.flush();
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
public static void writeRow(String[] rowData, BufferedWriter csvWriter) throws IOException {
StringBuilder stringBuilder = new StringBuilder();
for(String data : rowData) {
stringBuilder.append(data).append(",");
}
csvWriter.write(stringBuilder.toString());
csvWriter.newLine();
}
代码调用:
public static void main(String[] args) throws IOException {
List<String[]> dataTest = new ArrayList<>();
String[] s = new String[]{"test1", "test2", "test3", "test4", "test5", "test6"};
String[] s2 = new String[]{"OK", "OK", "OK", "OK", "OK", "OK"};
String[] s3 = new String[]{"OK", "OK", "OK", "OK", "OK", "OK"};
String[] s4 = new String[]{"OK", "OK", "OK", "OK", "OK", "OK"};
dataTest.add(s);
dataTest.add(s2);
dataTest.add(s3);
dataTest.add(s4);
writeBatchDataToCsv("D:\\test.csv", dataTest);
}
文件数据结果:
二、操作文件问题记录
1、因中途文件打开被占用导致写入失败出现异常
程序运行中生成的文件,在不断的往文件写入数据,若该文件在程序运行的途中被打开,之后的写入将会出现异常:java.io.FileNotFoundException,错误如下图所示:
解决思路:
在程序中,往文件写入数据之前,创建一个文件写入流如BufferedWriter,然后每次写入都通过这个写入流对象去写入数据到文件。
如往刚刚的文件中追加写入,用一个死循环来模拟程序平台不断的往该文件中写入文件。
代码实现:
public static void main(String[] args) throws IOException {
String data = "test11,test22,test33,test44,test55,";
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("D:\\test.csv", true));
while (true) {
if (writeDataToCsv(bufferedWriter, data)) {
System.out.println("写入数据成功");
}
}
}
public static boolean writeDataToCsv(BufferedWriter bufferedWriter, String data) {
if (bufferedWriter == null) {
return false;
}
try {
bufferedWriter.write(data);
bufferedWriter.newLine();
bufferedWriter.flush();
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
代码运行后,因为这是一个while死循环,则程序停止运行前会一直往文件写入数据,在程序运行后,人为的找到该文件并打开,则文件会出现如下状态,表示该文件被其他程序正在编辑,只能在已读状态打开,打开后可以看到写入的数据,同时程序还在不断的往该文件写入数据,把文件关掉,再次打开,以只读方式进入发现数据更新了。
2、解决上述文件占用问题后,只能追加写入,无法实现覆盖写入
问题1中解决了途中文件打开写入失败的问题,但是问题1中是追加写入,若同样的代码,改成以覆盖写入,即将true改成false或不填,运行程序后发现文件还是一直在追加写入,而每次写入时没有覆盖调原来的数据。
问题原因:
因为文件流一直没有被关闭,缓冲流无法被清除,所以无法覆盖掉原来的数据,导致覆盖写入无效,只能追加写入。
解决思路:
在写入数据的前,关闭一下文件流,再次打开,但重新new一个BufferedWriter对象的同时要同时改变原来一直传下来的BufferedWriter对象,因为重新new一个BufferedWriter对象之后,新的对象和旧的对象不是同一个对象了,它们的地址不同,所以要保证一开始一直被使用的BufferedWriter对象跟着变。如果没有保证旧的BufferedWriter对象被改变的话,虽然能实现覆盖写入,但是打开文件后,文件不再被程序占用,此时又会出现问题1中的程序被占用异常。
代码实现:
public static void main(String[] args) throws IOException {
String data = "test11,test22,test33,test44,test55,";
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("D:\\test.csv", false));
while (true) {
if (writeDataToCsv("D:\\test.csv", bufferedWriter, data)) {
System.out.println("写入数据成功");
}
}
}
public static boolean writeDataToCsv(String path, BufferedWriter bufferedWriter, String data) {
if (bufferedWriter == null) {
return false;
}
try {
bufferedWriter.close();
bufferedWriter = new BufferedWriter(new FileWriter(path,false));
bufferedWriter.write(data);
bufferedWriter.newLine();
bufferedWriter.flush();
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
文件数据结果:
因循环写入的是一行数据,所以每次打开文件都是只有一行数据,可以构造不同的数据写入,观察每次打开的区别。