@SaintShadow

После записи объекта в конец файла(append), чтение дописанных данных выдает StreamCorruptedException, какие есть способы справиться?

Захотелось мне записывать сериализированные объекты в файл, для теста использую обычные строки. Записываю их в файл, потом считываю - все прекрасно. Закрываю программу и открываю снова, дописываю строки в конец файла, после чего снова считываю весь файл. Объекты записанные в первой сессии считываются, после чего вылетает StreamCorruptedException invalid type code: AC. Гугл подсказал, что этот АС, записывается в файл перед дописанными данными. ObjectInputStream натыкается на него, и не знает что делать дальше.
public class saveMessages {

	public static void main(String[] args) throws IOException, ClassNotFoundException {
		
		BufferedReader bR = new BufferedReader(new InputStreamReader(System.in));

		       FileOutputStream fos = new FileOutputStream("e:/temp.out", true);
		  ObjectOutputStream oos = new ObjectOutputStream(fos);
			while(true)
			{
				String s = bR.readLine();
				if(s.equals("show"))
				{
					oos.close();
					fos.close();
					break;
				}
		oos.writeObject(s);
				}
			show();		
			
			}
	

		


public static void show() throws IOException, ClassNotFoundException
{
FileInputStream fis = new FileInputStream("e:/temp.out");
ObjectInputStream oin = new ObjectInputStream(fis);	


while (fis.available() != 0)
{
	
	  
	  String ts = (String) oin.readObject();
	  System.out.println(ts);
	}
}
}


Видел совет - стереть этот AC (3 байта). Но я пока не разбирался как это сделать.
Еще был совет использовать чужой класс. Но как он там работает внутри я не понимаю. потому и не особо горю желанием использовать.
Есть ли какие-то более разумные методы борьбы?
  • Вопрос задан
  • 3621 просмотр
Пригласить эксперта
Ответы на вопрос 2
ehabarov
@ehabarov
IT Specialist
StackOverflow предлагает такой метод: Appending to an ObjectOutputStream
Суть метода:
- Если конечный файл не существует - то пользуемся обычным ObjectOutputStream для его создания (в этом случае в начало файла пишется нужная сигнатура).
- Если файл уже существует - пользуемся предложенным там классом AppendingObjectOutputStream, который предотвращает повторное формирование сигнатуры.

UPD: Пример кода, перенес из комментария.

AppendingObjectOutputStream.java - это копия кода со StackOverflow.
ObjectStreamTest.java - пример использования в программе.

Метод writeObject() - выполняет запись очередного объекта в файл.
В этот методе используется:
- ObjectOutputStream - если файл не существует (будет создан).
- AppendingObjectOutputStream - если файл уже существует (будет дозаписан).

Метод readObjects() - последовательно читает файл с объектами и отображает имя класса каждого считанного объекта. Используется, чтобы удостовериться, что файл читается нормально после дописывания.

--- AppendingObjectOutputStream.java ---
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;

public class AppendingObjectOutputStream extends ObjectOutputStream 
{
  public AppendingObjectOutputStream(OutputStream out) throws IOException 
  {
    super(out);
  }
  @Override
  protected void writeStreamHeader() throws IOException 
  {
    // do not write a header, but reset:
    // this line added after another question
    // showed a problem with the original
    reset();
  }
}

--- ObjectStreamTest.java ---
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class ObjectStreamTest 
{
  public static void main(String[] args) throws IOException, ClassNotFoundException 
  {
    String filename = "objFile.bin";
    writeObject(filename, new String("Test1"));
    writeObject(filename, new Integer(10));
    writeObject(filename, new Long(200));
    writeObject(filename, new String("Test2"));
    readObjects(filename);
  }
  public static void writeObject(String filename, Object obj) throws IOException
  {
    File file = new File(filename);
    FileOutputStream  fos = null;
    ObjectOutputStream oos = null;
    if ( file.exists() ) 
    {
      fos = new FileOutputStream(file, true);
      oos = new AppendingObjectOutputStream( fos );
    }
    else
    {
      fos = new FileOutputStream(file);
      oos = new ObjectOutputStream(fos);
    }
    oos.writeObject(obj);
    oos.close();
    fos.close();
  }
  public static void readObjects(String filename) throws IOException, ClassNotFoundException
  {
    FileInputStream  fis = new FileInputStream(filename);
    ObjectInputStream ois = new ObjectInputStream(fis);
    Object obj = null;
    try 
    {
      while ( (obj = ois.readObject() ) != null )
      {
        System.out.println("Object class is : "+obj.getClass().getName());
      }
    } 
    catch (EOFException e) 
    {
      System.out.println("End of file reached.");
    }
    ois.close();
    fis.close();
  }
}
Ответ написан
@a_f0x
сделай флаш потоков
public static void main(String[] args) throws IOException, ClassNotFoundException {
File file = new File("d:/temp.out");
if (!file.exists())
file.createNewFile();
BufferedReader bR = new BufferedReader(new InputStreamReader(System.in));
FileOutputStream fos = new FileOutputStream(file, true);
ObjectOutputStream oos = new ObjectOutputStream(fos);
while(true){
String s = bR.readLine();
if(s.equals("show")){
oos.flush();
fos.flush();
oos.close();
fos.close();
break;
}
oos.writeObject(s);
}
show();
}
public static void show() throws IOException, ClassNotFoundException{
File file = new File("d:/temp.out");
if (!file.exists())
file.createNewFile();
FileInputStream fis = new FileInputStream(file);
ObjectInputStream oin = new ObjectInputStream(fis);
while (fis.available()!=0){
String ts = (String) oin.readObject();
System.out.println(ts);
}
}
}
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы