问题是:
如何在没有读取要写入的文件的情况下将没有数组(列表)的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对象序列化到一个文件中?