⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 encryptfile.java

📁 使用流类隐藏数据(使用流类将我们的数据隐藏到BMP图形文件中
💻 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 + -