java 操作文件及问题解决(csv)

一、文件基本操作

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;
    }

文件数据结果
因循环写入的是一行数据,所以每次打开文件都是只有一行数据,可以构造不同的数据写入,观察每次打开的区别。
在这里插入图片描述

  • 0
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值