运行前:在这个路径下面有9个文件。
运行后:产生了一个 merge.txt 文件
文件内容展示
代码部分
这部分代码,功能很简单就是把一个个的文本文件合并后写入一个总的 merge.txt 文件夹,当时学会了往文件里追加内容,所以写了这个 demo。
简单来说就是获取每一个文件(文本文件,我进行了过滤。)得到一个输入流,然后一个循环内,每次将一个文件的信息写入合并的文件内,循环结束,文件合并就完成了。
package com.filemerge;import java.io.bufferedreader;import java.io.bufferedwriter;import java.io.file;import java.io.fileinputstream;import java.io.filenotfoundexception;import java.io.fileoutputstream;import java.io.ioexception;import java.io.inputstreamreader;import java.io.outputstreamwriter;public class filemerge { //参数为一个文件夹路径 public static void filemerge(string path){ file target = new file(path); //待合并文件夹目录 file output = new file(path+file.separator+"merge.txt"); //合并文件夹位置 string[] names = target.list((dir,name)->name.contains(".txt")); //过滤非文本文件,返回值为一个 string 数组 bufferedreader reader = null; bufferedwriter writer = null; //outputstreamwriter 不要记错了! try { writer = new bufferedwriter(new outputstreamwriter(new fileoutputstream(output,true))); for (string name : names) { reader = new bufferedreader(new inputstreamreader(new fileinputstream(target+file.separator+name))); string line = null; while((line = reader.readline()) != null) { writer.write(line); writer.newline(); } writer.newline(); //每个文件进行换行分隔内容! } system.out.println("file merge successfully!"); } catch (filenotfoundexception e) { e.printstacktrace(); } catch (ioexception e) { e.printstacktrace(); } finally { try { reader.close(); writer.close(); } catch (ioexception e) { e.printstacktrace(); } } }}
测试代码:
package com.filemerge;public class test { public static void main(string[] args) { filemerge.filemerge("d:/db/dreamdragon"); }}
图片文件合并(重点)如果看完了上面的文本文件合并的话,不妨再多看一点,把下面这个图片文件的代码也看了吧,如果有什么错误,欢迎指出来。(还有关于图片的一些知识,不知道谁能指出来一下。)
代码如下:合并图片工具类
package dragon;import java.io.bufferedinputstream;import java.io.bufferedoutputstream;import java.io.bufferedwriter;import java.io.file;import java.io.fileinputstream;import java.io.filenotfoundexception;import java.io.fileoutputstream;import java.io.ioexception;import java.io.outputstreamwriter;public class imagemerge { //图片合并路径,将要合并图片放入同一个文件夹方便操作 public static final string mergepath = "d:/dragondatafile/beauty"; public static final string outputpath = "d:/dragondatafile/merge"; //工具类,就只是用静态方法了,不要创建对象了。 private imagemerge() {} /**执行合并操作 * * 思路如下:首先获取文件夹下面的所有图片文件信息, * 然后使用输入输出流依次将文件进行合并操作。 * * 这里的信息是指的文件大小,最重要的是文件的大小, * 考虑其它因素,不记录文件名,所以拆分时,会丢失文件名, * 但是不影响图片的显示。 */ public static void imagemerge() throws ioexception { file mergefile = new file(imagemerge.mergepath); file outputfile = new file(imagemerge.outputpath); if (!initpath(mergefile, outputfile)) { // 无法创建 mergepath throw new filenotfoundexception("无法创建文件夹: "+imagemerge.mergepath); } try (//创建输出文件 bufferedoutputstream bos = new bufferedoutputstream(new fileoutputstream(new file(outputfile, system.currenttimemillis()+".jpeg")))){ file[] files = mergefile.listfiles(); recordimageinfo(files, outputfile); //记录文件信息,保存于图片的文件夹下,可能更好点。 for (file file : files) { try ( bufferedinputstream bis = new bufferedinputstream(new fileinputstream(file))){ int hasread = 0; byte[] b = new byte[1024]; while ((hasread = bis.read(b)) != -1) { bos.write(b, 0, hasread); } } } } } //初始化路径,如果 mergepath 不存在 private static boolean initpath(file mergefile, file outputfile) { boolean mk_mergefile = false, mk_outputfile = false; if (!mergefile.exists()) { // mergepath 不存在 mk_mergefile = mergefile.mkdirs(); } else { mk_mergefile = true; } if (!outputfile.exists()) { mk_outputfile = outputfile.mkdirs(); } else { mk_outputfile = true; } return mk_mergefile && mk_outputfile; } //记录信息 private static void recordimageinfo(file[] files, file outputfile) throws filenotfoundexception, ioexception { try ( bufferedwriter bos = new bufferedwriter(new outputstreamwriter(new fileoutputstream(new file(outputfile,"mergeimageinfo.txt"), true)))){ for (file file : files) { string record = file.length()+" "; bos.write(record); bos.newline(); } } } }
图片分隔工具类
package dragon;import java.io.bufferedinputstream;import java.io.bufferedoutputstream;import java.io.bufferedreader;import java.io.file;import java.io.fileinputstream;import java.io.filenotfoundexception;import java.io.fileoutputstream;import java.io.ioexception;import java.io.inputstreamreader;import java.util.linkedlist;import java.util.list;import java.util.uuid;public class imageseparate { //拆分文件的位置 private static final string separatepath = "d:/dragondatafile/separate"; private imageseparate() {} /** * 合并后文件夹下面有两个文件(应该每一批合并文件,一个单独的文件夹): * 合并后文件,合并文件信息(大小)。 * * 思路:首先读取合并文件信息,然后依据大小依次从文件中取出 * 对应大小的字节数,写入一个文件中。 * @throws ioexception * */ public static void imageseparate() throws ioexception { file separatefile = new file(imageseparate.separatepath); if (initpath(separatefile)) { //无法创建文件夹 throw new filenotfoundexception("无法创建文件夹: "+imageseparate.separatepath); } file outputfile = new file(imagemerge.outputpath); //下面获取的都是 string 数组,但是正常情况下应该都是只有一个 string 的字符串 //获取图片文件信息文件 file[] infofile = outputfile.listfiles(f->f.getname().contains(".txt")); //获取合并图片文件 file[] mergefile = outputfile.listfiles(f->!f.getname().contains(".txt")); // 获取信息文件信息(图片的长度) list<long> fileinfo = getfileinfo(infofile[0]); try ( bufferedinputstream bis = new bufferedinputstream(new fileinputstream(mergefile[0]))){ fileinfo.stream().foreach(len->{ string filename = system.currenttimemillis()+uuid.randomuuid().tostring()+".jpeg"; system.out.println(filename); try ( bufferedoutputstream bos = new bufferedoutputstream(new fileoutputstream(new file(separatefile, filename)))){ long record = 0; int hasread = 0; byte[] b = new byte[1024]; /** * 这里处理比较麻烦,我说明一下: * 一次性去读 len 长度的数据,考虑到有时候文件会非常大,这个数据对内存的压力很大, * 所以舍弃了,如果文件很小,倒也是一个很好的方式(简便)。 * * 这里采用逐次读取的方式:(一般图片都会大于 1024 字节的,这个不考虑) * 当读取一次后,判断剩余的字节数是否小于 1024,如果小于的话,就直接 * 一次性读取这些字节数,并写入文件中,然后跳出循环,本次文件读取完成。 * */ while ((hasread = bis.read(b)) != -1) { bos.write(b,0,hasread); //先判断,再读取数据,否则会出错。 record += (long)hasread; if (len-record < 1024) { long tail = len-record; bis.read(new byte[(int)tail]); bos.write(b, 0, (int)tail); break; } } } catch (ioexception e) { e.printstacktrace(); } }); } } //获取信息文件信息(图片的长度) private static list<long> getfileinfo(file file) throws numberformatexception, ioexception{ list<long> fileinfo = new linkedlist<>(); try ( bufferedreader br = new bufferedreader(new inputstreamreader(new fileinputstream(file)))){ string line = null; while ((line = br.readline()) != null) { //将数据转换为 long 再存入集合,或许使用 datainputstream 更好吧 //注意,如果这个文件里面被修改了,可能会引发 runtimeexception string[] str = line.split(" "); fileinfo.add(long.parselong(str[0])); system.out.println(line); } } return fileinfo; } //初始化 拆分文件位置 private static boolean initpath(file file) { return file.mkdirs(); }}
测试类
package dragon;import java.io.ioexception;public class client { public static void main(string[] args) throws ioexception, numberformatexception, classnotfoundexception { //如果需要合并图片,就使用第一条语句,注释第二条, //如果需要拆分图片,就使用第二条语句,注释第一条 imagemerge.imagemerge(); // imageseparate.imageseparate(); }}
说明:
每一个类都含有很多注释 ,应该还是能表达清楚意思的,有几点需要说明一下。
运行效果:
测试准备图片: 注意观察文件夹的路径和第一张图片。
测试准备图片信息: 注意观察文件的大小和占用空间信息。
合并效果: 注意观察合并后的图片和合并文件的路径。
合并后的文件会产生一个单独的文本文件,这里面存储的是图片的大小信息,因为恢复图片,是需要这些信息的,否则图片可能就回不来了。
注意:我当时看到这个结果,感觉很奇妙,虽然合并了37张图片,但是它居然还可以正常显示第一张图片的信息,这个可能和图片本身的存储形式有关(我没有这方面的知识)。
文本文件信息截图:
注:我是以行为单位进行存储的,每行一个数据,读取也是这样的,这样感觉比较方便。千万不能修改这个文件的任何信息,否则就无法恢复图片的信息了。
恢复图片: 注意观察右下角那张图片,因为我没有保留文件名,所以生成图片的文件名是重写生成的,还有注意到了我的文件名比较长,这个可以参考我开头的那个博客链接,这里是使用当前日期的毫秒数+uuid来生成的图片名,确实是比较长了,但是不会重复,这是我需要的。
控制台输入信息:
我会把读取的图片信息(每张图片的大小数据)和恢复图片时生成的图片文件名打印出来,这样调试比较方便,看起来也很好看,哈!
一些细节图片的合并就是单纯的文件合并,只是获取每一个文件的输入流,然后将其依次写入一个输出流中。(这里使用的是字节流,图片可不能使用字符流!)
for (file file : files) { try ( bufferedinputstream bis = new bufferedinputstream(new fileinputstream(file))){ int hasread = 0; byte[] b = new byte[1024]; while ((hasread = bis.read(b)) != -1) { bos.write(b, 0, hasread); } }}
这里比较难得是如何从一个整的合并图片中恢复所有图片的信息,因为图片的特殊存储格式,如果在图片的头部产生错误,就无法识别了(我只知道图片头部含有一个魔数,用于标识图片,其他的不是很清楚,我没有这图像方面的知识,如果有人知道,可以在下面评论。),一个字节也不行!
我来说一说我的想法:
举个例子,干巴巴的说着估计很难讲的明白。
先看下面这张图片,假定这是(合并后图片中)某个图片 的信息,我们需要在一个完整的输入流中,完整的取出来这一部分,不能多也不能少! 注意是顺序读取数据。再强调一下,这是中间某一张图片,也就是这个图表示某一个图片的数据,但是不是整个文件的数据,也就是说,这个图片下面还有数据,最下面那个小于 1024 byte,只是表示这张图片还剩下少于 1024 byte得数据。
所以下面这种读取方式是错误的,无法正确的恢复图片。
byte[] b = new byte[1024];while ((hasread = bis.read(b)) != -1) { bos.write(b, 0, hasread);}
其实有一种很简单的方式,就是下面注释中的方式,每次直接将整个图片的数据读取出来,写入一个输出流,就是一张完整得图片了,简单粗暴,但是我考虑到,有时候图片太大,对于内存是一个很大的消耗,没有采用这种方式。
仍然采用逐次读取的方式:
说明:
设置一个字节计数器,在每次读取(1024byte)之后,下一次读取之前,判断当前图片的大小和当前读入的字节数的差值是否大于 1024 字节,即是否满足一次完整的读取,如果满足的条件,就继续读取写入操作,如果不足 1024字节,说明不能再进行读取写入了(因为当前图片下面还有其它图片数据,所以仍然是可以读取 1024 字节的,只是属于当前图片的字节数,不足 1024 字节了,即不能进行一次完整的读取了。)所以,如果不足以进行一次完整的读取,那就只读当前还需要的字节,只需要读取一次就行了,读取之后将数据写入输出流,退出当前循环,进行下一张图片的读取。 可以画图观察一下,就会理解了。
try ( bufferedoutputstream bos = new bufferedoutputstream(new fileoutputstream(new file(separatefile, filename)))){ long record = 0; int hasread = 0; byte[] b = new byte[1024]; /** * 这里处理比较麻烦,我说明一下: * 一次性去读 len 长度的数据,考虑到有时候文件会非常大,这个数据对内存的压力很大, * 所以舍弃了,如果文件很小,倒也是一个很好的方式(简便)。 * * 这里采用逐次读取的方式:(一般图片都会大于 1024 字节的,这个不考虑) * 当读取一次后,判断剩余的字节数是否小于 1024,如果小于的话,就直接 * 一次性读取这些字节数,并写入文件中,然后跳出循环,本次文件读取完成。 * */ while ((hasread = bis.read(b)) != -1) { bos.write(b,0,hasread); //先判断,再读取数据,否则会出错。 record += (long)hasread; if (len-record < 1024) { long tail = len-record; bis.read(new byte[(int)tail]); bos.write(b, 0, (int)tail); break; } } } catch (ioexception e) { e.printstacktrace(); }
不足之处如果仔细阅读了我的代码,应该可以看出来了,有一些地方写的不好。
主要有以下几点:
没有保存图片的类型,恢复图片时,只能强行指定文件的后缀名为 jpeg,这样做不是很好的做法。
恢复图片时,直接指定为jpeg,不太合适。
string filename = system.currenttimemillis()+uuid.randomuuid().tostring()+".jpeg";
这个是创建合并文件时,指定第一张图片的后缀名,这样做也不是很好。
new file(outputfile, system.currenttimemillis()+".jpeg")
所以我对上面代码进行了改进,在保存图片的大小信息的同时,保存图片的后缀名信息(一般都是有的,但是如果没有的话,我就指定一个 “.none” 作为后缀名了)。一开始我是准备还是直接按照如下形式存储:
图片大小 [空格分隔] 图片后缀名
但是实际处理过程中,这样感觉还是比较麻烦的,因为存储的数据都是字符信息了,java是没有办法直接使用的,显示转换太麻烦了,所以我决定不使用这种方式了,转而使用java的对象序列化。因为同时需要大小和后缀名两个属性,而且两个属性之间也是具有很强关系的(一对一),干脆封装一下,做成一个java类,这样使用起来很方便,而且两个属性之间也建立了联系,序列化恢复也比较方便。而且对象序列化还带来一个好处,java的对象序列化是二进制序列化,区别于 json 这种字符序列化,二进制是机器读取的,我们就算打开了也是乱码,所以,可以避免这个文件被别人给修改了。(一般是不会去修改二进制文件的吧,哈!)
图片对象模型
package dragon;import java.io.serializable;/** * 文件信息模型类: * 记录文件的大小和后缀名,因为总是 * 需要使用这个,就把它封装起来使用吧。 * */public class fileinfo implements serializable{ /** * 序列化 id */ private static final long serialversionuid = 1l; private long len; private string suffix; public fileinfo(long len, string suffix) { this.len = len; this.suffix = suffix; } public long getlen() { return this.len; } public string getsuffix() { return this.suffix; } //重写 tostring 方法,方便打印调试代码 @override public string tostring() { return "fileinfo [len=" + len + ", suffix=" + suffix + "]"; }}
对于原来的图片合并和分隔方法,都进行了一点改进,所以命名规则上都在原来的类前面加了一个 enhance (增强、改进)。
改进的图片合并类:enhanceimagemerge
package dragon;import java.io.bufferedinputstream;import java.io.bufferedoutputstream;import java.io.file;import java.io.fileinputstream;import java.io.filenotfoundexception;import java.io.fileoutputstream;import java.io.ioexception;import java.io.objectoutputstream;import java.util.linkedlist;import java.util.list;public class enhanceimagemerge { //图片合并路径,将要合并图片放入同一个文件夹方便操作 public static final string mergepath = "d:/dragondatafile/beauty"; public static final string outputpath = "d:/dragondatafile/merge"; //工具类,就只是用静态方法了,不要创建对象了。 private enhanceimagemerge() {} /**执行合并操作 * * 思路如下:首先获取文件夹下面的所有图片文件信息, * 然后使用输入输出流依次将文件进行合并操作。 * * 这里的信息是指的文件大小,最重要的是文件的大小, * 考虑其它因素,不记录文件名,所以拆分时,会丢失文件名, * 但是不影响图片的显示。 */ public static void imagemerge() throws ioexception { file mergefile = new file(enhanceimagemerge.mergepath); file outputfile = new file(enhanceimagemerge.outputpath); if (!initpath(mergefile, outputfile)) { // 无法创建 mergepath throw new filenotfoundexception("无法创建文件夹: "+enhanceimagemerge.mergepath); } file[] files = mergefile.listfiles(); string suffix = recordimageinfo(files, outputfile); //记录文件信息,保存于图片的文件夹下,可能更好点。 try (//创建输出文件 bufferedoutputstream bos = new bufferedoutputstream(new fileoutputstream(new file(outputfile, system.currenttimemillis()+suffix)))){ for (file file : files) { try ( bufferedinputstream bis = new bufferedinputstream(new fileinputstream(file))){ int hasread = 0; byte[] b = new byte[1024]; while ((hasread = bis.read(b)) != -1) { bos.write(b, 0, hasread); } } } } } //初始化路径,如果 mergepath 不存在 private static boolean initpath(file mergefile, file outputfile) { boolean mk_mergefile = false, mk_outputfile = false; if (!mergefile.exists()) { // mergepath 不存在 mk_mergefile = mergefile.mkdirs(); } else { mk_mergefile = true; } if (!outputfile.exists()) { mk_outputfile = outputfile.mkdirs(); } else { mk_outputfile = true; } return mk_mergefile && mk_outputfile; } 使用对象序列化进行数据的存储,方便快捷。 private static string recordimageinfo(file[] files, file outputfile) throws filenotfoundexception, ioexception { try ( //二进制保存的数据,无法直接阅读,不加扩展名了 objectoutputstream oos = new objectoutputstream(new fileoutputstream(new file(outputfile, "fileinfo"), true))){ list<fileinfo> fileinfos = new linkedlist<>(); for (file file : files) { string filename = file.getname(); //记录文件的大小和扩展名信息 如果没有的话,默认设置为 none。 long len = file.length(); string suffix = filename.lastindexof(".") != -1 ? filename.substring(filename.lastindexof(".")) : ".none"; fileinfo fileinfo = new fileinfo(len, suffix); system.out.println(fileinfo.tostring()); fileinfos.add(fileinfo); } oos.writeobject(fileinfos); //直接将集合序列化,序列化单个对象,读取的时候太麻烦了 } string firstfilename = files[0].getname(); //返回第一个文件的后缀名。 return firstfilename.lastindexof(".") != -1 ? firstfilename.substring(firstfilename.lastindexof(".")) : ".none"; }}
注意:对象序列化的时候,如果每次序列化一个对象的话,那么读取的时候,就无法判断怎么结束了,因为程序不知道该读取多少次才结束,而且似乎不能使用读取结果为 null 来判断,那样会引发一个 eofexception。
我去查阅资料,有人推荐了,在序列化的最后,添加一个 null 对象,这确实是一个很好的方法,但是感觉还是不好。
另一种方式就是直接序列化一个list 集合,这样确实是方便多了,存入一个集合,读取回来了还是一个集合,可以直接操作了,还省去将对象再组装成集合的时间。(对象序列化,我只是了解,用过那么一两次,不是很熟。)
对象序列化部分
使用对象序列化进行数据的存储,方便快捷。private static string recordimageinfo(file[] files, file outputfile) throws filenotfoundexception, ioexception { try ( //二进制保存的数据,无法直接阅读,不加扩展名了 objectoutputstream oos = new objectoutputstream(new fileoutputstream(new file(outputfile, "fileinfo"), true))){ list<fileinfo> fileinfos = new linkedlist<>(); for (file file : files) { string filename = file.getname(); //记录文件的大小和扩展名信息 如果没有的话,默认设置为 none。 long len = file.length(); string suffix = filename.lastindexof(".") != -1 ? filename.substring(filename.lastindexof(".")) : ".none"; fileinfo fileinfo = new fileinfo(len, suffix); system.out.println(fileinfo.tostring()); fileinfos.add(fileinfo); } oos.writeobject(fileinfos); //直接将集合序列化,序列化单个对象,读取的时候太麻烦了 } string firstfilename = files[0].getname(); //返回第一个文件的后缀名。 return firstfilename.lastindexof(".") != -1 ? firstfilename.substring(firstfilename.lastindexof(".")) : ".none";}
改进的图片分隔类:enhanceimageseparate
package dragon;import java.io.bufferedinputstream;import java.io.bufferedoutputstream;import java.io.file;import java.io.fileinputstream;import java.io.filenotfoundexception;import java.io.fileoutputstream;import java.io.ioexception;import java.io.objectinputstream;import java.util.list;import java.util.uuid;public class enhanceimageseparate { //拆分文件的位置 private static final string separatepath = "d:/dragondatafile/separate"; private enhanceimageseparate() {} /** * 合并后文件夹下面有两个文件(应该每一批合并文件,一个单独的文件夹): * 合并后文件,合并文件信息(大小)。 * * 思路:首先读取合并文件信息,然后依据大小依次从文件中取出 * 对应大小的字节数,写入一个文件中。 * * @throws ioexception * @throws classnotfoundexception * @throws numberformatexception * */ public static void imageseparate() throws ioexception, numberformatexception, classnotfoundexception { file separatefile = new file(enhanceimageseparate.separatepath); if (initpath(separatefile)) { //无法创建文件夹 throw new filenotfoundexception("无法创建文件夹: "+enhanceimageseparate.separatepath); } file outputfile = new file(imagemerge.outputpath); //下面获取的都是 string 数组,但是正常情况下应该都是只有一个 string 的字符串 //获取图片文件信息文件 file[] infofile = outputfile.listfiles(f->!f.getname().contains(".")); //序列化文件是没有后缀名的 //获取合并图片文件 file[] mergefile = outputfile.listfiles(f->f.getname().contains(".")); //图片文件都是有后缀名的 // 获取信息文件信息(图片的长度) system.out.println(infofile[0]); list<fileinfo> fileinfos = getfileinfo(infofile[0]); mergeoperation(fileinfos, mergefile[0], separatefile); } /** * 执行文件合并操作 * @param fileinfos 文件信息集合 * @param 需要合并文件的文件夹 * @param separatefile 合并操作后的文件夹 * * @throws ioexception * @throws filenotfoundexception * */ private static void mergeoperation(list<fileinfo> fileinfos, file mergefile, file separatefile) throws filenotfoundexception, ioexception { try ( bufferedinputstream bis = new bufferedinputstream(new fileinputstream(mergefile))){ fileinfos.stream().foreach(fileinfo->{ long len = fileinfo.getlen(); string filename = system.currenttimemillis()+uuid.randomuuid().tostring()+fileinfo.getsuffix(); system.out.println(filename); try ( bufferedoutputstream bos = new bufferedoutputstream(new fileoutputstream(new file(separatefile, filename)))){ long record = 0; int hasread = 0; byte[] b = new byte[1024]; /** * 这里处理比较麻烦,我说明一下: * 一次性去读 len 长度的数据,考虑到有时候文件会非常大,这个数据对内存的压力很大, * 所以舍弃了,如果文件很小,倒也是一个很好的方式(简便)。 * * 这里采用逐次读取的方式:(一般图片都会大于 1024 字节的,这个不考虑) * 当读取一次后,判断剩余的字节数是否小于 1024,如果小于的话,就直接 * 一次性读取这些字节数,并写入文件中,然后跳出循环,本次文件读取完成。 * */ while ((hasread = bis.read(b)) != -1) { bos.write(b,0,hasread); //先判断,再读取数据,否则会出错。 record += (long)hasread; if (len-record < 1024) { long tail = len-record; bis.read(new byte[(int)tail]); bos.write(b, 0, (int)tail); break; } } } catch (ioexception e) { e.printstacktrace(); } }); } } //获取信息文件信息(图片的长度) //抑制一下 unchecked 警告 @suppresswarnings("unchecked") private static list<fileinfo> getfileinfo(file file) throws numberformatexception, ioexception, classnotfoundexception{ try ( objectinputstream ois = new objectinputstream(new fileinputstream(file))){ return (list<fileinfo>) ois.readobject(); //强制类型转换一下,读取出来的数据都是 object 类型 } } //初始化 拆分文件位置 private static boolean initpath(file file) { return file.mkdirs(); }}
注意: 分隔还原图片时,图片的后缀名部分代码为:
使用java封装属性后,使用很方便了。
string filename = system.currenttimemillis()+uuid.randomuuid().tostring()+fileinfo.getsuffix();
反序列化读取集合:
这里我抑制了一个强制类型转换的警告。
通过序列化,可以发现代码量大大减少了,直接就是集合,使用非常方便。
//抑制一下 unchecked 警告@suppresswarnings("unchecked")private static list<fileinfo> getfileinfo(file file) throws numberformatexception, ioexception, classnotfoundexception{ try ( objectinputstream ois = new objectinputstream(new fileinputstream(file))){ return (list<fileinfo>) ois.readobject(); //强制类型转换一下,读取出来的数据都是 object 类型 }}
测试代码
package dragon;import java.io.ioexception;public class client { public static void main(string[] args) throws ioexception, numberformatexception, classnotfoundexception { //如果需要合并图片,就使用第一条语句,注释第二条, //如果需要拆分图片,就使用第二条语句,注释第一条 enhanceimagemerge.imagemerge(); // enhanceimageseparate.imageseparate(); }}
改进后代码运行结果 执行合并方法时,打印的图片对象模型的信息
合并后的效果
注意观察右边的 fileinfo 文件,因为是二进制数据,我就没有给它加上文件后缀名,加上了也是无法直接阅读的,里面存储的是图片对象模型集合的序列化信息。
执行分隔操作后的效果
控制台输出图片信息,可以看到每个图片的后缀名都恢复了,注意看最后一个,有一个文本文件!哈哈!这个图片后面似乎可以添加任何数据,也许视频也是可以的,只是我没有测试,这个应该和图片的存储格式、显示方式有关。
注意,下面恢复的时候,确实是有一个文本文件,并且是完好的,可以阅读的。
合并后被分隔出的文本文件的信息
以上就是java文件合并与修改md5值的问题怎么解决的详细内容。
