JOAO12
JOAO12

Reputation: 55

How to save data from a "For Loop" into a compressed ".txt" file

I am trying to write a java code to save data from a "For Loop" (2d array named "arr") into a compressed ".txt" file.

FileOutputStream fos = new FileOutputStream(path to zip file);
ZipOutputStream zipOut = new ZipOutputStream(new BufferedOutputStream(fos));
ZipEntry ze = new ZipEntry(path txt file);
zipOut.putNextEntry(ze);
for (int r = 0; r < 1048577; r++) {
    for (int c = 0; c < 25; c++) {
        zipOut.write(arr[r][c] + ","); // how do I write this line?
    }

    zipOut.write("\n"); // how do I write this line?
}

zipOut.closeEntry();
zipOut.close();

What piece of code should be added to convert the result into Bytes and then use "ZipOutputStream" to write data into a compressed ".txt" file?

Thanks.

Upvotes: 0

Views: 360

Answers (3)

MadProgrammer
MadProgrammer

Reputation: 347234

So, my "big" concern is in how you might "read" the data back in, writing it is actually relatively easy.

The following does a "basic" job, using a couple of StringJoiners to produce a String which can be written to the file and the a, somewhat, convoluted process to decompress it.

The problem here is, the limiting factor (for me at least), is the fact that you need to read the entire contents of the file before you can begin reconstructing it.

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.StringJoiner;
import java.util.zip.DataFormatException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

public class Test {

    public static void main(String[] args) throws IOException, DataFormatException {
        File targetFile = new File("Test.dat");

        int[][] data = new int[][]{
            {0, 1, 2, 3, 4, 5},
            {6, 7, 8, 9, 10, 11}
        };

        StringJoiner outterJoiner = new StringJoiner("\n");
        for (int[] outter : data) {
            StringJoiner innerJoiner = new StringJoiner(",");
            for (int value : outter) {
                innerJoiner.add(Integer.toString(value));
            }
            outterJoiner.add(innerJoiner.toString());
        }

        try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(targetFile))) {
            ZipEntry zipEntry = new ZipEntry("master");
            zos.putNextEntry(zipEntry);
            zos.write(outterJoiner.toString().getBytes());
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        try (ZipInputStream zis = new ZipInputStream(new FileInputStream(targetFile)); ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            ZipEntry zipEntry = zis.getNextEntry();
            if (zipEntry != null) {
                byte[] buffer = new byte[1024];
                int bytesRead = -1;
                while ((bytesRead = zis.read(buffer)) != -1) {
                    baos.write(buffer, 0, bytesRead);
                }

                String contents = new String(baos.toByteArray());
                System.out.println(contents);
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

I'm wondering if, instead of relying on \n as a delimiter, you used the ZipEntry instead, this would allow you to process each individual "line" of data at a time...

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.StringJoiner;
import java.util.zip.DataFormatException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

public class Test {

    public static void main(String[] args) throws IOException, DataFormatException {
        File targetFile = new File("Test.dat");

        int[][] data = new int[][]{
            {0, 1, 2, 3, 4, 5},
            {6, 7, 8, 9, 10, 11}
        };

        try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(targetFile))) {
            for (int index = 0; index < data.length; index++) {
                int[] values = data[index];
                ZipEntry zipEntry = new ZipEntry("Values-" + index);
                zos.putNextEntry(zipEntry);
                StringJoiner joiner = new StringJoiner(",");
                for (int value : values) {
                    joiner.add(Integer.toString(value));
                }
                zos.write(joiner.toString().getBytes());
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        try (ZipInputStream zis = new ZipInputStream(new FileInputStream(targetFile))) {
            ZipEntry zipEntry = null;
            while ((zipEntry = zis.getNextEntry()) != null) {
                System.out.println(zipEntry.getName());
                try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
                    byte[] buffer = new byte[1024];
                    int bytesRead = -1;
                    while ((bytesRead = zis.read(buffer)) != -1) {
                        baos.write(buffer, 0, bytesRead);
                    }

                    String contents = new String(baos.toByteArray());
                    System.out.println(contents);
                }
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

Which prints out...

Values-0
0,1,2,3,4,5
Values-1
6,7,8,9,10,11

Now, obviously, you might not know how many lines you need, where as the first example, a simple String#split will tell you. (You could pre-read each entry, but that's double dipping)

is it possible to have ZipOutputStream save "contents" into a compressed ".txt" file called "Compressed file.txt" in a zip file "C:/Users/Username/Documents/Compressed folder.zip" ?

That's entirely up to you, if you're not concerned about reading/parse the file again, then the process can be greatly reduced (in effort and complexity).

So, the example below will write a line of content at time, so you're only ever creating a single line of text and then writing it to the ZipEntry. The StringJoiner makes this process SOOOO much simpler

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.StringJoiner;
import java.util.zip.DataFormatException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class Test {

    public static void main(String[] args) throws IOException, DataFormatException {
        File targetFile = new File("Compressed.zip");

        int[][] data = new int[][]{
            {0, 1, 2, 3, 4, 5},
            {6, 7, 8, 9, 10, 11}
        };

        try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(targetFile))) {
            ZipEntry zipEntry = new ZipEntry("Compressed.txt");
            zos.putNextEntry(zipEntry);
            for (int[] outter : data) {
                StringJoiner joiner = new StringJoiner(",", "", "\n");
                for (int value : outter) {
                    joiner.add(Integer.toString(value));
                }
                zos.write(joiner.toString().getBytes());
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

Upvotes: 1

user16320675
user16320675

Reputation: 135

Here a very basic/simplyfied idea:

var zos = new ZipOutputStream(new FileOutputStream("text.zip"));
try (zos) {
    var entry = new ZipEntry("test.txt");
    zos.putNextEntry(entry);

    var value = 12345; // just an example, should come from array/loop
    
    zos.write(Integer.toString(value).getBytes());
    zos.write(",".getBytes());
    
    zos.write("\n".getBytes());
    
    zos.closeEntry();
}

you'll need to add the loop.

Note1: use variables/constants for ",".getBytes(...) and "\n"...
Note2: using the default system charset for getBytes(), to use a specific one, use something like getBytes(StandardCharsets.UTF_8)

Upvotes: 1

spring
spring

Reputation: 44

import java.util.*;
import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class Main {
    public static void main(String[] args) {
        FileOutputStream fos = null;
        ZipOutputStream zipOut = null;
        ZipEntry ze = null;
        try {
            char[][] arr = {{'a', 'b'}, {'d', 'c'}};
            fos = new FileOutputStream("a.zip");
            zipOut = new ZipOutputStream(new BufferedOutputStream(fos));
            ze = new ZipEntry("out.txt");
            zipOut.putNextEntry(ze);
            StringBuilder sb = new StringBuilder();
            for (int r = 0; r < arr.length; r++) {
                for (int c = 0; c < arr[0].length; c++) {
                    sb.append(arr[r][c]).append(",");
                }

                sb.append("\n"); // how do I write this line?
            }
            zipOut.write(sb.toString().getBytes());
            zipOut.closeEntry();
            zipOut.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

maybe this is useful for you

Upvotes: 1

Related Questions