Java Strong在更改一位时更改WAV文件。隐写术
encode_text()函数实现了LSB编码方法。首先记录消息长度,然后记录消息本身 numberOfBits分配用于写入消息的位数。写入一个字节的一位或两位或三位 这种编码方法使用一个位作为记录,声音的变化不应该被耳朵注意到。以及对眼睛图像的改变。但事实并非如此。由于某些原因,声音的开头会更改为“噪波”。这不应该 read()和save()确定,如果读取数据文件并将其刻录,则不会发生任何更改 问题是encode_text()函数有什么问题。或者我做错了什么Java Strong在更改一位时更改WAV文件。隐写术,java,wav,steganography,Java,Wav,Steganography,encode_text()函数实现了LSB编码方法。首先记录消息长度,然后记录消息本身 numberOfBits分配用于写入消息的位数。写入一个字节的一位或两位或三位 这种编码方法使用一个位作为记录,声音的变化不应该被耳朵注意到。以及对眼睛图像的改变。但事实并非如此。由于某些原因,声音的开头会更改为“噪波”。这不应该 read()和save()确定,如果读取数据文件并将其刻录,则不会发生任何更改 问题是encode_text()函数有什么问题。或者我做错了什么 import java.io.*;
import java.io.*;
import java.util.Arrays;
public class wavIO
{
private String myPath;
private long myChunkSize;
private long mySubChunk1Size;
private int myFormat;
private long myChannels;
private long mySampleRate;
private long myByteRate;
private int myBlockAlign;
private int myBitsPerSample;
private long myDataSize;
public byte[] myData;
public String getPath()
{
return myPath;
}
public void setPath(String newPath)
{
myPath = newPath;
}
public wavIO()
{
myPath = "";
}
public wavIO(String tmpPath)
{
myPath = tmpPath;
}
// read a wav file into this class
public boolean read()
{
DataInputStream inFile = null;
myData = null;
byte[] tmpLong = new byte[4];
byte[] tmpInt = new byte[2];
try
{
inFile = new DataInputStream(new FileInputStream(myPath));
//System.out.println("Reading wav file...\n"); // for debugging only
String chunkID = "" + (char)inFile.readByte() + (char)inFile.readByte() + (char)inFile.readByte() + (char)inFile.readByte();
inFile.read(tmpLong); // read the ChunkSize
myChunkSize = byteArrayToLong(tmpLong);
String format = "" + (char)inFile.readByte() + (char)inFile.readByte() + (char)inFile.readByte() + (char)inFile.readByte();
// print what we've read so far
//System.out.println("chunkID:" + chunkID + " chunk1Size:" + myChunkSize + " format:" + format); // for debugging only
String subChunk1ID = "" + (char)inFile.readByte() + (char)inFile.readByte() + (char)inFile.readByte() + (char)inFile.readByte();
inFile.read(tmpLong); // read the SubChunk1Size
mySubChunk1Size = byteArrayToLong(tmpLong);
inFile.read(tmpInt); // read the audio format. This should be 1 for PCM
myFormat = byteArrayToInt(tmpInt);
inFile.read(tmpInt); // read the # of channels (1 or 2)
myChannels = byteArrayToInt(tmpInt);
inFile.read(tmpLong); // read the samplerate
mySampleRate = byteArrayToLong(tmpLong);
inFile.read(tmpLong); // read the byterate
myByteRate = byteArrayToLong(tmpLong);
inFile.read(tmpInt); // read the blockalign
myBlockAlign = byteArrayToInt(tmpInt);
inFile.read(tmpInt); // read the bitspersample
myBitsPerSample = byteArrayToInt(tmpInt);
// print what we've read so far
//System.out.println("SubChunk1ID:" + subChunk1ID + " SubChunk1Size:" + mySubChunk1Size + " AudioFormat:" + myFormat + " Channels:" + myChannels + " SampleRate:" + mySampleRate);
// read the data chunk header - reading this IS necessary, because not all wav files will have the data chunk here - for now, we're just assuming that the data chunk is here
String dataChunkID = "" + (char)inFile.readByte() + (char)inFile.readByte() + (char)inFile.readByte() + (char)inFile.readByte();
inFile.read(tmpLong); // read the size of the data
myDataSize = byteArrayToLong(tmpLong);
// read the data chunk
myData = new byte[(int)myDataSize];
inFile.read(myData);
// close the input stream
inFile.close();
}
catch(Exception e)
{
return false;
}
return true; // this should probably be something more descriptive
}
// write out the wav file
public boolean save(String outputPath)
{
try
{
//DataOutputStream outFile = new DataOutputStream(new FileOutputStream(myPath));
DataOutputStream outFile = new DataOutputStream(new FileOutputStream(outputPath));
// write the wav file per the wav file format
outFile.writeBytes("RIFF"); // 00 - RIFF
outFile.write(intToByteArray((int)myChunkSize), 0, 4); // 04 - how big is the rest of this file?
outFile.writeBytes("WAVE"); // 08 - WAVE
outFile.writeBytes("fmt "); // 12 - fmt
outFile.write(intToByteArray((int)mySubChunk1Size), 0, 4); // 16 - size of this chunk
outFile.write(shortToByteArray((short)myFormat), 0, 2); // 20 - what is the audio format? 1 for PCM = Pulse Code Modulation
outFile.write(shortToByteArray((short)myChannels), 0, 2); // 22 - mono or stereo? 1 or 2? (or 5 or ???)
outFile.write(intToByteArray((int)mySampleRate), 0, 4); // 24 - samples per second (numbers per second)
outFile.write(intToByteArray((int)myByteRate), 0, 4); // 28 - bytes per second
outFile.write(shortToByteArray((short)myBlockAlign), 0, 2); // 32 - # of bytes in one sample, for all channels
outFile.write(shortToByteArray((short)myBitsPerSample), 0, 2); // 34 - how many bits in a sample(number)? usually 16 or 24
outFile.writeBytes("data"); // 36 - data
outFile.write(intToByteArray((int)myDataSize), 0, 4); // 40 - how big is this data chunk
outFile.write(myData); // 44 - the actual data itself - just a long string of numbers
}
catch(Exception e)
{
System.out.println(e.getMessage());
return false;
}
return true;
}
// return a printable summary of the wav file
public String getSummary()
{
//String newline = System.getProperty("line.separator");
String newline = "<br>";
String summary = "<html>Format: " + myFormat + newline + "Channels: " + myChannels + newline + "SampleRate: " + mySampleRate + newline + "ByteRate: " + myByteRate + newline + "BlockAlign: " + myBlockAlign + newline + "BitsPerSample: " + myBitsPerSample + newline + "DataSize: " + myDataSize + "</html>";
return summary;
}
// ===========================
// CONVERT BYTES TO JAVA TYPES
// ===========================
// these two routines convert a byte array to a unsigned short
public static int byteArrayToInt(byte[] b)
{
int start = 0;
int low = b[start] & 0xff;
int high = b[start+1] & 0xff;
return (int)( high << 8 | low );
}
// these two routines convert a byte array to an unsigned integer
public static long byteArrayToLong(byte[] b)
{
int start = 0;
int i = 0;
int len = 4;
int cnt = 0;
byte[] tmp = new byte[len];
for (i = start; i < (start + len); i++)
{
tmp[cnt] = b[i];
cnt++;
}
long accum = 0;
i = 0;
for ( int shiftBy = 0; shiftBy < 32; shiftBy += 8 )
{
accum |= ( (long)( tmp[i] & 0xff ) ) << shiftBy;
i++;
}
return accum;
}
// ===========================
// CONVERT JAVA TYPES TO BYTES
// ===========================
// returns a byte array of length 4
private static byte[] intToByteArray(int i)
{
byte[] b = new byte[4];
b[0] = (byte) (i & 0x00FF);
b[1] = (byte) ((i >> 8) & 0x000000FF);
b[2] = (byte) ((i >> 16) & 0x000000FF);
b[3] = (byte) ((i >> 24) & 0x000000FF);
return b;
}
// convert a short to a byte array
public static byte[] shortToByteArray(short data)
{
return new byte[]{(byte)(data & 0xff),(byte)((data >>> 8) & 0xff)};
}
public void encode(String text, int numberOfBits)
{
byte[] byteMessage = text.getBytes();
byte[] messageLength = bit_conversion(byteMessage.length);
encodeText(messageLength, myData, 0, numberOfBits);
encodeText(byteMessage, myData, 32, numberOfBits);
}
private void encodeText(byte[] addition, byte[] byteDataInputWav, int offset, int numberOfBits)
{
if(addition.length + offset > byteDataInputWav.length)
{
System.out.println("File not long enough!");
}
else
{
for(int i=0; i<addition.length; ++i)
{
int add = addition[i];
for(int bit=7; bit>=0; --bit, ++offset)
{
int b = (add >>> bit) & 1;
byteDataInputWav[offset] = (byte)((byteDataInputWav[offset] & numberOfBits) | b );
}
}
}
}
private byte[] bit_conversion(int i)
{
byte byte3 = (byte)((i & 0xFF000000) >>> 24);
byte byte2 = (byte)((i & 0x00FF0000) >>> 16);
byte byte1 = (byte)((i & 0x0000FF00) >>> 8 );
byte byte0 = (byte)((i & 0x000000FF) );
return(new byte[]{byte3,byte2,byte1,byte0});
}
public String decode(String inputPath)
{
byte[] byteDataOutputWav = myData;
int length = 0;
int offset2 = 32;
for(int i=0; i<32; ++i)
{
length = (length << 1) | (byteDataOutputWav[i] & 1);
}
byte[] result = new byte[length];
for(int b=0; b<result.length; ++b )
{
for(int i=0; i<8; ++i, ++offset2)
{
result[b] = (byte)((result[b] << 1) | (byteDataOutputWav[offset2] & 1));
}
}
return new String(result);
}
}
import java.io.*;
导入java.util.array;
公共类wavIO
{
私有字符串myPath;
私人长码;
私有长mySubChunk1Size;
私有int-myFormat;
私人长频道;
私家长住;
私人长粘虫;
私有int-myBlockAlign;
私有int myBitsPerSample;
私有长myDataSize;
公共字节[]myData;
公共字符串getPath()
{
返回myPath;
}
公共void setPath(字符串newPath)
{
myPath=newPath;
}
公共wavIO()
{
myPath=“”;
}
公共wavIO(字符串tmpPath)
{
myPath=tmpPath;
}
//将wav文件读入此类
公共布尔读取()
{
DataInputStream infle=null;
myData=null;
字节[]tmpLong=新字节[4];
字节[]tmpInt=新字节[2];
尝试
{
infle=newdatainputstream(newfileinputstream(myPath));
//System.out.println(“读取wav文件…\n”);//仅用于调试
字符串chunkID=“+(char)infle.readByte()+(char)infle.readByte()+(char)infle.readByte()+(char)infle.readByte();
infle.read(tmpLong);//读取ChunkSize
myChunkSize=byteArrayToLong(tmpLong);
字符串格式=“+(char)infle.readByte()+(char)infle.readByte()+(char)infle.readByte()+(char)infle.readByte();
//打印我们到目前为止读到的内容
//System.out.println(“chunkID:+chunkID+”chunk1Size:+myChunkSize+”格式:“+格式);//仅用于调试
字符串subChunk1ID=“+(char)infle.readByte()+(char)infle.readByte()+(char)infle.readByte()+(char)infle.readByte();
infle.read(tmpLong);//读取子缓存大小
mySubChunk1Size=byteArrayToLong(tmpLong);
infle.read(tmpInt);//读取音频格式。这对于PCM应该是1
myFormat=ByteArrayPoint(tmpInt);
infle.read(tmpInt);//读取通道(1或2)的#
myChannels=byteArrayToInt(tmpInt);
infle.read(tmpLong);//读取采样器
mySampleRate=byteArrayToLong(tmpLong);
infle.read(tmpLong);//读字节
粘虫=byteArrayToLong(tmpLong);
infle.read(tmpInt);//读取块对齐
myBlockAlign=byteArrayToInt(tmpInt);
infle.read(tmpInt);//读取位示例
myBitsPerSample=ByteArrayPoint(tmpInt);
//打印我们到目前为止读到的内容
//System.out.println(“SubChunk1ID:+SubChunk1ID+”SubChunk1Size:+mySubChunk1Size+”音频格式:“+myFormat+”频道:“+myChannels+”采样器:“+mySampleRate”);
//读取数据块头-读取数据块头是必要的,因为并非所有wav文件都在这里有数据块-现在,我们只是假设数据块在这里
字符串dataChunkID=“+(char)infle.readByte()+(char)infle.readByte()+(char)infle.readByte()+(char)infle.readByte();
infle.read(tmpLong);//读取数据的大小
myDataSize=byteArrayToLong(tmpLong);
//读取数据块
myData=新字节[(int)myDataSize];
填充读取(myData);
//关闭输入流
infle.close();
}
捕获(例外e)
{
返回false;
}
return true;//这应该是更具描述性的内容
}
//写出wav文件
公共布尔保存(字符串输出路径)
{
尝试
{
//DataOutputStream outFile=新的DataOutputStream(新的FileOutputStream(myPath));
DataOutputStream outFile=新DataOutputStream(新文件OutputStream(outputPath));
//按照wav文件格式写入wav文件
outFile.writeBytes(“RIFF”);//00-RIFF
write(intToByteArray((int)myChunkSize),0,4);//04-此文件的其余部分有多大?
outFile.writeBytes(“WAVE”);//08-WAVE
outFile.writeBytes(“fmt”);//12-fmt
write(intToByteArray((int)mySubChunk1Size),0,4);//16-此块的大小
write(shortToByteArray((short)myFormat),0,2);//20-音频格式是什么?1表示PCM=脉冲编码调制
outFile.write(shortToByteArray((短)MyChannel),0,2);//22-单声道或立体声?1或2?(或5或??)
write(intToByteArray((int)mySampleRate),0,4);//24-每秒采样数(每秒数)
write(intToByteArray((int)myByteRate),0,4);//每秒28字节
write(shortToByteArray((short)myBlockAlign),0,2);//32-#字节在一个样本中,用于所有通道
write(shortToByteArray((short)myBitsPerSample),0,2);//34-一个样本(数字)中有多少位?通常是16或24位
outFile.writeBytes(“数据”);//36-data
write(intToByteArray((int)myDataSize),0,4);//40-这个数据块有多大
outFile.write(myData);//44—实际数据本身—只是一长串数字
}
捕获(例外e)
{
System.out.println(e.getMessage());
返回false;
}
返回真值