ObjectOutputStream 追加写入读取错误
问题描述:
用类ObjectOutputStream向文件写读对象时,碰到一个问题:新建一个文件,用输出流ObjectOutputStream向文件连续写几个对象,关闭输出流,然 后读取,这些对象都可以读出;这时在向该文件增加对象,新写的对象就读不出了
问题出现的原因:
ObjectOutputStream建立后第一次写入一个对象时, 会在对象数据前写入一些标志的数据“AC ED 00 05”(用二进制方式查看打开),应该是流相关的信息。当你关闭 ObjectOutputStream 后再重新打开往文件里面写对象时(append方式),就会再一次把“AC ED 00 05”写入文件,而这些信息并不是你写入对象的数据,所以当你用ObjectInputStream来读取对象时,流会将除第一个“AC ED 00 05”以外的数据当作各个对象的数据,造成无法解析,所以读取时有一个java.io.StreamCorruptedException出现。 这个可以通过编辑Info.dat来验证,只要将“AC ED 00 05”删除(第一个“AC ED 00 05”保留)就可以正常读出后来加入的对象。 给出一个比较笨的解决方法: 在以后要添加新的对象到Info.dat时,将里面原有的对象读出放入ArrayList中,清空文件,再将对象集一次写入。
尝试解决办法:
那个“AC ED 00 05”是 ObjectOutputStream.writeSystemHeader()写进去的,你可以继承ObjectOutputStream类,覆盖这个方法。 在你自己的writeSystemHeader()里判断是不是第一次写入一个文件,如果是向一个文件大小不为零的文件追加的话,就调用 super.reset(),如果是第一次写这个文件,不是追加,就调用super.writeSystemHeader()
自定义类MyObjectOutputStream
[java] view plain copy
- /**
 
- * 此类继承ObjectOutputStream,重写writeStreamHeader()方法,以实现追加写入时去掉头部信息
 
- */
 
- public static class MyObjectOutputStream extends ObjectOutputStream {
 
- private static File f;
 
- // writeStreamHeader()方法是在ObjectOutputStream的构造方法里调用的
 
- // 由于覆盖后的writeStreamHeader()方法用到了f。如果直接用此构造方法创建
 
- // 一个MyObjectOutputStream对象,那么writeStreamHeader()中的f是空指针
 
- // 因为f还没有初始化。所以这里采用单态模式
 
- private MyObjectOutputStream(OutputStream out, File f) throws IOException, SecurityException {
 
- super(out);
 
- }
 
- // 返回一个MyObjectOutputStream对象,这里保证了new MyObjectOutputStream(out, f)
 
- // 之前f已经指向一个File对象
 
- public static MyObjectOutputStream newInstance(File file, OutputStream out) throws IOException {
 
- f = file;// 本方法最重要的地方:构建文件对象,两个引用指向同一个文件对象
 
- return new MyObjectOutputStream(out, f);
 
- }
 
- @Override
 
- protected void writeStreamHeader() throws IOException {
 
- // 文件不存在或文件为空,此时是第一次写入文件,所以要把头部信息写入。
 
- if (!f.exists() || (f.exists() && f.length() == 0)) {
 
- super.writeStreamHeader();
 
- } else {
 
- // 不需要做任何事情
 
- }
 
- }
 
- }
 
- /**
 - * 此类继承ObjectOutputStream,重写writeStreamHeader()方法,以实现追加写入时去掉头部信息
 - */
 - public static class MyObjectOutputStream extends ObjectOutputStream {
 - private static File f;
 - // writeStreamHeader()方法是在ObjectOutputStream的构造方法里调用的
 - // 由于覆盖后的writeStreamHeader()方法用到了f。如果直接用此构造方法创建
 - // 一个MyObjectOutputStream对象,那么writeStreamHeader()中的f是空指针
 - // 因为f还没有初始化。所以这里采用单态模式
 - private MyObjectOutputStream(OutputStream out, File f) throws IOException, SecurityException {
 - super(out);
 - }
 - // 返回一个MyObjectOutputStream对象,这里保证了new MyObjectOutputStream(out, f)
 - // 之前f已经指向一个File对象
 - public static MyObjectOutputStream newInstance(File file, OutputStream out) throws IOException {
 - f = file;// 本方法最重要的地方:构建文件对象,两个引用指向同一个文件对象
 - return new MyObjectOutputStream(out, f);
 - }
 - @Override
 - protected void writeStreamHeader() throws IOException {
 - // 文件不存在或文件为空,此时是第一次写入文件,所以要把头部信息写入。
 - if (!f.exists() || (f.exists() && f.length() == 0)) {
 - super.writeStreamHeader();
 - } else {
 - // 不需要做任何事情
 - }
 - }
 - }
 
测试方法:
[java] view plain copy
- public static void writeObject() throws Exception {
 
- String filename = "test.txt";
 
- File f = new File(filename);
 
- OutputStream os = new FileOutputStream(f, true);
 
- MyObjectOutputStream moos = MyObjectOutputStream.newInstance(f, os);
 
- moos.writeObject("abc");
 
- moos.writeObject(1);
 
- moos.close();
 
- }
 
												
											- public static void writeObject() throws Exception {
 - String filename = "test.txt";
 - File f = new File(filename);
 - OutputStream os = new FileOutputStream(f, true);
 - MyObjectOutputStream moos = MyObjectOutputStream.newInstance(f, os);
 - moos.writeObject("abc");
 - moos.writeObject(1);
 - moos.close();
 - }
 
