how2j.cn


工具版本兼容问题
InputStream字节输入流
OutputStream字节输出流
用于以字节的形式读取和写入数据


本视频是解读性视频,所以希望您已经看过了本知识点的内容,并且编写了相应的代码之后,带着疑问来观看,这样收获才多。 不建议一开始就观看视频



7分31秒
本视频采用html5方式播放,如无法正常播放,请将浏览器升级至最新版本,推荐火狐,chrome,360浏览器。 如果装有迅雷,播放视频呈现直接下载状态,请调整 迅雷系统设置-基本设置-启动-监视全部浏览器 (去掉这个选项)。 chrome 的 视频下载插件会影响播放,如 IDM 等,请关闭或者切换其他浏览器



步骤 1 : ASCII码 概念   
步骤 2 : 以字节流的形式读取文件内容   
步骤 3 : 以字节流的形式向文件写入数据   
步骤 4 : 练习-写入数据到文件   
步骤 5 : 答案-写入数据到文件   
步骤 6 : 练习-拆分文件   
步骤 7 : 答案-拆分文件   
步骤 8 : 练习-合并文件   
步骤 9 : 答案-合并文件   

所有的数据存放在计算机中都是以数字的形式存放的。 所以字母就需要转换为数字才能够存放
比如A就对应的数字65,a对应的数字97. 不同的字母和符号对应不同的数字,就是一张码表。
ASCII是这样的一种码表。 只包含简单的英文字母,符号,数字等等。 不包含中文,德文,俄语等复杂的。

