将字节数组存储在对象中,然后将其转换为 ObjectOutputStream? (卡住)

Storing Byte Array inside an Object, and then converting it to ObjectOutputStream? (Stuck)

我有点被这个问题困住了。

我有这个 FileDetails class,它存储文件的 details/metadata 字节数组中的完整文件。我想通过网络发送 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 文件并通过 Internet 发送它。

有什么建议吗?或者替代方法?

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

非常感谢。

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

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,....)

如果需要,您也可以通过网络发送 class 定义。

这里我添加了read/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

我不确定接收者是否会对根据消息中发送的路径名写入的某些文件感到满意。