0

I want read the CSV files inside the zip file and edit the record based on some condition. I am using FileSystem class to create zip file system and then edit csv files. I used the below code read csv files

public static List<String> getFileList() {
        List<String> fileList = new ArrayList<>();
        ZipFile zip = null;
        try {
            zip = new ZipFile(zipFile);
            Enumeration<? extends ZipEntry> entries = zip.entries();
            while (entries.hasMoreElements()) {
                ZipEntry entry = entries.nextElement();
                if (entry.getName().contains("**") && !entry.getName().contains("***")) {
                    fileList.add(entry.getName());
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return fileList;
    }

    public static void modifyTextFileInZip() throws IOException {
        Path zipfilePath = Paths.get(zipFile);

        try (FileSystem fs = FileSystems.newFileSystem(zipfilePath, null)) {
            for (String file : getFileList()) {
                Path source = fs.getPath(file);
                String tempFileDest = source.getParent().toString() + "/" + "temp_" + source.getFileName();
                tempFileDest = tempFileDest.replace(".red", "");
                Path temp = fs.getPath(tempFileDest);
                editFiles(source, temp);
            }
        }
    }

    public static void editFiles(Path source, Path dest) {
        CSVReader reader;
        try {
            reader = new CSVReader(new InputStreamReader(Files.newInputStream(source)));
            List<String[]> records = reader.readAll();
            Iterator<String[]> iterator = records.iterator();
            
            Optional<String> fileName =
            Files.list(source.getParent())
                    .filter(file -> file.getFileName().toString().endsWith("***") &&
                            !file.getFileName().toString().endsWith("****"))
                    .map(file -> file.toString())
                    .findFirst();
            //System.out.println(fileName);
            
            while (iterator.hasNext()) {
                String[] record = iterator.next();
                String val = null;
                if("****".equals(record[5])){
                    try {
                        val = fileName.orElseThrow(() -> new RuntimeException("File Not found"));
                        val = "**" + val;
                        //System.out.println(val);
                    } catch(Exception e){
                        System.out.println("File not Found");
                    }
                    record[5] = val;
                }
                
                for(String cell: record) {
                    System.out.print(cell);
                }
                System.out.println();          
            }
            
            Files.createFile(dest);
            PrintWriter outputFile = new PrintWriter(Files.newOutputStream(dest));
            CSVWriter writer = new CSVWriter(outputFile);
            writer.writeAll(records);

            writer.close();
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

erro log =>

java.nio.file.FileSystemException: C:\zipfile\P003.zip: The process cannot access the file because it is being used by another process.

    at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:86)
    at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)
    at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102)
    at sun.nio.fs.WindowsFileSystemProvider.implDelete(WindowsFileSystemProvider.java:269)
    at sun.nio.fs.AbstractFileSystemProvider.delete(AbstractFileSystemProvider.java:103)
    at java.nio.file.Files.delete(Files.java:1126)
    at com.sun.nio.zipfs.ZipFileSystem.sync(ZipFileSystem.java:1294)
    at com.sun.nio.zipfs.ZipFileSystem.close(ZipFileSystem.java:277)
    at com.shrikant.Main.Main2.modifyTextFileInZip(Main2.java:60)
    at com.shrikant.EditCsvFilesApplication.main(EditCsvFilesApplication.java:21)

I wans able to read the and edit the files using inputStream from Path object and then pass it to CSVReader object. But when I pass outputStream to CSVWriter and try to write data to temp file and can't see any changes inside zip file. And also I am getting a .tmp (zipfstmp3381860066025396844.tmp) file generated every I run my program.

I followed this => https://stackoverflow.com/a/43836969/20783127 to write this program

Don't know what's going wrong, I can anyone explain ?

I am trying read and edit the csv files in zip file using FileSystem class in java, but its not working

shrikant02
  • 15
  • 6
  • Which version of Java are you using? https://github.com/openjdk/jdk/blob/master/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java#L1871 shows that the temp file should replace the original. That method should be called from `close()`: https://github.com/openjdk/jdk/blob/master/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java#L484. You're calling that (through try-with-resources), so the file replacement should occur. – Rob Spoor Dec 15 '22 at 10:21
  • @RobSpoor I am using Java 8. I don't understand 'method should be called from close()' – shrikant02 Dec 15 '22 at 10:28
  • what I meant is that when you call `close()` (through the try-with-resources), the `sync()` call I linked to should be called automatically. That should take care of the file replacement. Can you perhaps try with Java 11 or Java 17? – Rob Spoor Dec 15 '22 at 10:37
  • @RobSpoor Actaully I am trying this in my work system, we don't have java 11 or java 17 – shrikant02 Dec 15 '22 at 10:44
  • @RobSpoor I tried to open .tmp file in 7Zip I can see my temp file there with new changes, do you know why this is happening and how we can avoid and make changes in the existing file. – shrikant02 Dec 15 '22 at 12:36
  • I've created a little test program to reproduce it. I actually could, by not closing the file. Can you use try-with-resources for `outputFile`? Even though you're closing the `CSVWriter`, the file itself appears to not be closed. Either the `CSVWriter` doesn't call `close()` of its underlying stream, or perhaps the code doesn't even get there. Is an exception printed? – Rob Spoor Dec 15 '22 at 13:49
  • I also noticed you don't close the `CSVReader`. That didn't prevent my test program from adding the file though. – Rob Spoor Dec 15 '22 at 13:55
  • @RobSpoor I am not getting exception in the console, CSVWriter with try-with-resources is also not working. – shrikant02 Dec 15 '22 at 14:09
  • @RobSpoor I am getting FileSystemException, when I close the reader before writing the file , I added the log in the question! – shrikant02 Dec 15 '22 at 14:33
  • Are you doing other things with the ZIP file? Because somewhere there's still a file handle to it open. That could be from reading or writing it; Windows is always very picky about that. – Rob Spoor Dec 15 '22 at 14:37
  • Note that an external program like 7-zip can also be the reason the file is still open. – Rob Spoor Dec 15 '22 at 14:38
  • @RobSpoor I am not doing anythin with the file. – shrikant02 Dec 15 '22 at 14:39

1 Answers1

1

You did not zip.close(). Better use the try-with-resources syntax, which closes also when an exception is thrown or one returns inside the { }.

try (ZipFile zip = new ZipFile(zipFile)) {
    ...
Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • Oh wow, I missed that. That's probably the file handle that's still open, that prevents the replacing of the file. – Rob Spoor Dec 15 '22 at 14:41