博主18年的互联网软件开发经验,从一名程序员小白逐步成为了一名架构师,我想通过平台将经验分享给大家,因此博主每天会在各个大牛网站点赞量超高的博客等寻找该技术栈的资料结合自己的经验,晚上进行用心精简、整理、总结、定稿,每天都会整理到12点,为了就是能让大家能够真正了解该技术栈的真正原理,最终从程序员成为一名真正的架构师,写的不一定是全站做好的,但是是全站最用心的~。
以后我会推出一些列的文章,每天都会更新,每天进步一点点,发布顺序【java的api基础、应用、实战】->【java开源技术栈及源码分析】->【java开源技术栈整合】->【java低代码开发平台的建设】
关注【架构师成长之道】 输入“java基础课程”,即可免费获得全套架构师全套课程
1.69 StreamCorruptedException
基本概念
StreamCorruptedException
表示在尝试读取或写入对象时,输入或输出流的格式不正确。通常,这种异常在对象序列化或反序列化期间出现,可能是因为流中的数据已被篡改或损坏。以下是 StreamCorruptedException
的属性、构造方法、方法和一个简单的例子:
属性:
-
无
构造方法:
-
StreamCorruptedException()
:创建一个新的StreamCorruptedException
实例,其中不包含详细信息。 -
StreamCorruptedException(String reason)
:使用指定的详细消息创建一个新的StreamCorruptedException
实例。
方法:
-
无
简单的例子:
javaCopy code import java.io.*; public class StreamCorruptedExceptionExample { public static void main(String[] args) { try { // 模拟数据被篡改的情况 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); objectOutputStream.writeObject(new Person("Alice", 30)); byte[] data = byteArrayOutputStream.toByteArray(); // 修改流中的数据 data[10] = (byte) (data[10] + 1); // 尝试从篡改后的流中读取对象 ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(data); ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream); Object obj = objectInputStream.readObject(); System.out.println("成功从篡改的流中读取对象:" + obj); } catch (IOException | ClassNotFoundException e) { System.out.println("读取对象时发生 StreamCorruptedException: " + e.getMessage()); } } } class Person implements Serializable { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Person{name='" + name + "', age=" + age + '}'; } }
在这个例子中,我们首先将一个 Person
对象写入到输出流中,然后模拟了流中的数据被篡改的情况。接着,我们尝试从篡改后的流中读取对象,这时会抛出 StreamCorruptedException
异常。
应用场景
StreamCorruptedException
主要用于指示在尝试读取或写入对象时,输入或输出流的格式不正确。以下是一些可能的应用场景及其对应的代码实现:
-
数据完整性验证: 在进行数据传输或存储时,可以通过检查数据是否已被篡改来验证数据的完整性。
javaCopy code import java.io.*; public class DataIntegrityVerification { public static void main(String[] args) { try { // 模拟数据被篡改的情况 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); objectOutputStream.writeObject(new Person("Alice", 30)); byte[] data = byteArrayOutputStream.toByteArray(); // 修改流中的数据 data[10] = (byte) (data[10] + 1); // 尝试从篡改后的流中读取对象 ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(data); ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream); Object obj = objectInputStream.readObject(); System.out.println("成功从篡改的流中读取对象:" + obj); } catch (IOException | ClassNotFoundException e) { System.out.println("读取对象时发生 StreamCorruptedException: " + e.getMessage()); } } } class Person implements Serializable { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Person{name='" + name + "', age=" + age + '}'; } }
在这个例子中,我们首先将一个 Person
对象写入到输出流中,然后模拟了流中的数据被篡改的情况。接着,我们尝试从篡改后的流中读取对象,这时会抛出 StreamCorruptedException
异常。
-
文件完整性验证: 在从文件中读取数据时,可以检查文件的校验和或哈希值,以验证文件的完整性。如果文件已被篡改,则可能会导致
StreamCorruptedException
异常。
javaCopy code import java.io.*; import java.security.*; public class FileIntegrityVerification { private static final String FILE_PATH = "data.dat"; public static void main(String[] args) { try { // 计算文件的哈希值 MessageDigest md = MessageDigest.getInstance("MD5"); byte[] hash = calculateHash(md, new FileInputStream(FILE_PATH)); // 修改文件内容 modifyFileContent(); // 再次计算文件的哈希值并验证 byte[] newHash = calculateHash(md, new FileInputStream(FILE_PATH)); if (MessageDigest.isEqual(hash, newHash)) { System.out.println("文件未被篡改"); } else { System.out.println("文件已被篡改"); } } catch (NoSuchAlgorithmException | IOException e) { e.printStackTrace(); } } private static byte[] calculateHash(MessageDigest md, InputStream inputStream) throws IOException { byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { md.update(buffer, 0, bytesRead); } return md.digest(); } private static void modifyFileContent() throws IOException { RandomAccessFile file = new RandomAccessFile(FILE_PATH, "rw"); file.seek(10); file.writeByte(file.readByte() + 1); // 修改文件内容 file.close(); System.out.println("文件内容已修改"); } }
在这个例子中,我们首先计算了文件的哈希值,然后模拟了文件内容被篡改的情况,并再次计算了文件的哈希值。如果文件内容被篡改,则可能会导致 StreamCorruptedException
异常。
实战例子
下面是一个项目实战示例,演示了如何使用 StreamCorruptedException
来处理数据完整性验证的情况。
假设你正在开发一个简单的文件传输应用程序,该应用程序负责从服务器下载文件并验证文件的完整性。在下载文件时,如果文件的哈希值与服务器端提供的哈希值不匹配,就会抛出 StreamCorruptedException
异常,表示文件可能已被篡改。
javaCopy code import java.io.*; import java.net.*; import java.security.*; import java.util.*; public class FileDownloader { private static final String SERVER_HOST = "example.com"; private static final int SERVER_PORT = 12345; private static final String FILE_PATH = "/path/to/file.txt"; public static void main(String[] args) { try { // 下载文件并验证完整性 byte[] fileData = downloadFile(); if (verifyIntegrity(fileData)) { System.out.println("文件下载成功且完整性验证通过"); } else { System.out.println("文件下载成功,但完整性验证失败"); } } catch (IOException | NoSuchAlgorithmException e) { System.out.println("文件下载失败:" + e.getMessage()); } } private static byte[] downloadFile() throws IOException { Socket socket = new Socket(SERVER_HOST, SERVER_PORT); OutputStream outputStream = socket.getOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream); objectOutputStream.writeUTF(FILE_PATH); objectOutputStream.flush(); InputStream inputStream = socket.getInputStream(); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { byteArrayOutputStream.write(buffer, 0, bytesRead); } socket.close(); return byteArrayOutputStream.toByteArray(); } private static boolean verifyIntegrity(byte[] fileData) throws NoSuchAlgorithmException { // 从服务器获取文件的哈希值(假设服务器提供了文件的哈希值) String expectedHash = "54b0c58c7ce9f2a8b551351102ee0938"; // 计算文件的哈希值 MessageDigest md = MessageDigest.getInstance("MD5"); byte[] actualHash = md.digest(fileData); // 将字节数组转换为十六进制字符串 StringBuilder actualHashStr = new StringBuilder(); for (byte b : actualHash) { actualHashStr.append(String.format("%02x", b)); } // 比较文件的哈希值与期望的哈希值 return actualHashStr.toString().equals(expectedHash); } }
在这个示例中,FileDownloader
类负责从服务器下载文件并验证文件的完整性。它通过建立与服务器的套接字连接,并发送文件路径来下载文件。下载完成后,它计算文件的哈希值并与服务器端提供的哈希值进行比较,以验证文件的完整性。如果哈希值匹配,则表示文件下载成功且完整性验证通过。如果哈希值不匹配,则可能会抛出 StreamCorruptedException
异常,表示文件可能已被篡改。