【问题标题】:How to save data from a "For Loop" into a compressed ".txt" file如何将“For Loop”中的数据保存到压缩的“.txt”文件中
【发布时间】:2021-10-28 10:24:46
【问题描述】:

我正在尝试编写 java 代码以将“For Loop”(名为“arr”的二维数组)中的数据保存到压缩的“.txt”文件中。

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();

应该添加什么代码将结果转换为字节,然后使用“ZipOutputStream”将数据写入压缩的“.txt”文件?

谢谢。

【问题讨论】:

  • 你的阵列是什么? String[][]?
  • 它是 Int[][],我需要在每个元素之间插入一个逗号。
  • 好的,为什么不将数据写入文件然后压缩呢?
  • 我想避免创建一个未压缩的txt文件,然后再次读取它以创建一个压缩的txt文件(这需要额外的时间)。
  • 所以您希望将ints 呈现为字符串?即 10,234 的值变成“10234”?

标签: java zip compression


【解决方案1】:
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();
        }

    }
}

也许这对你有用

【讨论】:

  • arr 是一个 'int[][]' 数组,填充了数字。 'char[][] arr' 怎么改成 'int[][] arr' 呢?
  • 是的,你完全正确(“append”方法接受一个“int”)。我刚刚测试了代码,它返回了 OutOfMemoryError,因为数组“arr”非常大(26,214,400 行乘 25 列)。这个问题怎么解决?
  • @user16320675 提出的建议最终解决了“OutOfMemoryError”异常。
【解决方案2】:

这是一个非常基本/简化的想法

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

您需要添加循环。

注意 1:",".getBytes(...)"\n"... 使用变量/常量
注意2:使用getBytes()的默认系统字符集,要使用特定的,使用getBytes(StandardCharsets.UTF_8)之类的东西

【讨论】:

  • 我有 2 个 java 代码:一个用于创建“.txt”文件(大小 3GB)。需要 1 分钟。 8 秒。创建这个“.txt”文件。以及压缩此“.txt”文件的其他代码。需要 54 秒。创建一个新的压缩“.txt”文件。由于我需要创建超过 10,000 个压缩的“.txt”文件,因此我试图让第一个代码创建压缩文件并避免使用第二个代码丢失 54 秒。我将此答案中显示的想法应用于第一个代码,但花了 7 分钟。 37 秒。创建一个压缩的“.txt”文件。相同的代码在更短的时间内创建一个未压缩的文件。有没有可能让它更快?
【解决方案3】:

所以,我的“大”问题在于如何“读取”回数据,写入数据实际上相对容易。

下面做一个“基本”的工作,使用一对StringJoiners 生成一个String,可以将其写入文件和一个有点复杂的解压缩过程。

这里的问题是,限制因素(至少对我而言)是您需要阅读文件的全部内容才能开始重建它。

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

我想知道,您是否不依赖 \n 作为分隔符,而是使用 ZipEntry,这将允许您一次处理每个单独的“行”数据...

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

打印出来的...

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

现在,很明显,您可能不知道需要多少行,作为第一个示例,一个简单的String#split 会告诉您。 (你可以预先阅读每个条目,但那是双重浸入)

是否可以让 ZipOutputStream 将“内容”保存到压缩文件“C:/Users/Username/Documents/Compressed folder.zip”中名为“Compressed file.txt”的压缩“.txt”文件中?

这完全取决于您,如果您不担心再次读取/解析文件,那么该过程可以大大减少(工作量和复杂性)。

因此,下面的示例将一次写入一行内容,因此您只需创建一行文本,然后将其写入ZipEntryStringJoiner 让这个过程变得非常简单

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

【讨论】:

  • 是否可以让 ZipOutputStream 将“内容”保存到压缩文件“C:/Users/Username/Documents/Compressed 文件夹中”名为“Compressed file.txt”的压缩“.txt”文件中。拉链”?
  • 这取决于您,将ZipEntry 更改为您想要的任何名称。我的问题是我没有看到你通过这条特定的路线实际上为自己节省了很多时间,但这就是我
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-26
相关资源
最近更新 更多