?? encryptfile.java~4~
字號:
/**
* 整體思路:我們需要將一些數據隱藏起來的時候,可以利用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();
}
//返回轉換為10進制的數字,表示文件的長度。
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 + -