示例中列出了可见的ASCII码以及对应的十进制和十六进制数字,不可见的暂未列出
<style> *{ font-size:15px; } table.t2{ border-collapse:collapse; width:300px; } td{ text-align:center; background-color:#F5F5DC; } tr.firstline td{ background-color:#F0F8FF; } </style> <table class="t2" border="1" width="100%"> <tr class="firstline"> <td width="33%">字符</td> <td width="33%" >十进制数字</td> <td >十六进制数字</td> </tr> <tr><td >!</td><td >33</td><td >21</td></tr> <tr><td >"</td><td >34</td><td >22</td></tr> <tr><td >#</td><td >35</td><td >23</td></tr> <tr><td >$</td><td >36</td><td >24</td></tr> <tr><td >%</td><td >37</td><td >25</td></tr> <tr><td >&</td><td >38</td><td >26</td></tr> <tr><td >'</td><td >39</td><td >27</td></tr> <tr><td >(</td><td >40</td><td >28</td></tr> <tr><td >)</td><td >41</td><td >29</td></tr> <tr><td >*</td><td >42</td><td >2A</td></tr> <tr><td >+</td><td >43</td><td >2B</td></tr> <tr><td >,</td><td >44</td><td >2C</td></tr> <tr><td >-</td><td >45</td><td >2D</td></tr> <tr><td >.</td><td >46</td><td >2E</td></tr> <tr><td >/</td><td >47</td><td >2F</td></tr> <tr><td >0</td><td >48</td><td >30</td></tr> <tr><td >1</td><td >49</td><td >31</td></tr> <tr><td >2</td><td >50</td><td >32</td></tr> <tr><td >3</td><td >51</td><td >33</td></tr> <tr><td >4</td><td >52</td><td >34</td></tr> <tr><td >5</td><td >53</td><td >35</td></tr> <tr><td >6</td><td >54</td><td >36</td></tr> <tr><td >7</td><td >55</td><td >37</td></tr> <tr><td >8</td><td >56</td><td >38</td></tr> <tr><td >9</td><td >57</td><td >39</td></tr> <tr><td >:</td><td >58</td><td >3A</td></tr> <tr><td >;</td><td >59</td><td >3B</td></tr> <tr><td ><</td><td >60</td><td >3C</td></tr> <tr><td >=</td><td >61</td><td >3D</td></tr> <tr><td >></td><td >62</td><td >3E</td></tr> <tr><td >@</td><td >64</td><td >40</td></tr> <tr><td >A</td><td >65</td><td >41</td></tr> <tr><td >B</td><td >66</td><td >42</td></tr> <tr><td >C</td><td >67</td><td >43</td></tr> <tr><td >D</td><td >68</td><td >44</td></tr> <tr><td >E</td><td >69</td><td >45</td></tr> <tr><td >F</td><td >70</td><td >46</td></tr> <tr><td >G</td><td >71</td><td >47</td></tr> <tr><td >H</td><td >72</td><td >48</td></tr> <tr><td >I</td><td >73</td><td >49</td></tr> <tr><td >J</td><td >74</td><td >4A</td></tr> <tr><td >K</td><td >75</td><td >4B</td></tr> <tr><td >L</td><td >76</td><td >4C</td></tr> <tr><td >M</td><td >77</td><td >4D</td></tr> <tr><td >N</td><td >78</td><td >4E</td></tr> <tr><td >O</td><td >79</td><td >4F</td></tr> <tr><td >P</td><td >80</td><td >50</td></tr> <tr><td >Q</td><td >81</td><td >51</td></tr> <tr><td >R</td><td >82</td><td >52</td></tr> <tr><td >S</td><td >83</td><td >53</td></tr> <tr><td >T</td><td >84</td><td >54</td></tr> <tr><td >U</td><td >85</td><td >55</td></tr> <tr><td >V</td><td >86</td><td >56</td></tr> <tr><td >W</td><td >87</td><td >57</td></tr> <tr><td >X</td><td >88</td><td >58</td></tr> <tr><td >Y</td><td >89</td><td >59</td></tr> <tr><td >Z</td><td >90</td><td >5A</td></tr> <tr><td >[</td><td >91</td><td >5B</td></tr> <tr><td >\</td><td >92</td><td >5C</td></tr> <tr><td >]</td><td >93</td><td >5D</td></tr> <tr><td >^</td><td >94</td><td >5E</td></tr> <tr><td >_</td><td >95</td><td >5F</td></tr> <tr><td >`</td><td >96</td><td >60</td></tr> <tr><td >a</td><td >97</td><td >61</td></tr> <tr><td >b</td><td >98</td><td >62</td></tr> <tr><td >c</td><td >99</td><td >63</td></tr> <tr><td >d</td><td >100</td><td >64</td></tr> <tr><td >e</td><td >101</td><td >65</td></tr> <tr><td >f</td><td >102</td><td >66</td></tr> <tr><td >g</td><td >103</td><td >67</td></tr> <tr><td >h</td><td >104</td><td >68</td></tr> <tr><td >i</td><td >105</td><td >69</td></tr> <tr><td >j</td><td >106</td><td >6A</td></tr> <tr><td >k</td><td >107</td><td >6B</td></tr> <tr><td >l</td><td >108</td><td >6C</td></tr> <tr><td >m</td><td >109</td><td >6D</td></tr> <tr><td >n</td><td >110</td><td >6E</td></tr> <tr><td >o</td><td >111</td><td >6F</td></tr> <tr><td >p</td><td >112</td><td >70</td></tr> <tr><td >q</td><td >113</td><td >71</td></tr> <tr><td >r</td><td >114</td><td >72</td></tr> <tr><td >s</td><td >115</td><td >73</td></tr> <tr><td >t</td><td >116</td><td >74</td></tr> <tr><td >u</td><td >117</td><td >75</td></tr> <tr><td >v</td><td >118</td><td >76</td></tr> <tr><td >w</td><td >119</td><td >77</td></tr> <tr><td >x</td><td >120</td><td >78</td></tr> <tr><td >y</td><td >121</td><td >79</td></tr> <tr><td >z</td><td >122</td><td >7A</td></tr> <tr><td >{</td><td >123</td><td >7B</td></tr> <tr><td >|</td><td >124</td><td >7C</td></tr> <tr><td >}</td><td >125</td><td >7D</td></tr> <tr><td >~</td><td >126</td><td >7E</td></tr> </table>


源代码
1. 双击选中单词 2. 三击选中整行 3. CTRL+F 查找 4. F8 全屏编辑,再次点击恢复
渲染中 渲染完成
效果
步骤 2 :

以字节流的形式读取文件内容

edit
InputStream是字节输入流,同时也是抽象类,只提供方法声明,不提供方法的具体实现。
FileInputStream 是InputStream子类,以FileInputStream 为例进行文件读取
package stream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; public class TestStream { public static void main(String[] args) { try { //准备文件lol.txt其中的内容是AB,对应的ASCII分别是65 66 File f =new File("d:/lol.txt"); //创建基于文件的输入流 FileInputStream fis =new FileInputStream(f); //创建字节数组,其长度就是文件的长度 byte[] all =new byte[(int) f.length()]; //以字节流的形式读取文件所有内容 fis.read(all); for (byte b : all) { //打印出来是65 66 System.out.println(b); } //每次使用完流,都应该进行关闭 fis.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
步骤 3 :

以字节流的形式向文件写入数据

edit
OutputStream是字节输出流,同时也是抽象类,只提供方法声明,不提供方法的具体实现。
FileOutputStream 是OutputStream子类,以FileOutputStream 为例向文件写出数据

注: 如果文件d:/lol2.txt不存在,写出操作会自动创建该文件。
但是如果是文件 d:/xyz/lol2.txt,而目录xyz又不存在,会抛出异常
以字节流的形式向文件写入数据
package stream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; public class TestStream { public static void main(String[] args) { try { // 准备文件lol2.txt其中的内容是空的 File f = new File("d:/lol2.txt"); // 准备长度是2的字节数组,用88,89初始化,其对应的字符分别是X,Y byte data[] = { 88, 89 }; // 创建基于文件的输出流 FileOutputStream fos = new FileOutputStream(f); // 把数据写入到输出流 fos.write(data); // 关闭输出流 fos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
步骤 4 :

练习-写入数据到文件

edit  姿势不对,事倍功半! 点击查看做练习的正确姿势
以字节流的形式向文件写入数据 中的例子,当lol2.txt不存在的时候,是会自动创建lol2.txt文件的。
但是,如果是写入数据到d:/xyz/lol2.txt,而目录xyz又不存在的话,就会抛出异常。
那么怎么自动创建xyz目录?
如果是多层目录 d:/xyz/abc/def/lol2.txt 呢?
练习-写入数据到文件
步骤 5 :

答案-写入数据到文件

edit
在查看答案前,尽量先自己完成,碰到问题再来查看答案,收获会更多
在查看答案前,尽量先自己完成,碰到问题再来查看答案,收获会更多
在查看答案前,尽量先自己完成,碰到问题再来查看答案,收获会更多
查看本答案会花费3个积分,您目前总共有点积分。查看相同答案不会花费额外积分。 积分增加办法 或者一次性购买JAVA 中级总计0个答案 (总共需要0积分)
查看本答案会花费3个积分,您目前总共有点积分。查看相同答案不会花费额外积分。 积分增加办法 或者一次性购买JAVA 中级总计0个答案 (总共需要0积分)
账号未激活 账号未激活,功能受限。 请点击激活
本视频是解读性视频,所以希望您已经看过了本答案的内容,带着疑问来观看,这样收获才多。 不建议一开始就观看视频

1分58秒 本视频采用html5方式播放,如无法正常播放,请将浏览器升级至最新版本,推荐火狐,chrome,360浏览器。 如果装有迅雷,播放视频呈现直接下载状态,请调整 迅雷系统设置-基本设置-启动-监视全部浏览器 (去掉这个选项)。 chrome 的 视频下载插件会影响播放,如 IDM 等,请关闭或者切换其他浏览器


package stream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; public class TestStream { public static void main(String[] args) { try { File f = new File("d:/xyz/abc/def/lol2.txt"); //因为默认情况下,文件系统中不存在 d:\xyz\abc\def,所以输出会失败 //首先获取文件所在的目录 File dir = f.getParentFile(); //如果该目录不存在,则创建该目录 if(!dir.exists()){ // dir.mkdir(); //使用mkdir会抛出异常,因为该目录的父目录也不存在 dir.mkdirs(); //使用mkdirs则会把不存在的目录都创建好 } byte data[] = { 88, 89 }; FileOutputStream fos = new FileOutputStream(f); fos.write(data); fos.close(); } catch (IOException e) { e.printStackTrace(); } } }
步骤 6 :

练习-拆分文件

edit  姿势不对,事倍功半! 点击查看做练习的正确姿势
找到一个大于100k的文件,按照100k为单位,拆分成多个子文件,并且以编号作为文件名结束。
比如文件 eclipse.exe,大小是309k。
拆分之后,成为
eclipse.exe-0
eclipse.exe-1
eclipse.exe-2
eclipse.exe-3
练习-拆分文件
步骤 7 :

答案-拆分文件

edit
在查看答案前,尽量先自己完成,碰到问题再来查看答案,收获会更多
在查看答案前,尽量先自己完成,碰到问题再来查看答案,收获会更多
在查看答案前,尽量先自己完成,碰到问题再来查看答案,收获会更多
查看本答案会花费5个积分,您目前总共有点积分。查看相同答案不会花费额外积分。 积分增加办法 或者一次性购买JAVA 中级总计0个答案 (总共需要0积分)
查看本答案会花费5个积分,您目前总共有点积分。查看相同答案不会花费额外积分。 积分增加办法 或者一次性购买JAVA 中级总计0个答案 (总共需要0积分)
账号未激活 账号未激活,功能受限。 请点击激活
本视频是解读性视频,所以希望您已经看过了本答案的内容,带着疑问来观看,这样收获才多。 不建议一开始就观看视频

6分47秒 本视频采用html5方式播放,如无法正常播放,请将浏览器升级至最新版本,推荐火狐,chrome,360浏览器。 如果装有迅雷,播放视频呈现直接下载状态,请调整 迅雷系统设置-基本设置-启动-监视全部浏览器 (去掉这个选项)。 chrome 的 视频下载插件会影响播放,如 IDM 等,请关闭或者切换其他浏览器


拆分的思路,先把源文件的所有内容读取到内存中,然后从内存中挨个分到子文件里

提示,这里用到了数组复制Arrays.copyOfRange
package stream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.Arrays; public class TestStream { public static void main(String[] args) { int eachSize = 100 * 1024; // 100k File srcFile = new File("d:/eclipse.exe"); splitFile(srcFile, eachSize); } /** * 拆分的思路,先把源文件的所有内容读取到内存中,然后从内存中挨个分到子文件里 * @param srcFile 要拆分的源文件 * @param eachSize 按照这个大小,拆分 */ private static void splitFile(File srcFile, int eachSize) { if (0 == srcFile.length()) throw new RuntimeException("文件长度为0,不可拆分"); byte[] fileContent = new byte[(int) srcFile.length()]; // 先把文件读取到数组中 try { FileInputStream fis = new FileInputStream(srcFile); fis.read(fileContent); fis.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } // 计算需要被划分成多少份子文件 int fileNumber; // 文件是否能被整除得到的子文件个数是不一样的 // (假设文件长度是25,每份的大小是5,那么就应该是5个) // (假设文件长度是26,每份的大小是5,那么就应该是6个) if (0 == fileContent.length % eachSize) fileNumber = (int) (fileContent.length / eachSize); else fileNumber = (int) (fileContent.length / eachSize) + 1; for (int i = 0; i < fileNumber; i++) { String eachFileName = srcFile.getName() + "-" + i; File eachFile = new File(srcFile.getParent(), eachFileName); byte[] eachContent; // 从源文件的内容里,复制部分数据到子文件 // 除开最后一个文件,其他文件大小都是100k // 最后一个文件的大小是剩余的 if (i != fileNumber - 1) // 不是最后一个 eachContent = Arrays.copyOfRange(fileContent, eachSize * i, eachSize * (i + 1)); else // 最后一个 eachContent = Arrays.copyOfRange(fileContent, eachSize * i, fileContent.length); try { // 写出去 FileOutputStream fos = new FileOutputStream(eachFile); fos.write(eachContent); // 记得关闭 fos.close(); System.out.printf("输出子文件%s,其大小是 %d字节%n", eachFile.getAbsoluteFile(), eachFile.length()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
步骤 8 :

练习-合并文件

edit  姿势不对,事倍功半! 点击查看做练习的正确姿势
把上述拆分出来的文件,合并成一个原文件。

以是否能正常运行,验证合并是否正确
步骤 9 :

答案-合并文件

edit
在查看答案前,尽量先自己完成,碰到问题再来查看答案,收获会更多
在查看答案前,尽量先自己完成,碰到问题再来查看答案,收获会更多
在查看答案前,尽量先自己完成,碰到问题再来查看答案,收获会更多
查看本答案会花费5个积分,您目前总共有点积分。查看相同答案不会花费额外积分。 积分增加办法 或者一次性购买JAVA 中级总计0个答案 (总共需要0积分)
查看本答案会花费5个积分,您目前总共有点积分。查看相同答案不会花费额外积分。 积分增加办法 或者一次性购买JAVA 中级总计0个答案 (总共需要0积分)
账号未激活 账号未激活,功能受限。 请点击激活
本视频是解读性视频,所以希望您已经看过了本答案的内容,带着疑问来观看,这样收获才多。 不建议一开始就观看视频

4分13秒 本视频采用html5方式播放,如无法正常播放,请将浏览器升级至最新版本,推荐火狐,chrome,360浏览器。 如果装有迅雷,播放视频呈现直接下载状态,请调整 迅雷系统设置-基本设置-启动-监视全部浏览器 (去掉这个选项)。 chrome 的 视频下载插件会影响播放,如 IDM 等,请关闭或者切换其他浏览器


与拆分文件不同(先把所有数据读取到内存中),合并文件采用另一种思路。

这种思路,不需要把所有的子文件都先读取到内存中,而是一边读取子文件的内容,一边写出到目标文件

即从eclipse.exe-0开始,读取到一个文件,就开始写出到 eclipse.exe中,然后处理eclipse.exe-1eclipse.exe-2 eclipse.exe-3 ... 直到没有文件可以读
package stream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import javax.security.auth.DestroyFailedException; public class TestStream { public static void main(String[] args) { murgeFile("d:/", "eclipse.exe"); } /** * 合并的思路,就是从eclipse.exe-0开始,读取到一个文件,就开始写出到 eclipse.exe中,直到没有文件可以读 * @param folder * 需要合并的文件所处于的目录 * @param fileName * 需要合并的文件的名称 * @throws FileNotFoundException */ private static void murgeFile(String folder, String fileName) { try { // 合并的目标文件 File destFile = new File(folder, fileName); FileOutputStream fos = new FileOutputStream(destFile); int index = 0; while (true) { //子文件 File eachFile = new File(folder, fileName + "-" + index++); //如果子文件不存在了就结束 if (!eachFile.exists()) break; //读取子文件的内容 FileInputStream fis = new FileInputStream(eachFile); byte[] eachContent = new byte[(int) eachFile.length()]; fis.read(eachContent); fis.close(); //把子文件的内容写出去 fos.write(eachContent); fos.flush(); System.out.printf("把子文件 %s写出到目标文件中%n",eachFile); } fos.close(); System.out.printf("最后目标文件的大小:%,d字节" , destFile.length()); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }


HOW2J公众号,关注后实时获知最新的教程和优惠活动,谢谢。


问答区域    
2024-09-11 文件拆分和合并答案 欢迎指正
Zzz112138




源文件存在: D:\software\nonLoaded\eclipse\eclipse.exe, 其大小为: 326,640字节 输出子文件: D:\software\nonLoaded\eclipse\eclipse.exe-0.dat, 其大小为: 102,400字节 输出子文件: D:\software\nonLoaded\eclipse\eclipse.exe-1.dat, 其大小为: 102,400字节 输出子文件: D:\software\nonLoaded\eclipse\eclipse.exe-2.dat, 其大小为: 102,400字节 输出子文件: D:\software\nonLoaded\eclipse\eclipse.exe-3.dat, 其大小为: 19,440字节 合并子文件输出: D:\software\nonLoaded\eclipse\eclipse-source.exe, 其大小为: 326,640字节
package HelloJava;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Locale;

public class splitOrMergeFile {
	protected String path;
	protected int maxLength;

	public splitOrMergeFile(String path, int maxLength) {
		this.path = path;
		this.maxLength = maxLength;
		File f = new File(path);
		if (f.exists())
			System.out.format(Locale.CHINA, "源文件存在: %s, 其大小为: %,d字节%n", f.toString(), f.length());
		else
			System.out.format("源文件不存在: %s%n", f.toString());
	}

	public void splitFile() throws IOException {
		File f = new File(this.path);
		FileInputStream fis = new FileInputStream(f);
		long fileLength = f.length();
		long totalChunks = (fileLength + this.maxLength - 1) / this.maxLength;
		byte[] buffer = new byte[this.maxLength];

		for (int i = 0; i < totalChunks; i++) {
			int readLength = (int) Math.min(this.maxLength, fileLength - i * this.maxLength);
			int bytesRead = fis.read(buffer, 0, readLength);

			if (bytesRead == -1) {
				break;
			}
			this.outputSubfile(buffer, bytesRead, i);
		}
		fis.close();
	}

	public void mergeFile() throws IOException {
		long maxIndex = this.getSplitNumber();
		long lengthByte = this.getSplitLength(maxIndex);
		long length = 0;
		byte[] buffer = new byte[(int) lengthByte];

		String[] fileName = new String[2];
		File fileNameObject = new File(this.path);
		String nameExtension = "";
		int lastPoint = this.path.lastIndexOf('.');

		if (fileNameObject.toString().contains(".")) {
			nameExtension = this.path.substring(lastPoint);
			fileName[0] = this.path.substring(0, lastPoint);
			fileName[1] = nameExtension;
		} else {
			fileName[0] = this.path;
			fileName[1] = "";
		}

		for (long i = 0; i < maxIndex; i++) {
			File f = new File(this.path + "-" + i + ".dat");
			FileInputStream fis = new FileInputStream(f);
			fis.read(buffer, (int) length, (int) f.length());
			length += f.length();
			fis.close();
		}
		if (maxIndex > 0) {
			File f = new File(fileName[0] + "-source" + fileName[1]);
			FileOutputStream fos = new FileOutputStream(f);
			fos.write(buffer, 0, (int) lengthByte);
			fos.close();
			System.out.format(Locale.CHINA, "合并子文件输出: %s, 其大小为: %,d字节%n", f.toString(), f.length());
		} else {
			System.out.format("子文件不存在: %s-0.dat%n", this.path);
		}
	}

	protected void outputSubfile(byte[] buffer, int bytesRead, int index) throws IOException {
		File f = new File(this.path + "-" + index + ".dat");
		FileOutputStream fos = new FileOutputStream(f);
		fos.write(buffer, 0, bytesRead);
		fos.close();
		System.out.format(Locale.CHINA, "输出子文件: %s, 其大小为: %,d字节%n", f.toString(), f.length());
	}

	protected long getSplitNumber() {
		for (long i = 0; i < Long.MAX_VALUE; i++) {
			File f = new File(this.path + "-" + i + ".dat");
			if (!f.exists())
				return i;
		}
		return 0;
	}

	protected long getSplitLength(long maxIndex) {
		long lengthByte = 0;
		for (long i = 0; i < maxIndex; i++) {
			File f = new File(this.path + "-" + i + ".dat");
			lengthByte += f.length();
		}
		return lengthByte;
	}

	public static void main(String[] args) {
		splitOrMergeFile f = new splitOrMergeFile("D:\\software\\nonLoaded\\eclipse\\eclipse.exe", 1024 * 100);
		try {
			f.splitFile();
			f.mergeFile();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

							





回答已经提交成功,正在审核。 请于 我的回答 处查看回答记录,谢谢
答案 或者 代码至少填写一项, 如果是自己有问题,请重新提问,否则站长有可能看不到





2024-07-06 结果检测通过的文件拆分、合并方法
虚心求学




1.将原始文件拆分为若干子文件 2.将上述若干子文件合并为单个文件 3.检测原始文件经过上述两个过程后,是否有损失或者错误。 结果表明,经过编写的程序拆分、合并后,数据无损,且与原始数据完全一致。
加载中
package myFileTest;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

import j2se.HelloWorld;
public class TestFile {

	public static void main(String[]args) throws IOException
	{
		File fold = new File("D:/testFolder/");			//测试路径
		File f = new File(fold,"/testFile.txt");		//测试文件
		fold.mkdirs();									//如果测试路径不存在,则新建一个
		FileOutputStream fos = new FileOutputStream(f);
		
		byte[]bs = getRandomStr(300*1000+3).getBytes(); //生成指定长度的字符串并转为数组
		fos.write(bs);									//写入内容
		fos.close();
		File parentFile = SplitFile(f,100*1000);		//将写入内容完毕的文件,拆分成若干个子文件
		File combineFile = CombineFile(parentFile);		//将拆分完毕的子文件,合并为一个文件
		if(FileEquals(f,combineFile))					//检查拆分、合并后的结果与原始文件是否相等
		{
			System.out.println("结果检查通过!原始文件经过拆分并合并后的结果,与原始文件完全一致;成功无损地完成文件拆分、合并过程。");
		}
		else
			System.out.println("结果检查失败!原始文件进行文件拆分、合并过程失败或过程有损失。");
	}
	//指定拆分长度,将file拆分为若干子文件(file-1、file-2...),拆分成功返回拆分文件存放的文件夹parentFile文件,失败返回null。
	public static File SplitFile(File file,int splitLength) throws IOException
	{
		if(file == null)return null;
		if(!file.exists())return null;
		int num = (int) Math.ceil((double)file.length()/splitLength);
		FileInputStream fis = new FileInputStream(file);
		File parentFile = new File(String.format("%s/newSplitFolder", file.getParent()));
		byte[]bs = new byte[(int)file.length()];
		fis.read(bs);
		for (int i = 0; i < num; i++) {
			byte[]tempArr;
			if(i<num-1)
			{
				tempArr = Arrays.copyOfRange(bs, i*splitLength, i*splitLength+splitLength);
			}
			else //拆分到最后一个文件
				tempArr = Arrays.copyOfRange(bs, i*splitLength, i*splitLength+(int)file.length()-((i-1)*splitLength+splitLength));
			parentFile.mkdirs();
			File f = new File(parentFile,String.format("/%s-%d.txt",(file.getName().split("\\."))[0],i+1));//split匹配正则表达式,'.'表示任意字符,需要转义
			FileOutputStream fos = new FileOutputStream(f);
			fos.write(tempArr);
			fos.close();
			System.out.println(String.format("拆分成功!第%d个子文件为:%s,大小为  %s %s字节", i+1,f.getAbsoluteFile(),String.valueOf(f.length()>=1000?(double)f.length()/1000:f.length()),f.length()>=1000?"千":""));
		}
		return parentFile;
	}
	//根据提供的文件夹,获取该文件夹下的所有子文件,将所有子文件合并为一个新的文件并返回,失败返回null;返回的合并结果路径位于提供的文件夹内。
	public static File CombineFile(File parentFileFolder) throws IOException
	{
		if(parentFileFolder==null)return null;
		File[]fs = parentFileFolder.listFiles();
		if(fs==null)return null;
		if(fs.length<1)return null;
		int total = 0;
		for (File f : fs) {
			total+=f.length();
		}
		byte[]bs = new byte[total];
		int index = 0;
		for (File f : fs) {
			if(f==null)continue;
			if(!f.exists())continue;
			byte[]datas = new byte[(int)f.length()];
			FileInputStream fis = new FileInputStream(f);
			fis.read(datas);
			System.arraycopy(datas, 0, bs, index, (int)f.length());
			index += f.length();
			fis.close();
		}
		File resFile = new File(String.format("%s/%s.%s",fs[0].getParent(),"combineFile",fs[0].getName().split("\\.")[1])); 
		FileOutputStream fos = new FileOutputStream(resFile);
		fos.write(bs);
		fos.close();
		
		System.out.println(String.format("%n子文件合并成功!合并结果文件:path:%s%nspace:%s %s字节", resFile.getAbsoluteFile(),
				String.valueOf(resFile.length()>=1000?(double)resFile.length()/1000:resFile.length())
				,resFile.length()>=1000?"千":""));
		return resFile;
	}
	//判断两个文件的内容、大小是否完全一致
	public static boolean FileEquals(File f1,File f2) throws IOException
	{
		if(f1==null||f2==null)return false;
		if(!f1.exists()||!f2.exists())return false;
		if(f1.length()!=f2.length())return false;
		FileInputStream fis = new FileInputStream(f1);
		byte[]bs1 = new byte[(int)f1.length()];
		byte[]bs2 = new byte[(int)f2.length()];
		fis.read(bs1);
		fis.close();
		fis = new FileInputStream(f2);
		fis.read(bs2);
		fis.close();
		return Arrays.equals(bs1, bs2);
	}
	///生成指定长度的随机字符串
	public static String getRandomStr(int length)
	{
		char[] cs = new char[length];
		for (int i = 0; i < cs.length; i++) {
			int rcase = (int)(Math.random()*10);//用于随机判断大小写
			if(rcase>=5)//各占一半的概率
			{
	
				cs[i] = (char)('A'+Math.random()*25);//Z与A相差25
			}
			else 
			{
				cs[i] = (char)('a'+Math.random()*25);//Z与a相差25
			}
				
		}
		return new String(cs);
	}
}

							





回答已经提交成功,正在审核。 请于 我的回答 处查看回答记录,谢谢
答案 或者 代码至少填写一项, 如果是自己有问题,请重新提问,否则站长有可能看不到





2024-03-28 解法之一吧
2023-06-15 文件拆分和合并的答案
2022-09-08 文件拆分和合并参考


提问太多,页面渲染太慢,为了加快渲染速度,本页最多只显示几条提问。还有 166 条以前的提问,请 点击查看

提问之前请登陆
提问已经提交成功,正在审核。 请于 我的提问 处查看提问记录,谢谢
关于 JAVA 中级-I/O-字节流 的提问

尽量提供截图代码异常信息,有助于分析和解决问题。 也可进本站QQ群交流: 578362961
提问尽量提供完整的代码,环境描述,越是有利于问题的重现,您的问题越能更快得到解答。
对教程中代码有疑问,请提供是哪个步骤,哪一行有疑问,这样便于快速定位问题,提高问题得到解答的速度
在已经存在的几千个提问里,有相当大的比例,是因为使用了和站长不同版本的开发环境导致的,比如 jdk, eclpise, idea, mysql,tomcat 等等软件的版本不一致。
请使用和站长一样的版本,可以节约自己大量的学习时间。 站长把教学中用的软件版本整理了,都统一放在了这里, 方便大家下载: https://how2j.cn/k/helloworld/helloworld-version/1718.html

上传截图