序列化许多没有Array的对象(List)

时间:2017-05-03 12:28:31

标签: java arrays serialization stack-overflow

问题是:

  

如何在没有读取要写入的文件的情况下将没有数组(列表)的MANY对象序列化到一个文件中?

我有点问题。

目前我正在编写一个名为File-O-Crypt的程序,该程序的任务是“压缩”并加密文件Directorys和Sub Files。 对于对代码感兴趣的人来说,所有重要的课程都是:(不是必需的)

package com.niton.cryptor;
import java.io.IOException;
import java.io.Serializable;
import java.nio.file.Files;

import com.niton.media.filesystem.Directory;
import com.niton.media.filesystem.NFile;

public class FileStore implements Serializable
{
    private static final long serialVersionUID = 3415969338489934461L;
    private byte[] content;
    private String name;
    private String relativePath;
    public FileStore() {
        // TODO Auto-generated constructor stub
    }
    public FileStore(NFile file,Directory lastSameParent){
        try {
            content = Files.readAllBytes(file.getPath());
        } catch (IOException e) {
            LOGGER.error(e);
            e.printStackTrace();
        }
        try{
            name = file.getName()+"."+file.getEnding();
        }catch (Exception e) { }
        relativePath = file.getPathAsString();
        relativePath = relativePath.replace(lastSameParent.getPathAsString(), "");
    }

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }
    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }
    /**
     * @return the relativePath
     */
    public String getRelativePath() {
        return relativePath;
    }
    /**
     * @param relativePath the relativePath to set
     */
    public void setRelativePath(String relativePath) {
        this.relativePath = relativePath;
    }
    @Override
    public String toString() {
        return relativePath;
    }
    /**
     * @return the content
     */
    public byte[] getContent() {
        return content;
    }
    /**
     * @param content the content to set
     */
    public void setContent(byte[] content) {
        this.content = content;
    }
}

解释NFile和Directory:它们来自一个简单的FileHandling Lib。但这些方法的名称正在描述他们的自我。

现在的代码是打包文件的代码:

LOGGER.log("Opening File Chooser", log);
        JFileChooser saver = new JFileChooser();
        saver.setFileSelectionMode(JFileChooser.FILES_ONLY);
        saver.setDialogTitle("Save Location");
        saver.setDialogType(JFileChooser.SAVE_DIALOG);
        saver.setMultiSelectionEnabled(false);
        saver.setApproveButtonText("Save");
        saver.showOpenDialog(frmFileocrypt);
        saver.setFileFilter(new FileFilter() {

            @Override
            public String getDescription() {
                return "Crypted Pack (.pack)";
            }

            @Override
            public boolean accept(File f) {
                return f.getName().endsWith(".pack") || f.isDirectory();
            }
        });
        saver.setAcceptAllFileFilterUsed(false);
        NFile file = new NFile(saver.getSelectedFile());

        String pwd1 = new String(packPwd1.getPassword());
        String pwd2 = new String(packPwd2.getPassword());
        if(!pwd1.equals(pwd2))
        {
            JOptionPane.showMessageDialog(null, "The Passwords are not the same!");
            LOGGER.log("Passwords do not match", log);
            return;
        }
        method = null;
        if(noEncrypt.isSelected())
            method = CryptMethod.No;
        if(noPwd.isSelected())
            method = CryptMethod.NoPwd;
        if(pwdSimple.isSelected())
            method = CryptMethod.sPwd;
        if(pwdExtreme.isSelected())
            method = CryptMethod.exPwd;

        if(method != CryptMethod.No)
        {
            if(createTemporaryFiles){

            }
            else
            {
                LOGGER.log("Start Crypting Files ...", log);
                ArrayList<FileStore> newStores = new ArrayList<>();
                loader.setMaximum(newStores.size());
                loader.setValue(0);
                for(FileStore store : fileStores)
                {
                    System.out.println("Threads used : "+Thread.activeCount()+"/"+maxThreads);
                    if(Thread.activeCount() < maxThreads){
                        new Thread(new Runnable() {

                            @Override
                            public void run()
                            {
                                CryptMethod methodX = method;
                                LOGGER.log("Crypt File : "+store.getName(), log);
                                newStores.add(new CryptedFileStore(store, methodX, pwd1));
                                LOGGER.log("File Store Complete Crypted", log);
                                loader.setValue(loader.getValue()+1);
                            }
                        }).start();
                    }else{
                        LOGGER.log("Crypt File : "+store.getName(), log);
                        newStores.add(new CryptedFileStore(store, method, pwd1));
                        LOGGER.log("File Store Complete Crypted", log);
                        loader.setValue(loader.getValue()+1);
                    }

                }
                fileStores = newStores;

            }
        }
        LOGGER.log("File Choosen : "+file.getPathAsString(), log);
        DataSaver<ArrayList<FileStore>> s = new DataSaver<>();
        try {

            LOGGER.log("Start Saving Files ...", log);
            s.save(fileStores, file);
            LOGGER.log("Files Saved", log);
        } catch (IOException e) {
            LOGGER.error(e);
            e.printStackTrace();
        }

你看我正在保存一个文件存储的ArrayList(上面的源代码)。 但现在问题是:

如果有人用例如36GB打包整个USB Stick我得到 StackOverflowError 因为我有一个数组文件列表(包含内容)所以我会需要40GB RAM 要解决这个问题,我必须先保存文件,
然后是这样的:(files是序列化文件库的数组,pack是生成的zip文件)

for(NFile nf : files){
    appendFile(nf,pack);
}

public static void appendFile(NFile from,NFile to){
        try {
            byte[] allBs = Files.readAllBytes(from.getPath());
            byte[] seperator = "SOME MARKER FOR SEPERATING".getBytes();
            byte[] content = new byte[allBs.length+seperator.length];
            for(int i = 0;i<allBs.length;i++){
                content[i] = allBs[i];
            }
            for(int i = 0;i<seperator.length;i++){
                content[i+allBs.length] = seperator[i];
            }
            Files.write(to.getPath(),content , StandardOpenOption.APPEND);
        } catch (Exception e) {
            // TODO: handle exception
        }
    }

它会起作用我认为但是当文件包含分隔符String时我有问题,因为那时我将无法再读它了所以最终的问题是:

  

如何在没有读取要写入的文件的情况下将没有数组(列表)的MANY对象序列化到一个文件中?

0 个答案:

没有答案