📄 encryptfile.java
字号:
/**
* 使用流类隐藏数据
* 整体思路:我们需要将一些数据隐藏起来的时候,可以利用bmp图形文件,bmp图形文件有其图形文件的长度,存放在bmp文件的
* 头结构中,bmp文件的头结构位于bmp文件的起始部分,前两个字节是图形文件的类型,后续的字节描述了图形文件的
* 大小。
* 我们可以利用这个特性,在写入隐藏内容时,将内容附着在图形文件的尾部,此时不影响图形文件的正常的显示(因为
* 头结构中描述了图形文件的大小),在读取我们附着在尾部的数据时,只要跳过图形文件的大小,此时再读取得数据就
* 是我们的真实的数据了,这样,即使是别人看到这个文件,打开后只是普通的图形文件,我们隐藏私有信息的目的就达
* 到了。
* 这种技术在前一段时间是很流行的一种,甚至专门出了破解的软件,在此例中只演示了存入字符数据,如果存入的是字
* 节数据,请自行更改,应该使用字节流。
* */
package ioconcealdata_a;
import java.io.*;
public class EncryptFile
{
private BufferedReader br = null;
private PrintWriter pw = null;
private String fileName = null;
private int fileLength = 0;
//在构造函数中获得文件的长度(备用)
public EncryptFile(String fileName) throws IOException
{
this.fileName = fileName;
this.fileLength = this.getBitMapLength(fileName);
}
private int getBitMapLength(String fileName) throws IOException
{
//BMP文件的第三个字节开始描述BMP文件长度(注意低位在前,高位在后。)
//前两个字节描述文件类型是不是BMP文件
FileInputStream fin = new FileInputStream(fileName);
//跳过前两个字节
fin.skip(2);
//获取BMP图形文件的大小
//得到字节的十六进制值
String lowLow = Integer.toHexString(fin.read());
String lowHigh = Integer.toHexString(fin.read());
String highHigh = Integer.toHexString(fin.read());
String highLow = Integer.toHexString(fin.read());
if (fin != null)
{
fin.close();
}
//返回转换为十进制的数字,表示文件的长度。
return Integer.parseInt(highHigh + highLow + lowHigh + lowLow, 16);
}
//将数据写入BMP文件的尾部(在实际使用时还需要加一些算法,对数据进行加解密。)
public void setData(String str) throws IOException
{
//判断是否已经构造了PrintWriter,如是则不进行构造。
if (pw == null)
{
//注意FileOutputStream的构造中的true表示附加数据
//PrintWriter构造中的true表示自动刷新,即遇到println自动冲刷数据。
pw = new PrintWriter(new FileOutputStream(fileName, true), true);
}
pw.println(str);
}
public String getData() throws IOException
{
if (br == null)
{
br = new BufferedReader(new InputStreamReader(new FileInputStream(this.fileName)));
}
//跳过图形文件,读取隐藏的内容。
br.skip(this.fileLength - 2);
//因为字符串是不可更改的,所以使用了StringBuffer来提高效率。
StringBuffer sb = new StringBuffer();
String strTemp = "";
while ((strTemp = br.readLine()) != null)
{
sb.append(strTemp + "\r\n");
}
//返回读到的数据
return sb.toString();
}
public void close() throws IOException
{
//最后流类要关闭,强制自己养成这个习惯。
if (br != null)
{
br.close();
}
if (pw != null)
{
pw.close();
}
}
public static void main(String[] args)
{
//下面是进行使用写好的类,提供了用户的交互,这个不是问题的核心。
try
{
BufferedReader keyIn = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入BMP文件的名字:");
String fileName = keyIn.readLine();
EncryptFile eFile = new EncryptFile(fileName);
System.out.println("请输入: (1)加入数据 (2)读取数据");
String choice = keyIn.readLine();
if (choice.equals("1"))
{
System.out.println("请输入要加入的数据,以End结束!");
String data = "";
while (!(data = keyIn.readLine()).equalsIgnoreCase("end"))
{
eFile.setData(data);
}
}
if (choice.equals("2"))
{
System.out.println(eFile.getData());
}
//最后关闭了流类
eFile.close();
}
catch (Exception e)
{
System.out.println(e);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -