2015-02-08 63 views
3

我有点卡住这个问题。在对象中存储字节数组,然后将其转换为ObjectOutputStream? (卡住)

我有这个FileDetails类存储文件的细节/元数据以及 整个文件在字节数组中。我想通过网络发送ObjectOutputStream中的FileDetails对象,接收者将在其中简单地读取文件并将其转换回FileDetails。

下面是代码:

class FileDetails { 

    private String fileName; 
    private long fileSize; 
    private byte[] fileData; 

    public FileDetails(String fileName, long fileSize, byte[] fileData) { 
     this.fileName = fileName; 
     this.fileSize = fileSize;  
     this.fileData = fileData; 
    } 

    public String getFileName() { 
     return fileName; 
    } 

    public long getFileSize() { 
     return fileSize; 
    } 

    public byte[] getFileData() { 
     return fileData; 
    } 

} 


File file = new File("C://test.dat"); 
RandomAccessFile randFileAccess = new RandomAccessFile(file, "r"); 
byte[] buff = new byte[(int) file.length()]; 
randFileAccess.readFully(buff); 

FileDetails fd = new FileDetails(file.getname(), file.length(); buff); 

FileOutputStream fos = = new FileOutputStream(C://oos.dat); 
ObjectOutputStream oos = new ObjectOutputStream(fos); 
oos.writeObject(fd); 
oos.write(buff); 

的问题是,该文件“TEST.DAT”是相当大的,它不是最佳的阅读它充分考虑一气呵成缓冲(很大)。我本来可以将 文件读入缓冲区中,但这需要我创建文件并将数据保存到磁盘中,而FileDetails对象使用字节数组时,我无法做到这一点。

我怎样才能解决这个问题?我只需要这种方法,即将数据作为字节数组存储在FileDetails对象中,然后将其转换为ObjectOutputStream,因为我将追加 追加ObjectOutStream文件的mp3文件信息并通过互联网发送。

任何暗示?还是另类办法?

编辑:其实我正在开发一个android应用程序。它将FileDetails对象中的文件元数据与字节数组中的文件数据一起存储。 将此FileDetails对象转换为ObjectOutputStream文件。现在,在此ObjectOutputStream文件前面附加了一个特定的mp3文件,该文件用于识别文件是否已由我的应用程序发送。 这个组合的mp3文件(包含“隐藏的”ObjectOutputStream文件)通过“流行”消息应用程序发送到接收器。 接收器通过他的“流行”消息应用下载mp3文件。现在我的应用程序开始运作。它识别mp3文件。并从mp3文件中提取ObjectOutputStream文件。并将其转换回FileDetails并使用其元数据检索原始文件。 我的方法是否正确?有没有其他方法来识别我的附加/隐藏文件?

非常感谢。

+1

您可以自由定义发件人和收件人之间的协议吗?发送元数据(“细节”)作为对象,但附加“原始”字节,即通过从文件(例如test.dat)复制到输出流。这样可以避免将文件数据存储在字节数组中。 – laune 2015-02-08 13:44:17

+0

我无法定义任何协议。其实我正在开发一个android应用程序,它使这个objectoutputstream文件,附加到mp3文件,然后通过另一个“流行”的消息应用程序发送这个MP3文件。接收器通过这个“流行”的消息应用下载这个mp3文件。现在我的应用程序开始运行并读取此mp3文件,如果mp3匹配了预定义的模式,它将读取objectoutputstream数据并将文件保存到SD卡。总而言之,这是一个将数据“隐藏”在mp3文件中的应用程序。 – Retr0spect 2015-02-08 13:53:03

+0

但该对象输出流的发送者和接收者来自你?你定义了类FileDetails,不是吗 - 所以它必须在任何一端。 – laune 2015-02-08 13:57:20

回答

1

在这里,我已经添加了读/的writeObject方法:

class FileDetails implements Serializable { 
    private static final int CHUNK_LEN = 0x10000; // 64k 
    private String fileName; 
    private long fileSize; 
    private File file; 

    // Note: everything can be deduced from a File object 
    public FileDetails(File file) { 
    this.fileName = file.getName(); 
    this.fileSize = file.length();  
    this.file = file; 
    } 

    public String getFileName() { 
    return fileName; 
    } 

    public long getFileSize() { 
    return fileSize; 
    } 

    // explicit coding for reading a FileDetails object 
    private void readObject(ObjectInputStream stream) 
    throws IOException, ClassNotFoundException { 
    fileName = stream.readUTF(); // file name 
    fileSize = stream.readLong(); // file size 
    // file data as a series of byte[], length CHUNK_LEN 
    long toRead = fileSize; 
    // write file data to a File object, same path name 
    file = new File(fileName); 
    OutputStream os = new FileOutputStream(file); 
    while(toRead > 0){ 
     // last byte arrays may be shorter than CHUNK_LEN 
     int chunkLen = toRead > CHUNK_LEN ? CHUNK_LEN : (int)toRead; 
     byte[] bytes = new byte[chunkLen]; 
     int nread = stream.read(bytes); 
     // write data to file 
     os.write(bytes, 0, nread); 
     toRead -= nread; 
    } 
    os.close(); 
    } 

    // explicit coding for writing a FileDetails object 
    private void writeObject(ObjectOutputStream stream) 
    throws IOException { 
    stream.writeUTF(fileName); // file name as an "UTF string" 
    stream.writeLong(fileSize); // file size 
    // file data as a series of byte[], length CHUNK_LEN 
    long toWrite = fileSize; 
    // read file data from the File object passed to the constructor 
    InputStream is = new FileInputStream(file); 
    while(toWrite > 0){ 
     // last byte[] may be shorter than CHUNK_LEN 
     int chunkLen = toWrite > CHUNK_LEN ? CHUNK_LEN : (int)toWrite; 
     byte[] bytes = new byte[chunkLen]; 
     int nread = is.read(bytes); 
     stream.write(bytes); 
     toWrite -= nread; 
    } 
    is.close(); 
    } 

    private void readObjectNoData() 
    throws ObjectStreamException { 
    } 
} 

我和短文件测试此:

File file = new File("test.dat"); 
FileDetails fd = new FileDetails(file); 
FileOutputStream fos = new FileOutputStream("oos.dat"); 
ObjectOutputStream oos = new ObjectOutputStream(fos); 
oos.writeObject(fd); 
oos.close(); 

// test on a local system: rename test.dat to avoid overwriting 
file.renameTo(new File("test.dat.sav")); 

FileInputStream fis = new FileInputStream("oos.dat"); 
ObjectInputStream ois = new ObjectInputStream(fis); 
FileDetails fd1 = (FileDetails)ois.readObject(); 
ois.close(); 
// now the file test.dat has been rewritten under the same path, 
// i.e., test.dat exists again and test.dat.sav == test.dat 

我不知道接收者是否会很乐意与某些文件是根据消息中发送的路径名写入的。

+0

代码工作完美。劳恩,我不能够感谢你。但还有一件事。接收器如何取回原始的“test.dat”文件? – Retr0spect 2015-02-08 15:21:36

+0

接收器必须(在跳过mp3之后)在重命名后执行我在main中编码的内容:从对象输入流重建FileDetails。 - 应该添加一些错误处理代码;另外,请使用try-with-resource来访问文件等。 – laune 2015-02-08 16:21:37

+0

我这样做,我得到FileDetails对象。但我想提取实际的“test.dat”。假设我发送一个附加到mp3文件的pdf文件作为oos.dat(FileDetails对象)。接收器如何从oos.dat(FileDetails对象)获取pdf文件?请原谅我的无知,我刚开始学习java。谢谢。 – Retr0spect 2015-02-08 16:43:37

2

是否有可能将类添加到接收器? 那么你可以尝试这样的事:

File file = new File("C://test.dat") 
InputStream in = null; 
    try { 
    in = new BufferedInputStream(new FileInputStream(file)); 
    -> send over the network 
    finally { 
    if (in != null) { 
     in.close(); 
    } 
    } 
} 

接收器可以只写字节到一个临时文件(并在内存中没有追究他们)

InputStream is = socket.getInputStream(); 
FileOutputStream fos = new FileOutputStream("C://test.dat"); 
BufferedOutputStream bos = new BufferedOutputStream(fos); 
//something like: 
byte[] buffer = new byte[1024]; 
int len = is.read(buffer); 
while (len != -1) { 
    bos.write(buffer, 0, len); 
    len = is.read(buffer); 
} 

如果操作完成后,实例对象FileDetails fd = new FileDetails(the file you just created,....)

如果必须,您还可以通过网络发送类定义。

+0

我无法使用套接字发送文件。请阅读我原始帖子的内嵌评论。 – Retr0spect 2015-02-08 14:13:57

+0

好的,这让我的回答毫无意义 – Leander 2015-02-08 14:15:50

相关问题