ObjectOutputStream 追加写入读取错误的更多相关文章
- ObjectOutputStream 追加写入读取错误 - 自己的实现方案
		
本篇博客灵感来自http://blog.csdn.net/chenssy/article/details/13170015 问题描述.问题出现的原因.尝试解决办法,请参见鄙人上一编博客. 上一编文章解 ...
 - Java读取txt文件和覆盖写入txt文件和追加写入txt
		
//创建文件 public static void createFile(File filename) { try { if(!filename.exists()) { filename.create ...
 - python3读取、写入、追加写入excel文件
		
由于excel版本不同,python处理的时候选择的库页不同. 一.操作对应版本表格需要用到的库 1.操作xls格式的表格文件,需要用到的库如下: 读取:xlrd 写入:xlwt 修改(追加写入):x ...
 - net快速写入/读取大量数据Postgresql
		
Postgresql快速写入/读取大量数据 http://www.cnblogs.com/podolski/p/7152144.html 环境及测试 使用.net驱动npgsql连接post数据库.配 ...
 - 测开之路七十九:python 文件处理和对象的写入读取
		
"""处理文件:open(文件名, 模式,编码) 'r' 打开阅读(默认)'w' 打开写入,首先截断文件'x' 打开独占创建,如果文件已经存在则失败'a' 打开写入,追加 ...
 - JS+Selenium+excel追加写入,使用python成功爬取京东任何商品~
		
之前一直是requests库做爬虫,这次尝试下使用selenium做爬虫,效率不高,但是却没有限制,文章是分别结合大牛的selenium爬虫以及excel追加写入操作而成,还有待优化,打算爬取更多信息 ...
 - 安装vs2013以后,链接数据库总是报内存损坏,无法写入的错误
		
安装vs2013以后,链接数据库总是报内存损坏,无法写入的错误 这个错误几个月以前解决过一次,但是到又碰到的时候,竟然完全忘记当时怎么解决的了, 看来上了年纪记忆真是越来越不行了... 解决方案很简单 ...
 - DataContext 数据在F5刷新频繁,会出现数据读取错误
		
DataContext 数据在F5刷新频繁,会出现数据读取错误 DataContext是 Linq to sql数据模型的底层数据库对象所有LInq数据表对象都是由它派生的, 只要建立一个数据库操作, ...
 - Java基础知识强化之IO流笔记20:FileOutputStream写出数据实现换行和追加写入
		
1. 如何实现数据的换行? (1) package com.himi.fileoutputstream; import java.io.FileNotFoundException; import j ...
 
随机推荐
- Python 入门教程 9 ---- A Day at the Supermarket
			
第一节 1 介绍了for循环的用法 for variable in values: statement 2 for循环打印出列表的每一项 for item in [1 , 2 , 3]: print ...
 - POJ 1631 Bridging signals DP(最长上升子序列)
			
最近一直在做<挑战程序设计竞赛>的练习题,感觉好多经典的题,都值得记录. 题意:给你t组数据,每组数组有n个数字,求每组的最长上升子序列的长度. 思路:由于n最大为40000,所以n*n的 ...
 - js jquery 验证写法
			
<?php header("Content-type: text/html; charset=utf-8"); ?> <script src="jque ...
 - Java连接Oracle数据库的示例代码
			
最基本的Oracle数据库连接代码(只针对Oracle11g): 1.右键项目->构建路径 ->配置构建路径,选择第三项“库”,然后点击“添加外部Jar”,选择 “D:\Oracle\ap ...
 - 配置数据库连接池,Tomcat6.0 连接池的配置
			
Tomcat6.0 连接池的配置1.本人当前使用的Tomcat版本为:6.0.20,oracle为稳定的9i版本 2.下文为方便起见,依习惯以%Tomcat_Home%表示Tomcat安装的目录,本人 ...
 - SEXTANTE中调用任意C++控制台程序的简单例子
			
在sextante中单纯利用python或者调用sextante已有算法进行自定义开发,很多情况下速度不咋给力,同样的操作调用QGIS的C++插件比用sextante里的算法要快,有时候快的 还不止一 ...
 - javascript创建自定义对象和prototype
			
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
 - OpenCV——使用ROI进行图像切割
			
ROI(region of interest)——感兴趣区域. 1.用途 这个区域是图像分析所关注的重点.圈定这个区域,以便进行进一步的处理.而且,使用ROI指定 想读入的目标,可以减少处理时间,增加 ...
 - 写一个Windows上的守护进程(3)句柄的管理
			
写一个Windows上的守护进程(3)句柄的管理 在Windows中编程,跟HANDLE打交道是家常便饭.为了防止忘记CloseHandle,我都是使用do-while-false手法: void f ...
 - Qt模型/视图、委托
			
MVC视图和控制器对象相结合,其结果是模型/视图结构,仍然分离了数据与呈现给用户的方式,使得它可以在几个不同的视图中显示相同的数据,并实现新类型的视图而无需改变底层的数据结构.为了灵活的处理数据输入, ...