gpt4 book ai didi

JAVA:如何在二进制文件中正确存储对象?不覆盖

转载 作者:太空宇宙 更新时间:2023-11-04 11:31:51 26 4
gpt4 key购买 nike

我正在开发 Java 文件 I/O 接口(interface),我需要我的文件采用二进制格式,而不是字符串格式。我发现 ObjectOutputStream 和 ObjectInputStream 对我的需求很有用,但我需要接口(interface)能够在文件末尾写入,因为我需要它在同一文件中一遍又一遍地记录 future 的数据。

我尝试使用 FileOutputStream(String file, boolean append) 构造函数,但由于我的类实现了 Serialized,因此似乎存在问题。当它尝试读取第二条记录时,它会抛出 StreamCorruptedException。我知道这一定是因为有这个标题描述了对象的字段。

我的问题是,如何才能成功存储对象?我喜欢使用对象,因为它可以更轻松地构造和处理数据。这是我到目前为止的代码:

try
{
FileOutputStream outFile;
ObjectOutputStream outStream;
FileInputStream inFile;
ObjectInputStream inStream;

outFile = new FileOutputStream("people.mcf", true);
outStream = new ObjectOutputStream(outFile);

//Writing the objects
System.out.println("Writing file...");
for(int i = 0; i < 3; i++)
{
outStream.writeObject(people[i]);
}
System.out.println("Finished writing file...");
outFile.close();
outStream.close();
//Reading the files
System.out.println("Attempting to read file...");
inFile = new FileInputStream("people.mcf");
inStream = new ObjectInputStream(inFile);
Person buffer;
while(true)
{
buffer = (Person)inStream.readObject();
System.out.println(buffer.getData());
}

}
catch(EOFException e)
{
System.out.println("Reached end of file...");
}
catch(IOException e)
{
System.err.println(e.toString());
}

这是 Person 类:

static class Person implements Serializable
{
private final String name;
private final int age;
private final String address;

public Person(String name, int age, String address)
{
this.name = name;
this.age = age;
this.address = address;
}

public String getData()
{
return name + " " + age + " " + address;
}
}

这是我得到的输出:

Writing file...
Finished writing file...
Attempting to read file...
Andres 26 Palo Gordo
Pilar 22 Palo Gordo
Kelvin 27 Palo Gordo
java.io.StreamCorruptedException: invalid type code: AC
BUILD SUCCESSFUL (total time: 0 seconds)

编辑:我不是在问为什么会出现 StreamCorruptedException,我知道是 ObjectOutputStream 导致了这种情况,我要求的是另一种以结构化方式存储对象数据的方法。

最佳答案

如果您的记录具有固定长度或至少具有最大长度,则以下代码可以完成这项工作。

使用RandomAccessFile您将能够查找文件指针来写入新记录或更新现有记录。请参阅Indexed File in Wikipedia .

为了更加便携,您可以使用 ByteBuffer 序列化记录,已被 FileChannel 使用这是 RandomAccessFile 的接口(interface),请参阅 RandomAccessFile.getChannel() .

代码示例:

重新审视人员类别:

import java.nio.ByteBuffer;
import java.util.UUID;

public class Person implements ISerializable<UUID> {

private final UUID _id;
private final String _name;
private final int _age;
private final String _address;

public Person( ByteBuffer source ) {
_id = SerializeUtil.unserializeUUID( source );
_name = SerializeUtil.unserializeString( source );
_age = source.get();
_address = SerializeUtil.unserializeString( source );
}

public Person( String name, int age, String address) {
_id = UUID.randomUUID();
_name = name;
_age = age;
_address = address;
}

@Override
public UUID getKey() {
return _id;
}

@Override
public void serialize( ByteBuffer target ) {
target.clear();
SerializeUtil.serializeUUID ( _id , target );
SerializeUtil.serializeString( _name , target );
target.put((byte)_age );
SerializeUtil.serializeString( _address, target );
}
}

索引文件类:

import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Map;
import java.util.TreeMap;
import java.util.function.Consumer;
import java.util.function.Function;

public class IndexedFile<K extends Comparable<K>, R extends ISerializable<K>>
implements
Closeable
{
private final Map<K, Long> _index = new TreeMap<>();
private final RandomAccessFile _file;
private final FileChannel _channel;
private final ByteBuffer _record;
private final Function<ByteBuffer, R> _factory;

public IndexedFile( File tracksFile, int recordSize, Function<ByteBuffer, R> factory ) throws IOException {
_file = new RandomAccessFile( tracksFile, "rw" );
_channel = _file.getChannel();
_record = ByteBuffer.allocate( recordSize );
_factory = factory;
_channel.truncate( 0 );
}

@Override
public void close() throws IOException {
_file.close();
_channel.close();
}

public int size() {
return _index.size();
}

public int recordSize() {
return _record.capacity();
}

public void put( R record ) throws IOException {
final K key = record.getKey();
final Long offset = _index.get( key );
if( offset != null ) {
_channel.position( offset );
}
else {
final long pos = _channel.size();
_channel.position( pos );
_index.put( key, pos );
}
record.serialize( _record );
_record.position( _record.limit());
_record.flip();
_channel.write( _record );
}

public R read( int recNo ) throws IOException {
if( recNo >= _index.size()) {
return null;
}
final long offset = recNo*_record.capacity();
_channel.position( offset );
_record.clear();
_channel.read( _record );
_record.flip();
return _factory.apply( _record );
}

public R get( K key ) throws IOException {
final Long offset = _index.get( key );
if( offset == null ) {
return null;
}
_channel.position( offset );
_record.clear();
_channel.read( _record );
_record.flip();
return _factory.apply( _record );
}
}

为了完整性,实用程序类:

import java.nio.ByteBuffer;
import java.util.UUID;

public final class SerializeUtil {

public static void serializeString( String s, ByteBuffer target ) {
final byte[] bytes = s.getBytes();
target.putInt( bytes.length );
target.put( bytes );
}

public static String unserializeString( ByteBuffer target ) {
final int length = target.getInt();
final byte[] bytes = new byte[length];
target.get( bytes );
return new String( bytes );
}

public static void serializeUUID( UUID id, ByteBuffer target ) {
target.putLong( id.getMostSignificantBits());
target.putLong( id.getLeastSignificantBits());
}

public static UUID unserializeUUID( ByteBuffer source ) {
final long msb = source.getLong();
final long lsb = source.getLong();
return new UUID( msb, lsb );
}
}

以及接口(interface)ISerialized:

import java.nio.ByteBuffer;

public interface ISerializable<K extends Comparable<K>> {

public K getKey();

public void serialize( ByteBuffer target );
}

关于JAVA:如何在二进制文件中正确存储对象?不覆盖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43698661/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com