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

Java 在对象中存储字节数组,然后将其转换为ObjectOutputStream?(卡住了),java,bytearray,objectoutputstream,Java,Bytearray,Objectoutputstream,我被这个问题困住了 我有一个FileDetails类,它存储文件的详细信息/元数据以及 字节数组中的完整文件。我想通过网络发送ObjectOutputStream中的FileDetails对象,接收者将在其中 简单读取文件并将其转换回FileDetails 代码如下: class FileDetails { private String fileName; private long fileSize; private byte[] fileData; publ

我被这个问题困住了

我有一个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,因为我将添加 附加一个mp3文件作为ObjectOutStream文件的信息并通过internet发送

有什么建议吗?还是其他方法

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


提前非常感谢。

是否可以将该类添加到接收器? 然后你可以试试这样的东西:

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();
     }
   }
 }
接收器只需将字节写入临时文件(而不将其保存在内存中)

如果操作完成,实例化对象
FileDetails fd=newfiledetails(您刚刚创建的文件,…)


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

这里我添加了读/写对象方法:

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

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

您可以自由定义发送者和接收者之间的协议吗?将元数据(“详细信息”)作为对象发送,但附加字节“原始”,即通过从文件(例如test.dat)复制到输出流。这避免了将文件数据存储在字节数组中。我无法定义任何协议。实际上,我正在为android开发一个应用程序,它制作这个objectoutputstream文件,将其附加到mp3文件中,然后通过另一个“流行”消息应用程序发送这个mp3文件。接收器通过这个“流行”消息应用程序下载此mp3文件。现在我的应用程序开始运行并读取此mp3文件,如果mp3与预定义模式匹配,它将读取objectoutputstream数据并将文件保存到SD卡。总而言之,它是一款发送mp3文件中“隐藏”数据的应用程序。但该对象输出流的发送方和接收方都来自您?您定义了FileDetails类,不是吗?因此它必须位于两端。是的,FileDetails类位于两端。但我不确定如何读取和识别“元数据”字节和实际文件“test.dat”字节。您可以为java.io.Serializable编写自定义方法readObject和writeObject。我会尝试一下并在这里发布。我不能使用套接字发送文件。请阅读我的原始帖子的内联评论。代码工作得很好。劳恩,我非常感谢你。但还有一件事。接收者如何才能取回原始的“test.dat”文件?接收者必须(跳过mp3后)执行重命名后我在main中编写的代码:从对象输入流重建FileDetails。-应添加一些错误处理代码;另外,使用try-with-resource访问文件,等等。我这样做了,我得到了FileDetails对象。但我想提取实际的“test.dat”。假设我将一个pdf文件作为oos.dat(FileDetails对象)发送到mp3文件。接收方如何从oos.dat(FileDetails对象)获取pdf文件?请原谅我的无知,我刚刚开始学习java。谢谢。但是,在readObject期间,文件被写入“test.dat”。注意,我的main将test.dat重命名为test.dat.sav,因此实际上我正在从读取文件的位置重写该文件。在这两者之间,它存储在oos.dat中,它表示“在线数据”。这非常混乱。我将再一次深入研究代码。为你的帮助干杯。我真的很感激。祝你今天愉快,劳恩。
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