I have to encrypt some file (jpg) using vigenere cipher. I wrote some code, but after encryption and decryption my file is corrupted. The first 1/4 of image displays okay, but the rest of it is corrupted. Here is my code:
#Override
public byte[] encryptFile(byte[] file, String key) {
char[] keyChars = key.toCharArray();
byte[] bytes = file;
for (int i = 0; i < file.length; i++) {
int keyNR = keyChars[i % keyChars.length] - 32;
int c = bytes[i] & 255;
if ((c >= 32) && (c <= 127)) {
int x = c - 32;
x = (x + keyNR) % 96;
bytes[i] = (byte) (x + 32);
}
}
return bytes;
}
#Override
public byte[] decryptFile(byte[] file, String key) {
char[] keyChars = key.toCharArray();
byte[] bytes = file;
for (int i = 0; i < file.length; i++) {
int keyNR = keyChars[i % keyChars.length] - 32;
int c = bytes[i] & 255;
if ((c >= 32) && (c <= 127)) {
int x = c - 32;
x = (x - keyNR + 96) % 96;
bytes[i] = (byte) (x + 32);
}
}
return bytes;
}
What did I do wrong?
EDIT:
reading and writing to file:
public void sendFile(String selectedFile, ICipher cipher, String key) {
try {
DataOutputStream outStream = new DataOutputStream(client
.getOutputStream());
outStream.flush();
File file = new File(selectedFile);
FileInputStream fileStream = new FileInputStream(file);
long fileSize = file.length();
long completed = 0;
long bytesLeft = fileSize - completed;
String msg = "SENDING_FILE:" + file.getName() + ":" + fileSize;
outStream.writeUTF(cipher.encryptMsg(msg, key));
while (completed < fileSize) {
int step = (int) (bytesLeft > 150000 ? 150000 : bytesLeft);
byte[] buffer = new byte[step];
fileStream.read(buffer);
buffer = cipher.encryptFile(buffer, key);
outStream.write(buffer);
completed += step;
bytesLeft = fileSize - completed;
}
outStream.writeUTF(cipher.encryptMsg("SEND_COMPLETE", key));
fileStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private void downloadFile(String fileName, int fileSize,DataInputStream input,ICipher cipher, String key) {
try {
FileOutputStream outStream = new FileOutputStream("C:\\" + fileName);
int bytesRead = 0, counter = 0;
while (counter < fileSize) {
int step = (int) (fileSize > 150000 ? 150000 : fileSize);
byte[] buffer = new byte[step];
bytesRead = input.read(buffer);
if (bytesRead >= 0) {
buffer = cipher.decryptFile(buffer, key);
outStream.write(buffer, 0, bytesRead);
counter += bytesRead;
}
if (bytesRead < 1024) {
outStream.flush();
break;
}
}
Display.getDefault().syncExec(new Runnable() {
#Override
public void run() {
window.handleMessage("Download sucessfully");
}
});
outStream.close();
} catch (Exception e) {
Display.getDefault().syncExec(new Runnable() {
#Override
public void run() {
window.handleMessage("Error on downloading file!");
}
});
}
}
You encode the file in whatever chunks come from the disk I/O:
int step = (int) (bytesLeft > 150000 ? 150000 : bytesLeft);
byte[] buffer = new byte[step];
fileStream.read(buffer);
buffer = cipher.encryptFile(buffer, key);
But you decode the file in whatever chunks come from the network I/O:
bytesRead = input.read(buffer);
if (bytesRead >= 0) {
buffer = cipher.decryptFile(buffer, key);
outStream.write(buffer, 0, bytesRead);
counter += bytesRead;
}
These chunks are likely to disagree. The disk I/O may always give you full chunks (lucky for you), but the network I/O will likely give you packet-sized chunks (1500 bytes minus header).
The cipher should get an offset into the already encoded/decoded data (or encode/decode everything at once), and use that to shift the key appropriately, or this may happen:
original: ...LOREM IPSUM...
key : ...abCde abCde...
encoded : ...MQUIR JRVYR...
key : ...abCde Cdeab... <<note the key got shifted
decoded : ...LOREM GNQXP... <<output wrong after the first chunk.
Since the packet data size is (for Ethernet-sized TCP/IP packets) aligned at four bytes, a key of length four is likely to be always aligned.
another issue is that you are ignoring the number of bytes read from disk when uploading the file. While disk I/O is likely to always give you full-sized chunks (the file's likely to be memory-mapped or the underlying native API does provide this guarantee), nothing's taken for granted. Always use the amount of bytes actually read: bytesRead = fileStream.read(buffer);
Related
Suppose I receive bytes in chunks and I want to efficiently decode them to a string (that is going to be Unicode obviously), also I want to know, as soon as I can, if that string begins with a certain sequence.
One way could be:
public boolean inputBytesMatch(InputStream inputStream, String match) throws IOException {
byte[] buff = new byte[1024];
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int len;
while ((len = inputStream.read(buff)) > 0){
byteArrayOutputStream.write(buff, 0, len);
String decoded = new String(byteArrayOutputStream.toByteArray(), Charset.defaultCharset());
if (decoded.startsWith(match)){
return true;
}
}
return false;
}
but this involves allocating a new array from the byteArrayOutputStream every time there is a new chunk and String will do another copy in the constructor. All this seems to me pretty inefficient. Also string will do a decode of the bytes in the constructor, every single time, doing it from the beginning once again.
How can I make this process faster?
Actually you don't need a ByteArrayOutputStream at all.
First turn your String match into a byte[], using your desired encoding.
Then just compare each incoming chunk with the next part of that array:
public boolean inputBytesMatch(InputStream inputStream, String match) throws IOException {
byte[] compare = match.getBytes(Charset.defaultCharset());
int n = compare.length;
int compareAt = 0;
byte[] buff = new byte[n];
int len;
while (compareAt < n && (len = inputStream.read(buff, 0, n-compareAt)) > 0) {
for (int i=0; i < len && compareAt < n; i++, compareAt++) {
if (compare[compareAt] != buff[i]) {
// found contradicting byte
return false;
}
}
}
// No byte was found which contradicts that the streamed data begins with compare.
// Did we actually read enough bytes?
return compareAt >= n;
}
You might find this version more readable:
public boolean inputBytesMatch(InputStream inputStream, String match) throws IOException {
byte[] compare = match.getBytes(Charset.defaultCharset());
int n = compare.length;
int compareAt = 0;
byte[] buff = new byte[n];
int len;
while (compareAt < n && (len = inputStream.read(buff, 0, n-compareAt)) > 0) {
if (!isSubArray(compare, compareAt, buff, len)) {
return false;
}
compareAt += len;
}
return compareAt >= n;
}
private boolean isSubArray(byte[] searchIn, int searchInOffset, byte[] searchFor, int searchForLength)
{
if (searchInOffset + searchForLength >= searchIn.length) {
// can not match
return false;
}
for (int i=0; i < searchForLength; i++) {
if (searchIn[searchInOffset+i] != searchFor[i]) {
return false;
}
}
return true;
}
I can read WAV file (8-bit per sample) in the following function and copy it to another file. I want to play with the overall volume of the source file with given scale parameter, which is in range [0, 1]. My naive approach was to multiple byte with scale and convert it to byte again. All I got a noisy file. How can I achieve this byte by byte volume adjustment?
public static final int BUFFER_SIZE = 10000;
public static final int WAV_HEADER_SIZE = 44;
public void changeVolume(File source, File destination, float scale) {
RandomAccessFile fileIn = null;
RandomAccessFile fileOut = null;
byte[] header = new byte[WAV_HEADER_SIZE];
byte[] buffer = new byte[BUFFER_SIZE];
try {
fileIn = new RandomAccessFile(source, "r");
fileOut = new RandomAccessFile(destination, "rw");
// copy the header of source to destination file
int numBytes = fileIn.read(header);
fileOut.write(header, 0, numBytes);
// read & write audio samples in blocks of size BUFFER_SIZE
int seekDistance = 0;
int bytesToRead = BUFFER_SIZE;
long totalBytesRead = 0;
while(totalBytesRead < fileIn.length()) {
if (seekDistance + BUFFER_SIZE <= fileIn.length()) {
bytesToRead = BUFFER_SIZE;
} else {
// read remaining bytes
bytesToRead = (int) (fileIn.length() - totalBytesRead);
}
fileIn.seek(seekDistance);
int numBytesRead = fileIn.read(buffer, 0, bytesToRead);
totalBytesRead += numBytesRead;
for (int i = 0; i < numBytesRead - 1; i++) {
// WHAT TO DO HERE?
buffer[i] = (byte) (scale * ((int) buffer[i]));
}
fileOut.write(buffer, 0, numBytesRead);
seekDistance += numBytesRead;
}
fileOut.setLength(fileIn.length());
} catch (FileNotFoundException e) {
System.err.println("File could not be found" + e.getMessage());
} catch (IOException e) {
System.err.println("IOException: " + e.getMessage());
} finally {
try {
fileIn.close();
fileOut.close();
} catch (IOException e) {
System.err.println("IOException: " + e.getMessage());
}
}
}
A java byte is in a range from -128 to 127, while the byte used in the wav pcm format ranges from 0 to 255. That is most likely why you are changing your pcm data to random/noisy values.
buffer[i] = (byte) (scale * (buffer[i]<0?256+(int)buffer[i]:buffer[i]));
The problem is when i send up to 40 KB everything is okay when i send more sometime half of the data received some time nothing ,is there a limit of the networkstream.Read ,even though i cunked the data ,i can't determine if the problem form the java or the c# from the network stream or the Output stream
C# SERVER
private void ReadData(){
if (networkStream.DataAvailable)
{
int size = GetBufferSize();
Thread.Sleep(340);
byte[] myReadBuffer = new byte[size];
int numberOfBytesRead = 0;
while (true)
{
numberOfBytesRead = networkStream.Read(myReadBuffer, 0, myReadBuffer.Length);
if (numberOfBytesRead >= myReadBuffer.Length)
{
break;
}
}
string str = Encoding.UTF8.GetString(myReadBuffer, 0, size);
dynamic Message = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(str);
// Android Message , JSON String
if (OnAndroidMessage != null)
{
OnAndroidMessage(Message);
}
}
}
private int GetBufferSize()
{
byte[] myReadBuffer = new byte[4];
int numberOfBytesRead = 0;
do
{
numberOfBytesRead = networkStream.Read(myReadBuffer, 0, myReadBuffer.Length);
} while (networkStream.DataAvailable && numberOfBytesRead < myReadBuffer.Length);
if (numberOfBytesRead > 0)
{
// reverse the byte array.
if (BitConverter.IsLittleEndian)
{
Array.Reverse(myReadBuffer);
}
return BitConverter.ToInt32(myReadBuffer, 0);
}
else
{
return 0;
}
}
Java Client // i tested this also without cutting the data to smaller paces ,half of the data received not all of them
mBufferOut = socket.getOutputStream();
private void sendMessage(final String message) {
if (mBufferOut != null && message != null) {
try {
byte[] data = message.getBytes("UTF-8");
Log.d("_TAG", "Sending: " + message);
Log.d("_TAG", "Message length: " + Integer.toString(data.length));
mBufferOut.write(toByteArray(data.length));
mBufferOut.flush();
List<byte[]> divideArray = divideArray(data, 10000);
for (byte[] dataChunk : divideArray) {
Log.e("_TAG","CHUNK SIZE > " + Integer.toString(dataChunk.length));
mBufferOut.write(dataChunk, 0, dataChunk.length);
mBufferOut.flush();
}
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
private List<byte[]> divideArray(byte[] source, int chunksize) {
List<byte[]> result = new ArrayList<byte[]>();
int start = 0;
while (start < source.length) {
int end = Math.min(source.length, start + chunksize);
result.add(Arrays.copyOfRange(source, start, end));
start += chunksize;
}
return result;
}
Any ideas ?
Solution from this post NetworkStream is reading data that should not be there
static void ReadExact(Stream stream, byte[] buffer, int offset, int count)
{
int read;
while(count > 0 && (read = stream.Read(buffer, offset, count)) > 0) {
offset += read;
count -= read;
}
if(count != 0) throw new EndOfStreamException();
}
the problem is the Read it takes size and want to get that size you need to give it chunks and check each chunk
And also read does not restart from where it stopped until it reads the amount is set to read meaning if i set to read 10 then if it not find the 10 then it will read what it find as example it reads 6 ,it will return 6 and when to loop another time ti read the rest it dose not start from 6 it start from 0 and read until 4 so you overwrite your data ,and if it read 10 from the first try then it set the read to finish so it dose not start from 0 ,it needs to read the amount the has been set to it to re set the read to new buffer location.
I have the raw data and want to convert and generate a jpeg file, I do that as below, but it does not work. The generated file could not be opened well.
String photo="0xFFD8FFE000104A46494600010200000100010000FFDB004300080606070605080707070909080A0C140D0C0B0B0C1912130F141D1A1F1E1D1A1C1C20242E2720222C231C1C2837292C30313434341F27393D38323C2E333432FFDB0043010909090C0B0C180D0D1832211C213232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232FFC00011080193012C03012200021101031101FFC4001F0000010501010101010100000000000000000102030405060708090A0BFFC400B5100002010303020403050504040000017D01020300041105122131410613516107227114328191A1082342B1C11552D1F02433627282090A161718191A25262728292A3435363738393A434445464748494A535455565758595A636465666768696A737475767778797A838485868788898A92939495969798999AA2A3A4A5A6A7A8A9AAB2B3B4B5B6B7B8B9BAC2C3C4C5C6C7C8C9CAD2D3D4D5D6D7D8D9DAE1E2E3E4E5E6E7E8E9EAF1F2F3F4F5F6F7F8F9FAFFC4001F0100030101010101010101010000000000000102030405060708090A0BFFC400B51100020102040403040705040400010277000102031104052131061241510761711322328108144291A1B1C109233352F0156272D10A162434E125F11718191A262728292A35363738393A434445464748494A535455565758595A636465666768696A737475767778797A82838485868788898A92939495969798999AA2A3A4A5A6A7A8A9AAB2B3B4B5B6B7B8B9BAC2C3C4C5C6C7C8C9CAD2D3D4D5D6D7D8D9DAE2E3E4E5E6E7E8E9EAF2F3F4F5F6F7F8F9FAFFDA000C03010002110311003F00F6FA28A29805145140051451400514514005145140051451400514514005145473DC436B0B4D712A451A8C96638028024A47758D0BC8EA883AB31C01F8D79378ABE307D9E56B6D022460320DCCC3393FECAFF535E57A978AF57D5E42F7D772DD303951249903E8338FD2B3753B16A0FA9F495D78CBC3766E526D6ECC30EAA926F23FEF9CD541F117C264E3FB613FEFD3FF00857CC6F7F719E622A3D8D345E90D8669233DF934B9A43E589F555AF8C7C397A7106B5664FA349B0FEB8AD98E449A3124522C887A3230607F115F22C573295CEF561EBEB5A7A6F88F54D2E5CE9D7F7169275D88F853F874A7CEFA8B94FAA68AF1FF000FFC68DA63B6D7AD09230AD7110C1FA95E87F0C57A9697ACE9DAD5B0B8D36F22B98CF5D8791F51D455A9264B4D17A8A28A620A28A2800A28A2800A28A2800A28A2800A28A2800A51494A280128A28A0028A28A0028A28A0028A28A0028A28A0028A28A0028EBD29934D1C11192460AA06492715E3FE3AF8A4AE1F4ED1A42F191896742507FBAA7A9FAFE5EB5329243516CED7C57F11346F0B1681CB5DDF01FF1EF09FBBFEF1E83F9D78678ABC71AFF008B1C8B9B81059E72B6D136D41F527935CEDC5F2CF2B3B939639214D57DE8C4E56539F7CD67ABDCD2C96C35AD9DF3F316FA1CD41F67393C1E3F4AB5B369046187A30C1A9198ECDC7E71EFD47E35484545DF1E76B30FC6944C0B6D90004F46E9565E35920C44E41EC1BA5565469818A5003FF09EC698890AC903EE53807AEDEF56149980C601C703B56747349012AD929D08EE2A682630B7964831B0CA363BD2B05CBBE647226D67C30E391C83EF5A7E1DF115DF87B5459E165CA7547C94907A6474FA8AC391B77FA420C38E185123078C3E4846EA07F09FF0A2C173E87F0BFC4AB4D4094BC91A3079DB272F1FAFCC3EF2FEBF5AF428E48E6892589D5E371B95D4E430F506BE3DD3B529EC2E53E620A9C8E6BD8FC11E3796CE6315D05FB131CCCA0FFAB6271BD4761FDE51F5A14ADA306AFAA3D868A4565750CAC195864107208F5A5AD080A28A2800A28A2800A28A2800A28A2800A51494A280128A28A0028A28A0028A28A0028A28A0028A28A00291DD63467760AAA32C4F40296B3F5ABE834ED2AE6EEE1808A08DA56CFA0FEB9C63DE93D00F36F8A3E2C9C694D6B6B32DBDBB9D8CA41F36538071FEC8C1E47D33D715E1DF3DCC9F331E7A0EF5A3E21D72EF5CD41A7B876650488E33D14139C5635CCBB104607CC7A9EE6B35AEACD5E9A124925BC2DB51958FAF5A8C5DB2B0DA11BF0A9F4DD1E6BE94048CB13DB15DB5878363441E747BD8F50074A529A45C294A5B1C4F99E728DAA5241E9D2A41E6B0E62FA95EFF00857AADA783ED4A85F2571EB5A71F836CC631101DF359BAC8D96199E31F6372C1A3E327953DEAC7F665CB60B4041038E3835ED0BE09B160410016EE074ABF07846CE188A8E47A11C52F6A2742C784FF00663B22C8C8403C64D46DA534711254943E9FC26BDCE7F075ABC451506D3C81DC1ACFFF00841C213D0AE7D3EF7D69FB50740F14F2D90F03A8C303DE976AA301B7746460D7A9DEF80BF78C5172A0646055393C05232B148C9A7ED513EC19E632C7B485CE71F75BDAB5748D425B69E378D80208EBC8AEA2E7C0572225C0C38EBED5CAEA1A3DEE8D39F3A3207F7BB535352D0995294753E82F869E215D574A92C89C1B7C794A7A85EEA3D81E9EC457755E03F08F561078AA189FFD5CE8F193E84F4FA7231F8D7BF56D17A18496A14514551214514500145145001451450014A29294500251451400514514005145140051451400514514005791FC69D61EDF4FB1D2918ABDD31B89D73CED5E114FB6727F0AF5D1C902BE59F1EEB4DADF8B751BC32168C4A62847A2A9C0FE59FC6A27D8B86F739B4600B3919C0FCAA7D374C6D46E038C919E49F5AA5187B8963B7897259B923D6BD4342D223B3B651B7240F4EA6B3A92E546D469FB4916343D1D2CE2CEDF9ABA6B5B4E4123AF5A4B1B5C95523DEB6238D7B0AE3726CF4D2515616080051C55C8E2C7E3DE9225031C55B54E3B50919C98C58F8A781ED8A78434A0107919AAB117136E78A367183520500F029D8E2AAC4DCAE500ED51B46A3B55964F5A858617247150D14881A08DC608159BAA786AD354B49219630430FCAB558F3D69CB271EB4E3614AEB63C0EEB4EBAF0978A9AD64E064346FCF2339047BD7BEF863C5B6DAEC49138115DEDE9FC3263FBBFE15C3FC4BD086ADA30BB857FD2ED7E6423A91DC579FF833C4F2699A8C4D2B1F2FEEC981CE3D47B8AE984CE3A94CFA728AA5A56A10EA7A7C7710CA2418C33018C9F5FC7AD5DAE839C28A28A0028A28A0028A28A0029452528A004A28A2800A28A2800A28A2800A28A2800A28A280313C61A99D1FC1FAADF23EC923818467B876E063F135F26DD49BA7C0249007FDF55F44FC67B868BC190C2A7026BB5DDEE02935F3BDAC66599E663C29FD6A1EE5AD8DBF0AD8F99A9A36DF963EE7B9F5AF56B2B718500702B88F07DA79AE5C70057A3DAC41556B8EB4AF23D1C2C6D0B97AD6301781C9AB2894C846D5A99783ED592376C9A3241ABD1E0AD514EA0F7AB48FB718AD22CCA68B1B41E29DB062A157E6A40FF4FCAB4BA33B3142F7EB476E94BBBDA9BBB27A629084238A89C0A909E2A17383ED52CB488641935096C1E3A54D230A84F3599A5886ED44D0329E4115E07E26D38E87E25991011139DE9F8F5AF7E90706BCB7E275906582E80F990ED27DAB4A72B4ADDCCAAC6F0F437FE16F8A12DAF63D2EEA4CADD9C44DEADD81FF003DEBD92BE51D2EE5EDC413A64496F2ACA8476E735F52E9F7D16A7A75B5F43FEAEE23120F6CF6AEB83E879F35D4B34514568405145140051451400528A4A5140094514500145145001451450014514500145145007887C69D54CBAE5BE9CAC765B5B6E23B6F7E7F9015E4B68A44078EA6BADF89F76F77F103572321525108FA2A815CFDBAE21403B93591A58EF7C1B1008A3DB9AEF235007D2B86F0683B73F85776831CD71D4F88F4E969045B8F18AB089919A8208D9B1C6055C5D8BC67A7BD42453648910C7153245C6714D4C6719156546056AA262E4C84A1EC28C107A55B007B505148C815A720B9CACA48EB4D63F9D58D80F03141840C52E563E6457C12290C79AB2540A8CE31CD4B882914DD315011CE4D5D7E7355996B26B53452216C115C478F625934975C65BB576CFC5713E386FF00896B8EFDA85BA097C2CF32D381DA14746054E7D8D7BD7C2AD48DE7851AD1DF2F6729403D14F23F5CD782AFFA35B893241F3011F88AF50F8437E135EBBB407E4B9B7DE33EAA47F426BB63B9E6CB63D8E8A28AD8C828A28A0028A28A0029452528A004A28A2800A28A2800A28A2800A28A2800A28A2803E62F8951087C7FAE6063F7C08FAB006B06DC816A093CF35D1FC5424F8F356C83933A819F408B5CC4583005EF9AC99A23D1BC19FF001EC0E39CF35DDC2BBD87A570DE0A42F66A7DFAD7758658895E1BD6B8E5F133D283F710EBBD452D94C7102F2770BDBEB58CD3DEBCA658A399971D00C66B4EDECBE6DC0EECF527BD6B430C11A65880A393934E2BB8DCADB1C98D6EEA39B63298703952A49A58BC4F7F04A04DB8C67A315E3F1AE96E758D0D0849AFED432F6F30122AACD79A3CC02895006E465700D53B74145DF7458B2D7FCF452CB82C3B56B4773E62E41AE5E58238FE687057B62B4B4EBA050293ED494D8E54D5AE8DC0D81B8F7E94D79F6A73D052647979CF359B7B3EC8B1DEAA53B19A8DD9625D4A1894963D3AD64DC78BAC230427CCDD3D6AABD8BDE29123E14FAD25B785B4EDFB9A4CB7A16E951CCD9A38463B8DFF0084B239064201ED4B078844F36CDBD3AE78ABA9E0DD295CC811998F5CB714B3F87AD1147930AA6DE4629B892A6B62D330740CBD08AE2BC6CB9D35F9C135D3596FB794DBC99D8DCA9F43E95CDF8F976E8F2B7A63F9D42DD0DE89A3C9F5090ADB40A7AB499FC2BD0BE12AEEF17DB64E365B3903F0AF3CBEC32D99EB8E48AF47F83C86EBC6534C14797059B11EC4903FC6BB5743CE7D4F73A28A2B5320A28A2800A28A2800A51494A280128A28A0028A28A0028A28A0028A28A0028A28A00F9F7E3469A6DFC671DC7245EC2AE3D8AFCA7F97EB5C1C49F291D81FCEBD3FE2EDD26A7736D2C6EAE2D77A851D403DFF00315E796F092625E4EF7FE558F3A7B1BBA72834A47A8F82EC8C3A4C6C47279AEA88079C671DAA8E8F08B6D2E18F1D1055A30866CE07E55C5296A7A118E962A6A9AC0D3ACFF75099676E12251924D7137FA7F88F5EB5B89B51927B7E3315B47C291EF5E8B0D8C68776C279CF1D5AAD84509F7703FBACBC5383B6E124AD647885AE93796EA206D31CAEEC991A3249EBC7A735E856BA5DAD9F87AD4249E5DD85CCA814B29F63EE2BAC658CF1B500CE78CD4125BC1C928315B395D58CE314A5CC73902ABC2DE5BB473852C114E41FF0AB7612BACF116EAC39FAD5C91460A43C023E638E83DAAB4087ED4840E178158CB7B1D4B53A549098C0E2B1EFE461305E3D066B522271D6B3AFD7372983834A5B1115A983A85C933790B2B48E78C29DAA3EA6B9BF1035FE93A840A2F41B574DCFF67C027D831C9AEFBECD14ED9740ADDF1C66AC8B0B7600490A381D03006B485B726ABE6D0F2FB2D675E96F9174BD4E658E473B52E083F28EEDD715D3E99E3C963BDFECFD66DCC72E7689907C8DEF5D545A4D82E76DAC60E739E29B7BA4D9DCC4639218F6FA003344E48CE2927A9332A4C56442083CF06B9AF1EDB97F0EDCB019C2D741696CD664448DF201819EC2AA78920FB57876F62C6498CE2B38BD47256D8F9FAF59B108EC11715EAFF0411BFB5753720FFC7B800E3FDB15E65730868ADF079008FCABDE3E137874693E184D42420CF7EA1F8FE1404E07F5AEE8EACF3A477D451456A66145145001451450014A2929450025145140051451400514514005145140053263B6090FA29FE54FA8AE7FE3D66FF71BF952635B9E49E23D363BBD36750BF300C49AE074887CED5AC62EC0D7AD3DBECB09A771BBCCC9C7A03D2BCE34487678AC8DA42C6481ED9AE24EC9A3D6C42E69C59E9F08022503A01C55A8B008F535562FB8335617839AC5948BC98039A4765CE0134D8D59BAF6A9C460AF4156913A22990CEDF2834BF675032D93577C9E7DA94A0C1E00ABE5072EC645C2F1B40FCAAB471E2451D31E953DD5CA6F644E48EB51DB2316DCFC13DAB37B9B2BA46AC43E5EBDAA8DF27EF15BB568C3165338ED515D4584208AA71D084D5CA9182782335602100E18D47692AABF9520E3B1AD45851B907F2A515714DD999F8607E6E7E82A64DAD9C60D58680E781513463B7047A537168574C6141CE4556B98F7DACB1766523F4AB2CD8E33F8D44DD718EB59ADC867855AD83DDEAB1DA2004B4A463D81C1FD2BDFBC213A1D30DA22145B7014293D3B7F4AF29F0C5929F175E1E71049264FA64D7ABF8517F7133FF78E7F535D506F9D2339538AC3CA4F7B9D0D14515D479C145145001451450014A29294500251451400514514005145140051451400535D3CC8DD0FF1291F9D3A8A00F3EBAB8F95AD597231B6B8F4B3FB3789E2754DB1CA060F5C15EBFCEBD0F52B0824D5E50D1F0ADB87E3CD624FA7F977EB21036A9CA0FEB5E7BBA7667B32946704D7A97630401C5581512F0054919C9ACDEE28B2F44700135723C7B5504600558127191D6B5831495C9A595546011CD50BAB9DB048C3A81493CD96DA0F350C830A549EBC1A6E772A3048AD6DE5470F9923282464926A05D52D2698A5ADD452B2FDE54704D23DA15F9762CF1F64638C5645D787ECA6B9FB54109B7BA439568CE39ACCDAC9EB73BC86E63FB2C7800311CD41A8DC471C439193EBDBDEB9D4BD9D618D7692CBF7A96E54DF6D697718D7FE599E327DFDAA9D46D58C552D6E68C135B4F1931CC8E41E769CD68432B0406B120B1557F336C716472B18EBF5AD34CEC233CF6A94EC54E28D38A40E9D71448063B66B3ADA7C3956386156DA5C826B572BA3271B3229463E95093FBC19F5A7C8F9A87AB0158F507B1CDF84F4F293EAD7520C1B8BA62B91FC3935DFE876FE458938C076C8FA7F9CD7190DD3C33982304E093D2BBFB3564B2815B8608335D346CE4D99E2D3A74947B93D14515D479A145145001451450014A292945002514514005145140051451400514514005145140181AD109A821C632832477E6B12FB9B98BDD4E6BABD4B4EFB6857460B2A7033D08F435CF6A3A75EC2F1CAF6FF00BB4C86752081F5AE5A907CCD9E851A90704AFA9507414FCFA77A8C1F996A6C6074AE496E744762CC2011ED53380919CFE150C1D053EE01DA31D68520DD9573B14B100B13C9A89E6C92481D68951B6E4E460679AAAB20DC4B3F51DE9DCD3726CB6E38E4FA7A52471BC8E30BB4F7CD466E23FEF73DEACC534783CB608F5AA516C1A63F728382A188EE6A09449B738C96FCE9B27D97EFE589FF007A9C2E63098FCB34DC243507B91C45C939247D0D5A490AB28CFE354DAE602321B07D29D14A92B80A6A354368BD38257CD4E5D7F5A9A19FCC881031EC6848999001D31447179701DDCF3DA8E633BA6AC46CD938F5A72FDE3DE88937483FD919A338622927EF112D8B36D6F1CB7702EC041619E3F1AE9AB9DD2D8A6A51A9E7208FD2BA2AEFA0BDD38B177E7498514515B1CA145145001451450014A2929450025145140051451400514514005145140051451400541789E658CE9D731B7F2A9E8A011E7F9F9B8EB572325B150DE43F67BF9A2C7DC738CFA76A58240C40CF23A8AF2E71B33D783BC6E5B806D18F7AB650B019AAA061855E8CFC9C524852672FE287D422457B5E235E5801D6AADB68D7F73134BF6E5703691B57AE7AFE55D2DF0EA48C8C60E7D2B9C669F4E95CDB48446DCED3574F9766691E669723B337A3F0920B8883DC48F191CF6E6AEC1E1784DCC8BBA50A318F98F354ECFC4EB3BC21D3CAC0C12790C7EBDABA3B6BB6688CADB7040C6C39AE9518F439AA55C44349192DE19B737423DD273CFDEE31531F0C59A5C20F2CB260E77126B504F9973B0F03AD51D575836908749225653CAC8092C3D0629D910ABD693514CA177E18B4304DB536313F2107A570DA86997367AC35B59DE3C8CC385EA14D74979E24BA9ACCC512E1D9B265C6D38CFA547A3DA6C2D7329DD2B9FBC6B19B8A3B29C6B4173547F2356C2D9EDED63576DD26D0093DCD589942C6062A44E82A2B87CE7DAB07B195EEC860036C8C7D71459422E6F16324856EA475C5337058B1EBCD5ED0E3DD73249FDD5C7E26AA8C79A689AB2E5836695A6990D9B99159DE4E9B9CF415728A2BD2492D11E74A4E4EF2614514532428A28A0028A28A0029452528A004A28A2800A28A2800A28A2800A28A2800A28A2800A28A28039AF135B18DE3BC45E1BE490FA1EC6B120601F23B8AED7548567D2AEA3619FDD923EA3915E7D04C164C13D3D6B8EBC75B9DD869E9666EAFCCBCF5AB314BB545508240CA79071522B9E45729D0D166750EA7D0D65C96E1B28466B495C15C30CF6A6B202D914D15176461AD83C527AA75C7A569C114B1A1F227703FBB9C7E9569610DD7AD35E0639033C77ADE32B22DD6BAB4861B9D4241CCCEBC609500715464B68F2C6526473F89ABC23988032187B76A992D72727A5539F9046A463B7E06341605DC3B8DAA3A2D6AC2BB48006054ED1AA800520E0F15CF27A932A8E7AB2756C2D57958B71EBD6A4270951310AA49EB506688A66C0DB918AE8749B73058A9618793E66FE9FA5626996BF6FBDC9FF53110CFE84F615D4D76E1A165CCCE5C4CFECA0A28A2BA8E40A28A2800A28A2800A28A2800A51494A280128A28A0028A28A0028A28A0028A28A0028A28A0028A28A0064EBBADE55F5461FA579A5C407EFA1C30EF5E9AC32A47A8AF3ED9918C77C573623A1D78657B95AD2F46423707BE6B4BCC19045645CDB9DDB9090DD8D4715F151B64241E9CD7234759D086CE304559519158305F7EF3048DAA339F5AD7B5B859A3C8239F4A2C3B96D1950F5FAD48D2A1E322A011EF0769A745096E0F03EB571B834B726DC9C6318A0C800EB4184636D46D1ED18269BB92921ACC18F06A189A4676F300001C2FB8A460E24181F281C9A8A7B958863F88F02B268B7648B06404E73C0AA57373B80033ED8EB51CB73B1319F98D3614DC771E49A496A458E97C36BB6CE6E724B8273F4AD9AC8F0F9FF469C7A38FE55AF5E952F811E756569B0A28A2B4330A28A2800A28A2800A28A2800A51494A280128A28A0028A28A0028A28A0028A28A0028A28A0028A2A1BCBB86C6CA6BB9D82C50A1763EC280399F1CF8CA2F0B69DB61DAFA84C0F9687A20FEF1FE9591632F9D04726721D0367EA335E4DE28D62E35AD62EAF2E1B2EFD17B2827803E8057A2784EEBED5E1DB17DD9611053F51C5736236475E13768D9962CF38ED599756BB8671C8F4ADCC6E5E955A6871D338AE53AD9CBCE92A11E8390DDC55BD3B57F298473101B3C62AFCF6CAE318CD62DDE9ED13E42165EA41A6990F4D51D859EA28FC123F3AD486E623800F26BCD2192488E239DA33FDC93A568C1AB5EC6B8F2C330EEA69A9587A33BE69541E587355E796319F9BA7415C87F6DEA2E9810AEEF76A824BBBB646134EAA7D23E48FCE872B8F447437FABC709F2E3F99CF1B456524CE5CC8F9F309FBA0F4AA96D1B48F98D0EE3D647EB8AD6B5B355009EB50D8D216084C982C38EC2B436630288A221B3DAA57C2D24522383C476FA15EDBC17785B7BB72A65FF009E6C3A13EDEB5DA672320E41EF5E25F102E04726991E7EF3393F4C015DAFC35F1136A9A39D3AE1CB5C5A0F9198F2F1F41F974FCABBE8BF711E76257EF19DC514515B180514514005145140051451400528A4A5140094514500145145001451450014514500145148EEB1A1791951072598E00FC68016BC9FC79E2BFED367D3ECE4FF00428DB0CE3FE5AB7F80ED5A3E36F1AA3A3E97A54C19586279D0F07FD953E9EA6BCDA42197A8E7D6901CEDC125AE0E73F3819FA0FF00EBD775F0D2F849677762C7E689F7AFFBADFF00D715C03BE4DD0F4909AD5F06EA8BA6788A2676C473298DF3EFD2B2AAAF166F425CB347B745D3A734AF186078E2A382459143035615782C3F2AE24CF4199CE9863C7D29862126411C8F5AB73A1249039A85305C714EC4B332EB464946E518359ADA2DD21F91C81D706BB48911D7A0AB1F654206467EB4D23367111E8B76EBF3C9B7DEB42D7C3F1A00CE4BB1EE6BA836C00C019A6B461171D0D26868CE8ED123F976E3F0A9634F98E0F3529EB5246BE9516344204DA09A89CE6AC13CD65EAF7F0E9D632DCCCDB52352C4D32E279AFC42BE137896D6D94E45BC596FAB1CFF002029BE17D667D175E1750B0CC6F8656E8CAC3915CA4F7B2EA5AB4F7B2FDF9A4DD8F41D87E55A36AE3FB4255EA4A822BBE9C6D148F2EB4B9A6DA3E94D2757B4D6ACFED16AFD3878CFDE43E87FC6AFD784691AF5DE8B791DDDABE0E00743F75C7A1AF58D1FC63A4EAC91AF9EB6F70C398A538E7D01E86B43237E8A28A60145145001451450014A2929450025145140051451400514557BEBFB4D36DCDC5EDC470443F89CE33F4F5A00B155AF750B4D36033DEDC47047EAE7AFD07535E7FAEFC50DBBA1D1A0F6F3E71FC97FC6BCEB51D56FB529DA7BCB996690F763FE71480F4AD6FE28C30068F4AB6DE738F3A6E9F50BFE35C2EA1E24D4B5B72F7B7724880F11E70B9F6038AC02C40F5278AB200450BE9D7EB400F3212DC9FAD34E09F5A3273FE1428DE4E28039890E2FAE93D4D537CAB706AD6A07CBD5A418E180355A5033C5203D17C11E3500A69DA8BE18E16299BBFB1F7AF4E8A50CBC57CD0A4839AF4AF04F8DFE68F4DD4E5E7858A66EFF00EC9FF1AE6AB4BAA3B68D6BFBB23D464019491F7AA9104B607153F99C0C74A4C073D7E9581D16085BCB6C1EF5A50CA081CD515418C1E0FA1A9150A9E0D589D997DDC01559C9639A728247CC734BD3A0C527A896840D1E0824FE14A3273C53DBDCD4324A154F350CB4C259022939E71F957947C46D6CCCF1E9B1BFCA4EF900F4EC2BB0F12F88A0D26C9E495B2C461133CB1AF17BCBB9350BD96E66399246C9F6F6AD68D3BBB9957A9C91E5EAC2DC61C35685930FED5EBD63AA5180800A9B4F707598C632769AEC479E744AC36E29E92100AB72A6A1604673CF34A0F1914C4741A478BF59D1088E1BB3242BFF002C66F9971FD3F0AEFB48F891A6DE6D8F5089ACE4EEE3E7427F98AF2224B019E48A5538638FAD007D1B6F7305DC2B35B4C9344DD1E36C8A92BE7FD3B59BDD3271359DC490B772A783F51DEBBED17E24872B16AD08F4F3A11FCD7FC2981E854556B2D42CF5287CDB3B88E65EFB4F23EA3A8AB3400528A4A5140094557BCBEB4D3E0335E5C470460672ED8CFD077FC2B88D5BE27DA405A3D2ED8CEDDA59BE55FC0753FA5007A063358DAAF8A747D1C1173788D28FF96317CEFF0090E9F8D790EA9E31D6F562CB35F3A45DE387E45FD3AFE35866407D7DCD203BFD5FE27DE4BB934DB74B64E81DFE773FD07EB5C35F6A577A8CED71773CB34A7BC8C4FF00FAAAAE79CF34BB7D7AF5C668018DC1CF3ED4C2C718E2A6231C541236073D3DA9804403CB93C85AB180467144516D8957B9EB52140383EBDA9011E4820D390F5EF4D3F4A72F0076E7AD3039AD7E331DFC72606186335473915B7E248F75BA3839DA7358719040A402ED04533186E73528EB4D71C5033BDF08F8E9AD82586AB21687858A76EABECDEDEF5E9D0CCB22875604119041CE457CE238AEAFC2DE32B8D15D6DEE0B4D624F4EAD1FBAFF0085615297589D54ABF491EE11B2BAFCD532A7A1CD62586A905E5BA5C5BCAB2C520CAB29AD14BA0C301856074DBB1780E3A5359F02AAB5D85E335565BC2C719C0A4C39596259B1F2E79AE7BC45E22B6D16C9A5998173C2203CB1AA1E22F16DAE871329224BA23E5881E7F1F415E4DA96A575AADDB5CDDC85DCF41D947A0ABA74DCBD08A95953D16E3F54D56E758BE6BABA7C93F757B20F4155E250324D44064D585C05E2BA924B4381B7277623310BD79A4D224275C8FF00DD34D90D3B4319D710F600D52133AB93B64F3D3EB4C1D31C5492A9CFA1FAD464118EA4D021EB81D4FD3141CF3D7E948A71C8A7F5E707F9D30101E3A54884AF538C5443E623B0EE2941C938CD0068D95FDC59CAB35B4EF14ABD1D1B06BBBD1FE23CABB62D521128FF009EB1E037E23A1FD2BCD94E39C1C83EB4A84EEE01F5CD007BFE9FADE9DAA28369751BB1FF009664E1C7E06B42BE7A8AEA488AF278E841E47D2BA8B1F1A6B105B08C5F160A78F31031C7D4F3401C96A3A85DDFDD34B757124B21272CEC4E2A9E3279A795F9DB8E734D0B8F4CD201BB4038F5A5038F5A7E0000E38F7EB4D0A3A5001B79C76EF9A7E79271903DE8EF8DB8FEB48DC28C1F7A6031987F09FAD44AA659BB155E695DB0BEF4FB6DA611B48627EF7B1A009C201D40A6139CE69E5C0E00E2A2273C2F3400BB739EB4A7E5200E4D359B6FCA0FCDFC8D3118904E39CF5A008354877E9F271CE0D72509E0576D7196818631C57158DB23AFA3114809FB6690F22914F6341A061B734DC62A40334A40C50069E85E23BDD06E7740DBE163FBC858FCADF4F43EF5EBDA26B567AE588B9B490F1C3C7FC487D0D78601CE6AD58EA779A45D19ECA53148CBB4FA11EF594E9A96A8DA95671D1EC7B95DDFDB58C465BAB88E251FC523015C1F887C7E8375BE93F331E0CEC381F415C8DA69FACF8AF50710CCB7572ABBFCB7994311FEC8279FC2A8CB6EF04EF14A312236D61E84528D14B5654F10DE911B2CB2DCCAD34CED248C72598E49A455C9A52B838A78E0715AD8E76C5D985E3AD0A7029493D0D340E4E78A00639C8AB1A0A13AA338C12077AAED57BC3F9FB5CDF85342674B229607A54382B8CF03D2AC331278E83F5A8D86E3D00EF4C045C0C8E9ED4A3078C9C7D690F3DB38A453EF8FC2801AC304B7AD3C13C1E31EF43ED452EE7FFAF446498F0463B8E6801C011DFA76A7024F503EB9A400B2F2C73DE973C8C76F5A600783CD5AB771E59C9E73E95588E84F39F6A9635F94E01C669010151BC9C9EA69303271CE3BD3E4FF005878C60D373B718EB9EB400846072700D03AF3CFB52B0C9A5238DDC73C50034E7B6334D7C91D31CFA53BD7814C276FCB9FA8A0444E85B8C702A9CA92452F99136D6EFE87EB578B82085E49ED4C16ECE4971B47EB40C8E0BE49DB6C8BE5C9E98E0FD2ACFDE3F2F029C96D146095500F73D4D03D01C50044460F149820E31C1A7B0DC4E3814CCF1C75068026C62220F5C57177236DF4C3FDA26BB55CB752335C86A6BB354947AE08A1810A9E29D4D51C53C5200CE0D3B19EB49DEA7B5B59AF2EA2B5B7469269582A2A8C924D004124B15BED79559D370CAA9C16F500D76E60F08F8CECE38F4EB74D37548D00007064FF007933F31F7539F6ABF73F0F6CA1D323B7D76DA6B19C1222D5AD2433C2D9ED2276FC307DAB87D7FC19AB786CC77132A4F6321FDCDFDAB6E89FD391F74FB1C1A1810EB1E1DD5FC38EB3CF62A210DF25DC0C5933F51F74FB1C1AB177E29BBD7EDE34D4EDA396EE20156F106D91C7A3FF0078FBF5AEA7C21E319622B61AF3FDA2D241B3ED122EF641E920FF00968BF5E4763573C59E04B7D3617D6348402D061A7815B70881E8E87BC67F4A4981E7FC30F7A403079A8DEE10DD6DE81BA7D6A43CB7BFA5318A4934DC734E1C76A0F5E280227E957BC387FD22E0919C11546438539ABFE1AFF59367B9142133A4241FE1C7A5386DE724629A78207A0CD1C6C231DFB5301E7681918FA546ECA8A18E001D4D3B04F7E00CD38283C7502988CF25AE640EC708BF747F5AB6140DA41A468003B97AFA53C71C1EB40C78072401C9F5A41EFD0D286E8476EE69AD8248273E94002918273CD5A831B09C1E4F6AAC09CE7F954D1394523DFD280227F99C8F7CE6A323E61EE6A4707CC3EB9ED4D66032768E29084E7248E94A464918E075A14719FC69369C1386FF001A603791D8FD7AD4172E5636DA7E603AD4CD9E80F1EF50CA01041E9DE8027B765F2D766002323DEA5EE723B67154AC0E6231FF00CF3623FC2AF01D0AE2801802AE79C64669833D0726A5DBB739C533A9A008882783834D00027207E34E627A74151A8049EB8F6A432CA9C6707A7A5727AEAECD490FF796BA98BDFA0F5AE73C509B25865039068623354F14F14C4C15C8E98CD380E47AD218F5F7AB7A5EADA769BAAC7F6F4BB2A4644B6920592139E187AFD38AA6D88D0B9E83F53E95962D24B9B96D873331C853FC5EC3DE803E8AD1BC5727D83ED32CE9ACE92DF2BDEC0BFBC8FDA68CF5FC7F3AD88F45B596DDEF3427866B2BA189EC5BE6B79C77001FBADEC79F4AF9B346D6752F0FEA02EB4FB892DEE17861D98775653C11EC6BDAFC09E28B2D76E0C9A704B0D5587FA56984FEE6E40EAF17A1EF8EA3B509EA339FF17F82D7458CEA9A6A3FF67B361E26E5AD98F63EABE869FE03F16E66FEC1BCC488EAC2D83F46047CD09FF658671E86BD635158EF2CE46110994A149A16FF00968BDD4FB8F5AF9BFC5FA5CBE15F1029B5998DBB91716530EBB73C7E208C1FA5262454F18E93FD83E269ECE125AD89135BB1EF1B723F2E9F8555B39FCD8C17FBE3EF7BD69F8C7598F5FD52DAE23006D814311D99BE623F024D62A298B6BAF51DBD685B0CD23EB8A43C669A8E2440C0F07A539A98114C32BC77AD1F0E1C4D3301E959B3B6067D0715A7E1A18926CF6C53423A323058F7C518C8C91CD2838EF9CF34E61C6473EB40840ADB724D19EA470691D84519627E526A38EE637182E37771D29812FF00C0BDA9B83CE453B8EDF8D200318A0069C28EF4BF771807DE9922E5003EB5230F90F3C50319B8EFE01E956603FBBEBDEAB36401F313562023CBFBB9E680226FBCDC73BBA537664E4FD49A7BF32301EB4857FBBD7340814718C72280C40E690E71D7927AD213C633400D3B8609A8A4C7271D7F954A4823FF00AD4C2BFBBCE68029DB1F2EF4AF389173D7B8AD34E87273E959736E8E58A4C7DD6F4ED5A48C3B66801EC3907B9EB4C619241CE4F6A5E7A9E39A46E79CD0042CBCEDC8A4C90411DBB629597E6240F6CD20E09CF1DF34864919E08C561F899736E9EA1AB701F907F4ACBF10A03A7B1C64820D0C47356A7E4C1EDC558C1C8C753D2A9C1F7F6FF7B8AB723145F2C6379E0FB0A432299B7B051F717F53EB558AFEF1707073C1F4AB2DF2AD57670A771ED401D55868C3C656412C87FC4E605DD264610A0E3E76EC7D0F7E95662F00F89746BC59844AB3429E7978A603C90A32599891B715E9DF0E3458347F0B5BCB082D737C05C3BB8DBDB8273D140E99FAD721E3FF00170D5125D1F4B90FF6786FDFCE3ADD30FF00D90761DFAD16B01BDE0FF88B17885DE19891A9C3117940181728BD580ECE3AFBD711F142E6DEE6EE0B78195E32FF006984AF40AE3E603DB2335CFF00867C3F75AD7886382D9DA1863FDE5CDC02408A21F78923D4718EE4E2B47C796B0597898410487CBF215920239B75249543EF8C1FC6A7A8CE6228BA7153B28C6295050E302A84471B7932609F909FC8FAD5F1C8CD51601D0D49693160626E5D4617DC50319390C5547739FC2B6BC383E6B8F6C561B7339EF8E056EF8748F3E6EDC8A6846F76E3D297B6724629C7AF07826800007DB8E9408301D406C1F6AAD25946C72B953E839156D07209A42C7711C7E069814A34B8B77009CC6474CE7FFD5568005471D7BD48DCB6D3E9C7151B282DDB8F7A006CA732A28E78A776C1CE4531FF00D7E31C8C54A41241A0631BE5233DEA6B70BE59C8EFDEA171EC01A920E10F04F3400A48DE727B9E94600E074A523058E463A5260123BD0211B1C01CD31BAF00600A71197E69B8DC4F031D28019C8E08C5249D38E7F0A7E7AD46C7E6A00AD7281D1947A75A9ADDC3DBA311CE39A57518F5A82DBE5DF1E790723E86802E9248CF149D88A542186D34857D0FE740119DA3193C8F4A69EBDB03D2A42AB9FAF7A43C76EA3E94862A803E53DCD53D690BE972F6C0AB8A7902A2BF8F759CAA73F74D023854FBD56630076AACA306AC4679A43125E168D32C5F55D6ACEC1012679557819EA69B3B002BB4D363B7F08E8B0EA1E403ADDD022191CFCD0E47551DB0A7AF5C91401D678F3C522D206F0F6992004288EF2643D80C794BEC3BFE55C3691A3DDEBDA8C5A7D8C7BA693A93C2A2F7663D80A8E1B5B8D42F22B6B789E6B899C2A22F2598D7B069D61A57C3FF000BCF7178EB230C7DAA543CDCCBD44319FEE8EE7F1A00CAD565D23E1C7851520559A490E61571F35ECC3FE5A3FF00D335EC3FFAF5E2134F737F753DFDCBBCB2CB2169256EEC79AD2F156BF7BE24D665D46F9C176F95117EEC483A228F415D55A78705AF80B51374A5654B64BA718E56466CA29FF80E0FE353D467131F4A7B2FCA69919E01A95CE56A845743DA865039EF401F352C9400D8979F6ADFF0EE049393D320561C43835BDE1D1CCE7FDAA680DD23278071480F5F989A7E7E5383CD346319FE54085191CFEA29C76F427F1C528E3A372074C500E7B649E6980CC64920D20C93806970A48CF514050791F8500349CCAE47AF6A9368DA33DBAD44BC8CE39CFE15229E79C508631B19C63247AD4B0E761E40E6A27C1239E4FAD490950878CF3D85021E48F9BA75A418DDD3927348E36330A07098E33FCA8108D819E73ED51139240E062A46C6083CE2A238CFB1340C71238A6E3739078ED4A70070793403C640CD0046E00380411F4AAA0EDBBF665C67DEAE119C6073DCD54B8182AE3A86CD005A46E29DC670BDF9A895883CF3F5A99946CDD9E4D003581C8E7EB4D6E00C76E94EE0AE29A4E78E82800CED26A4917CC84E0678EF50F7F71D7356010613CE7B62803CF241B6575F4635345CF4A4BE5297B3A91D1CD1074A919A9A0E9E351D7ADE2750D1A1F31C762179C1F6CE3F5A8F58D58EADAF3488E5A08FF7711FEF0CF2DF89C9FCA8B5D44596997B1404FDAAEB1133FF00722EA40F763C7D07BD75DF0CBC286E6F63D6AE60591124D9650B8F96494725DBFD841C9F7C500773E0BF0E47E1DD31F53D49960BD6877CD230FF008F3848E9FF005D1BD3A8CE2BCFFC6BE2697C45A80601A1B1B7CA5AC19E157FBC7D58F735B9E33F152EAD31D2B4F99A4D3E172D2CDDEEA5EEE7FD91D87E35CE68FE1EB9F126B096301F2D00DF3CCC3E58631D58FF004F534010F843C3D1DF5CCBACEA3116D2EC181F2CFF00CBCCDFC310F5F56F6FAD7A6EA3666DB47B6B5D4486B9D46F04F780F655F9DC7D00551F9D6CE95A3DA2A5BB451AC1A4E9C08B4493A330FBD33FA9EE7DF02B86F1DEBE1747BCD4C92AD7AAD61A6C6C7E61167F7B29FAF4CFAB1F4A9921A3CACDC2DC4D24C8A111DD9828E8A09C81521E56B3ED8E015F4ABE394AA02303E6A24E4D0A79A6B1CB714089A3C05ADDF0E6364FC7F17F4AC3C6D415BBE1B03C894F425C8CE69A036CE0F6FA8A41F7BDA9CD95071D33C1A0025FD47AD0217DF278A3E600B0C71C53874E7A534819E99CF4A6023678CFA7A51850BDB03D0D047CE383F4CD237DC73EDD31400C5C989724FD314E52320FAD391405C1FAD38631C0C9A008D946086C023A54909DA8402719F5A6363A93D78E29D1AE54F03AD003DF3E6373819A69CB71C648E6948667386EFDA9A46E272706810D6CF7C1A839278FC2A7700707A8AAA3396CFAD0344E010B818E98E690718073CF7A45CB70453F8CF4C6D1400C0700E1AA3957CC47E3B75A9362E3D0FA5211CE07208E68020B7625149EBD2AC8E4118E2ABC6A04AEA7D7233DAACAF5DB9E9400D38048E9CFA534F390339A7F439033EF48E39CD0033EF718A9A305931C0CD440F3935221C92391480E27594F2F559C0E84E6A0B7FB9577C40BB7546F75154A004C3C024F603BD219AFE18D0A4D7F54FB386F2E05CC97136388A31D4FD7B0F52457A1F8C35C8F42D31742D3904171342239114F36B6DD562FF7DBAB7D7DE974D8AD7C07E0D5B899524BC720953FF2DEE7190BFEE479C9F56AF3B334F7D772DCDCC8D2CF3397776E4B313480D1D22C6E350BC86CED2232CF336C4403A9AF6FD0BC356FA4E9BFD9B036EC90F7D72A3995FB2AFB0E807E359BE07F0A1D0AC84B3A0FED6BA8F2FBB8FB34479DBEC48E4FA74AEBE666B78520B407CE7E221DC67AB9F73DBD055A4230FC437313C52D81996D74FB64F32FE71F7628D7A20F5F4F7635F3C78B7C40FE24D71EEFCBF26D63510DA41DA2887DD1F5EE7DC9AED3E2378A23BACE83A5CBBACA19375CCEA7FE3E651FFB2AF6F5EB5CEF81BC2BFF000926BC0DCA37F665A625BB61FC433F2C63DD8F1F4C9A8651B29E15165F08DEFE6091DCCD2A5E3B38F98467E48D07B9C96C7B8AE290FCB8AEF7E2EF88775D41E1D81940B7713DE04FBBE6E30B18F645E3EA6BCFE13914201A38269ABCBFE34BD18D2C3CB5311331C0ADEF0E28FB2B9238DE6B9F73D6BA2F0E7FC79F4FE2269A066CE4AAE07AD19DAD8007F8D07248C77ED40C9C93802810E0CD827B76E28182016EA29491B7078E7AE681C7BD30180E5BF1FC6924394E4F538E6970093914C906022E3BF7A009768C06639FA5203B72DB4E29FD62E3191E948589EA7B7A50046572CC1781EF52C0008F9F5F5A898ED20E39FAD4F06761FAD3026F29031C2F7A1E240385EB451480AF2C69B41C738F5A8C449FDDEF451400F4893238EDEB4796BB18E3B8EF451400EF2D3D283126FE9FAD145022BBC482E970BDAA648931D3F5A28A062BC4983F2F6A431271C7EB451400C1121DD91D3DE9E235DDD28A2901CC789608FF00B414EDE76FA9AA365122AC6CA3043020E7DE8A290CECBC7A4BF8896D589305B5B44B0A678405431FCC9249AB5F0D6C2D6E3C5B69E742B208D1E550DC80CA09071DF07D68A2840CF6BD3544912BBFCCD2CD8727F88019C1FC6B9EF175D4F0783F55BA8A5649DD9223203CED638600F6C8A28AB7D40F03B8823C9F97F5AF6CF03DAC1A7F81B4E92D6258DDEDEE2ED88E774CB9018E7AE0018ED451598CF9FAE07DA6692798B492C8C5DDD9892C4F249AB56D0C7B47CBDBD68A2840C6B431E4FCBFAD3E1823DDF77F5A28A6215A18F27E5FD6BA4F0FC118B0FBBFC47BFBD1450819AFE5261BE5EFEB48224C0F97F5A28A62078D42A8C7BF5A72C498FBB4514C00429B54EDE49E6A19517ED0463A5145004BE5260F1FAD46635C118FD68A2980890C67AAF7F5AB1046BB5B8FE2A28A00FFD9";
InputStream is = new ByteArrayInputStream( photo.getBytes());
FileOutputStream out = new FileOutputStream("C:\\test.jpg");
byte[] data = new byte[1024];
int readBytes = 0;
while ((readBytes = is.read(data)) > 0) {
out.write(data,0,readBytes);
}
out.flush();
out.close();
is.close();
What if I get the string like that, it looks like not the hex
String photo = "/9j/4AAQSkZJRgABAgEASABIAAD/7gAOQWRvYmUAZAAAAAAB/+EUhkV4aWYAAE1NACoAAAAIAAsBDwACAAAABgAAAJIBEAACAAAAFAAAAJgBEgADAAAAAQ....."
Just remove the 0x with substring and convert hex string to byte array :
try {
String photo =
"0xFFD8FFE000104A46494600010200000100010000FFDB004300080606070605080707070909080A0C140D0C0B0B0C1912130F141D1A1F1E1D1A1C1C20242E2720222C231C1C2837292C30313434341F27393D38323C2E333432FFDB0043010909090C0B0C180D0D1832211C213232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232FFC00011080193012C03012200021101031101FFC4001F0000010501010101010100000000000000000102030405060708090A0BFFC400B5100002010303020403050504040000017D01020300041105122131410613516107227114328191A1082342B1C11552D1F02433627282090A161718191A25262728292A3435363738393A434445464748494A535455565758595A636465666768696A737475767778797A838485868788898A92939495969798999AA2A3A4A5A6A7A8A9AAB2B3B4B5B6B7B8B9BAC2C3C4C5C6C7C8C9CAD2D3D4D5D6D7D8D9DAE1E2E3E4E5E6E7E8E9EAF1F2F3F4F5F6F7F8F9FAFFC4001F0100030101010101010101010000000000000102030405060708090A0BFFC400B51100020102040403040705040400010277000102031104052131061241510761711322328108144291A1B1C109233352F0156272D10A162434E125F11718191A262728292A35363738393A434445464748494A535455565758595A636465666768696A737475767778797A82838485868788898A92939495969798999AA2A3A4A5A6A7A8A9AAB2B3B4B5B6B7B8B9BAC2C3C4C5C6C7C8C9CAD2D3D4D5D6D7D8D9DAE2E3E4E5E6E7E8E9EAF2F3F4F5F6F7F8F9FAFFDA000C03010002110311003F00F6FA28A29805145140051451400514514005145140051451400514514005145473DC436B0B4D712A451A8C96638028024A47758D0BC8EA883AB31C01F8D79378ABE307D9E56B6D022460320DCCC3393FECAFF535E57A978AF57D5E42F7D772DD303951249903E8338FD2B3753B16A0FA9F495D78CBC3766E526D6ECC30EAA926F23FEF9CD541F117C264E3FB613FEFD3FF00857CC6F7F719E622A3D8D345E90D8669233DF934B9A43E589F555AF8C7C397A7106B5664FA349B0FEB8AD98E449A3124522C887A3230607F115F22C573295CEF561EBEB5A7A6F88F54D2E5CE9D7F7169275D88F853F874A7CEFA8B94FAA68AF1FF000FFC68DA63B6D7AD09230AD7110C1FA95E87F0C57A9697ACE9DAD5B0B8D36F22B98CF5D8791F51D455A9264B4D17A8A28A620A28A2800A28A2800A28A2800A28A2800A28A2800A51494A280128A28A0028A28A0028A28A0028A28A0028A28A0028A28A0028EBD29934D1C11192460AA06492715E3FE3AF8A4AE1F4ED1A42F191896742507FBAA7A9FAFE5EB5329243516CED7C57F11346F0B1681CB5DDF01FF1EF09FBBFEF1E83F9D78678ABC71AFF008B1C8B9B81059E72B6D136D41F527935CEDC5F2CF2B3B939639214D57DE8C4E56539F7CD67ABDCD2C96C35AD9DF3F316FA1CD41F67393C1E3F4AB5B369046187A30C1A9198ECDC7E71EFD47E35484545DF1E76B30FC6944C0B6D90004F46E9565E35920C44E41EC1BA5565469818A5003FF09EC698890AC903EE53807AEDEF56149980C601C703B56747349012AD929D08EE2A682630B7964831B0CA363BD2B05CBBE647226D67C30E391C83EF5A7E1DF115DF87B5459E165CA7547C94907A6474FA8AC391B77FA420C38E185123078C3E4846EA07F09FF0A2C173E87F0BFC4AB4D4094BC91A3079DB272F1FAFCC3EF2FEBF5AF428E48E6892589D5E371B95D4E430F506BE3DD3B529EC2E53E620A9C8E6BD8FC11E3796CE6315D05FB131CCCA0FFAB6271BD4761FDE51F5A14ADA306AFAA3D868A4565750CAC195864107208F5A5AD080A28A2800A28A2800A28A2800A28A2800A51494A280128A28A0028A28A0028A28A0028A28A0028A28A00291DD63467760AAA32C4F40296B3F5ABE834ED2AE6EEE1808A08DA56CFA0FEB9C63DE93D00F36F8A3E2C9C694D6B6B32DBDBB9D8CA41F36538071FEC8C1E47D33D715E1DF3DCC9F331E7A0EF5A3E21D72EF5CD41A7B876650488E33D14139C5635CCBB104607CC7A9EE6B35AEACD5E9A124925BC2DB51958FAF5A8C5DB2B0DA11BF0A9F4DD1E6BE94048CB13DB15DB5878363441E747BD8F50074A529A45C294A5B1C4F99E728DAA5241E9D2A41E6B0E62FA95EFF00857AADA783ED4A85F2571EB5A71F836CC631101DF359BAC8D96199E31F6372C1A3E327953DEAC7F665CB60B4041038E3835ED0BE09B160410016EE074ABF07846CE188A8E47A11C52F6A2742C784FF00663B22C8C8403C64D46DA534711254943E9FC26BDCE7F075ABC451506D3C81DC1ACFFF00841C213D0AE7D3EF7D69FB50740F14F2D90F03A8C303DE976AA301B7746460D7A9DEF80BF78C5172A0646055393C05232B148C9A7ED513EC19E632C7B485CE71F75BDAB5748D425B69E378D80208EBC8AEA2E7C0572225C0C38EBED5CAEA1A3DEE8D39F3A3207F7BB535352D0995294753E82F869E215D574A92C89C1B7C794A7A85EEA3D81E9EC457755E03F08F561078AA189FFD5CE8F193E84F4FA7231F8D7BF56D17A18496A14514551214514500145145001451450014A29294500251451400514514005145140051451400514514005791FC69D61EDF4FB1D2918ABDD31B89D73CED5E114FB6727F0AF5D1C902BE59F1EEB4DADF8B751BC32168C4A62847A2A9C0FE59FC6A27D8B86F739B4600B3919C0FCAA7D374C6D46E038C919E49F5AA5187B8963B7897259B923D6BD4342D223B3B651B7240F4EA6B3A92E546D469FB4916343D1D2CE2CEDF9ABA6B5B4E4123AF5A4B1B5C95523DEB6238D7B0AE3726CF4D2515616080051C55C8E2C7E3DE9225031C55B54E3B50919C98C58F8A781ED8A78434A0107919AAB117136E78A367183520500F029D8E2AAC4DCAE500ED51B46A3B55964F5A858617247150D14881A08DC608159BAA786AD354B49219630430FCAB558F3D69CB271EB4E3614AEB63C0EEB4EBAF0978A9AD64E064346FCF2339047BD7BEF863C5B6DAEC49138115DEDE9FC3263FBBFE15C3FC4BD086ADA30BB857FD2ED7E6423A91DC579FF833C4F2699A8C4D2B1F2FEEC981CE3D47B8AE984CE3A94CFA728AA5A56A10EA7A7C7710CA2418C33018C9F5FC7AD5DAE839C28A28A0028A28A0028A28A0029452528A004A28A2800A28A2800A28A2800A28A2800A28A280313C61A99D1FC1FAADF23EC923818467B876E063F135F26DD49BA7C0249007FDF55F44FC67B868BC190C2A7026BB5DDEE02935F3BDAC66599E663C29FD6A1EE5AD8DBF0AD8F99A9A36DF963EE7B9F5AF56B2B718500702B88F07DA79AE5C70057A3DAC41556B8EB4AF23D1C2C6D0B97AD6301781C9AB2894C846D5A99783ED592376C9A3241ABD1E0AD514EA0F7AB48FB718AD22CCA68B1B41E29DB062A157E6A40FF4FCAB4BA33B3142F7EB476E94BBBDA9BBB27A629084238A89C0A909E2A17383ED52CB488641935096C1E3A54D230A84F3599A5886ED44D0329E4115E07E26D38E87E25991011139DE9F8F5AF7E90706BCB7E275906582E80F990ED27DAB4A72B4ADDCCAAC6F0F437FE16F8A12DAF63D2EEA4CADD9C44DEADD81FF003DEBD92BE51D2EE5EDC413A64496F2ACA8476E735F52E9F7D16A7A75B5F43FEAEE23120F6CF6AEB83E879F35D4B34514568405145140051451400528A4A5140094514500145145001451450014514500145145007887C69D54CBAE5BE9CAC765B5B6E23B6F7E7F9015E4B68A44078EA6BADF89F76F77F103572321525108FA2A815CFDBAE21403B93591A58EF7C1B1008A3DB9AEF235007D2B86F0683B73F85776831CD71D4F88F4E969045B8F18AB089919A8208D9B1C6055C5D8BC67A7BD42453648910C7153245C6714D4C6719156546056AA262E4C84A1EC28C107A55B007B505148C815A720B9CACA48EB4D63F9D58D80F03141840C52E563E6457C12290C79AB2540A8CE31CD4B882914DD315011CE4D5D7E7355996B26B53452216C115C478F625934975C65BB576CFC5713E386FF00896B8EFDA85BA097C2CF32D381DA14746054E7D8D7BD7C2AD48DE7851AD1DF2F6729403D14F23F5CD782AFFA35B893241F3011F88AF50F8437E135EBBB407E4B9B7DE33EAA47F426BB63B9E6CB63D8E8A28AD8C828A28A0028A28A0029452528A004A28A2800A28A2800A28A2800A28A2800A28A2803E62F8951087C7FAE6063F7C08FAB006B06DC816A093CF35D1FC5424F8F356C83933A819F408B5CC4583005EF9AC99A23D1BC19FF001EC0E39CF35DDC2BBD87A570DE0A42F66A7DFAD7758658895E1BD6B8E5F133D283F710EBBD452D94C7102F2770BDBEB58CD3DEBCA658A399971D00C66B4EDECBE6DC0EECF527BD6B430C11A65880A393934E2BB8DCADB1C98D6EEA39B63298703952A49A58BC4F7F04A04DB8C67A315E3F1AE96E758D0D0849AFED432F6F30122AACD79A3CC02895006E465700D53B74145DF7458B2D7FCF452CB82C3B56B4773E62E41AE5E58238FE687057B62B4B4EBA050293ED494D8E54D5AE8DC0D81B8F7E94D79F6A73D052647979CF359B7B3EC8B1DEAA53B19A8DD9625D4A1894963D3AD64DC78BAC230427CCDD3D6AABD8BDE29123E14FAD25B785B4EDFB9A4CB7A16E951CCD9A38463B8DFF0084B239064201ED4B078844F36CDBD3AE78ABA9E0DD295CC811998F5CB714B3F87AD1147930AA6DE4629B892A6B62D330740CBD08AE2BC6CB9D35F9C135D3596FB794DBC99D8DCA9F43E95CDF8F976E8F2B7A63F9D42DD0DE89A3C9F5090ADB40A7AB499FC2BD0BE12AEEF17DB64E365B3903F0AF3CBEC32D99EB8E48AF47F83C86EBC6534C14797059B11EC4903FC6BB5743CE7D4F73A28A2B5320A28A2800A28A2800A51494A280128A28A0028A28A0028A28A0028A28A0028A28A00F9F7E3469A6DFC671DC7245EC2AE3D8AFCA7F97EB5C1C49F291D81FCEBD3FE2EDD26A7736D2C6EAE2D77A851D403DFF00315E796F092625E4EF7FE558F3A7B1BBA72834A47A8F82EC8C3A4C6C47279AEA88079C671DAA8E8F08B6D2E18F1D1055A30866CE07E55C5296A7A118E962A6A9AC0D3ACFF75099676E12251924D7137FA7F88F5EB5B89B51927B7E3315B47C291EF5E8B0D8C68776C279CF1D5AAD84509F7703FBACBC5383B6E124AD647885AE93796EA206D31CAEEC991A3249EBC7A735E856BA5DAD9F87AD4249E5DD85CCA814B29F63EE2BAC658CF1B500CE78CD4125BC1C928315B395D58CE314A5CC73902ABC2DE5BB473852C114E41FF0AB7612BACF116EAC39FAD5C91460A43C023E638E83DAAB4087ED4840E178158CB7B1D4B53A549098C0E2B1EFE461305E3D066B522271D6B3AFD7372983834A5B1115A983A85C933790B2B48E78C29DAA3EA6B9BF1035FE93A840A2F41B574DCFF67C027D831C9AEFBECD14ED9740ADDF1C66AC8B0B7600490A381D03006B485B726ABE6D0F2FB2D675E96F9174BD4E658E473B52E083F28EEDD715D3E99E3C963BDFECFD66DCC72E7689907C8DEF5D545A4D82E76DAC60E739E29B7BA4D9DCC4639218F6FA003344E48CE2927A9332A4C56442083CF06B9AF1EDB97F0EDCB019C2D741696CD664448DF201819EC2AA78920FB57876F62C6498CE2B38BD47256D8F9FAF59B108EC11715EAFF0411BFB5753720FFC7B800E3FDB15E65730868ADF079008FCABDE3E137874693E184D42420CF7EA1F8FE1404E07F5AEE8EACF3A477D451456A66145145001451450014A2929450025145140051451400514514005145140053263B6090FA29FE54FA8AE7FE3D66FF71BF952635B9E49E23D363BBD36750BF300C49AE074887CED5AC62EC0D7AD3DBECB09A771BBCCC9C7A03D2BCE34487678AC8DA42C6481ED9AE24EC9A3D6C42E69C59E9F08022503A01C55A8B008F535562FB8335617839AC5948BC98039A4765CE0134D8D59BAF6A9C460AF4156913A22990CEDF2834BF675032D93577C9E7DA94A0C1E00ABE5072EC645C2F1B40FCAAB471E2451D31E953DD5CA6F644E48EB51DB2316DCFC13DAB37B9B2BA46AC43E5EBDAA8DF27EF15BB568C3165338ED515D4584208AA71D084D5CA9182782335602100E18D47692AABF9520E3B1AD45851B907F2A515714DD999F8607E6E7E82A64DAD9C60D58680E781513463B7047A537168574C6141CE4556B98F7DACB1766523F4AB2CD8E33F8D44DD718EB59ADC867855AD83DDEAB1DA2004B4A463D81C1FD2BDFBC213A1D30DA22145B7014293D3B7F4AF29F0C5929F175E1E71049264FA64D7ABF8517F7133FF78E7F535D506F9D2339538AC3CA4F7B9D0D14515D479C145145001451450014A29294500251451400514514005145140051451400535D3CC8DD0FF1291F9D3A8A00F3EBAB8F95AD597231B6B8F4B3FB3789E2754DB1CA060F5C15EBFCEBD0F52B0824D5E50D1F0ADB87E3CD624FA7F977EB21036A9CA0FEB5E7BBA7667B32946704D7A97630401C5581512F0054919C9ACDEE28B2F44700135723C7B5504600558127191D6B5831495C9A595546011CD50BAB9DB048C3A81493CD96DA0F350C830A549EBC1A6E772A3048AD6DE5470F9923282464926A05D52D2698A5ADD452B2FDE54704D23DA15F9762CF1F64638C5645D787ECA6B9FB54109B7BA439568CE39ACCDAC9EB73BC86E63FB2C7800311CD41A8DC471C439193EBDBDEB9D4BD9D618D7692CBF7A96E54DF6D697718D7FE599E327DFDAA9D46D58C552D6E68C135B4F1931CC8E41E769CD68432B0406B120B1557F336C716472B18EBF5AD34CEC233CF6A94EC54E28D38A40E9D71448063B66B3ADA7C3956386156DA5C826B572BA3271B3229463E95093FBC19F5A7C8F9A87AB0158F507B1CDF84F4F293EAD7520C1B8BA62B91FC3935DFE876FE458938C076C8FA7F9CD7190DD3C33982304E093D2BBFB3564B2815B8608335D346CE4D99E2D3A74947B93D14515D479A145145001451450014A292945002514514005145140051451400514514005145140181AD109A821C632832477E6B12FB9B98BDD4E6BABD4B4EFB6857460B2A7033D08F435CF6A3A75EC2F1CAF6FF00BB4C86752081F5AE5A907CCD9E851A90704AFA9507414FCFA77A8C1F996A6C6074AE496E744762CC2011ED53380919CFE150C1D053EE01DA31D68520DD9573B14B100B13C9A89E6C92481D68951B6E4E460679AAAB20DC4B3F51DE9DCD3726CB6E38E4FA7A52471BC8E30BB4F7CD466E23FEF73DEACC534783CB608F5AA516C1A63F728382A188EE6A09449B738C96FCE9B27D97EFE589FF007A9C2E63098FCB34DC243507B91C45C939247D0D5A490AB28CFE354DAE602321B07D29D14A92B80A6A354368BD38257CD4E5D7F5A9A19FCC881031EC6848999001D31447179701DDCF3DA8E633BA6AC46CD938F5A72FDE3DE88937483FD919A338622927EF112D8B36D6F1CB7702EC041619E3F1AE9AB9DD2D8A6A51A9E7208FD2BA2AEFA0BDD38B177E7498514515B1CA145145001451450014A2929450025145140051451400514514005145140051451400541789E658CE9D731B7F2A9E8A011E7F9F9B8EB572325B150DE43F67BF9A2C7DC738CFA76A58240C40CF23A8AF2E71B33D783BC6E5B806D18F7AB650B019AAA061855E8CFC9C524852672FE287D422457B5E235E5801D6AADB68D7F73134BF6E5703691B57AE7AFE55D2DF0EA48C8C60E7D2B9C669F4E95CDB48446DCED3574F9766691E669723B337A3F0920B8883DC48F191CF6E6AEC1E1784DCC8BBA50A318F98F354ECFC4EB3BC21D3CAC0C12790C7EBDABA3B6BB6688CADB7040C6C39AE9518F439AA55C44349192DE19B737423DD273CFDEE31531F0C59A5C20F2CB260E77126B504F9973B0F03AD51D575836908749225653CAC8092C3D0629D910ABD693514CA177E18B4304DB536313F2107A570DA86997367AC35B59DE3C8CC385EA14D74979E24BA9ACCC512E1D9B265C6D38CFA547A3DA6C2D7329DD2B9FBC6B19B8A3B29C6B4173547F2356C2D9EDED63576DD26D0093DCD589942C6062A44E82A2B87CE7DAB07B195EEC860036C8C7D71459422E6F16324856EA475C5337058B1EBCD5ED0E3DD73249FDD5C7E26AA8C79A689AB2E5836695A6990D9B99159DE4E9B9CF415728A2BD2492D11E74A4E4EF2614514532428A28A0028A28A0029452528A004A28A2800A28A2800A28A2800A28A2800A28A2800A28A28039AF135B18DE3BC45E1BE490FA1EC6B120601F23B8AED7548567D2AEA3619FDD923EA3915E7D04C164C13D3D6B8EBC75B9DD869E9666EAFCCBCF5AB314BB545508240CA79071522B9E45729D0D166750EA7D0D65C96E1B28466B495C15C30CF6A6B202D914D15176461AD83C527AA75C7A569C114B1A1F227703FBB9C7E9569610DD7AD35E0639033C77ADE32B22DD6BAB4861B9D4241CCCEBC609500715464B68F2C6526473F89ABC23988032187B76A992D72727A5539F9046A463B7E06341605DC3B8DAA3A2D6AC2BB48006054ED1AA800520E0F15CF27A932A8E7AB2756C2D57958B71EBD6A4270951310AA49EB506688A66C0DB918AE8749B73058A9618793E66FE9FA5626996BF6FBDC9FF53110CFE84F615D4D76E1A165CCCE5C4CFECA0A28A2BA8E40A28A2800A28A2800A28A2800A51494A280128A28A0028A28A0028A28A0028A28A0028A28A0028A28A0064EBBADE55F5461FA579A5C407EFA1C30EF5E9AC32A47A8AF3ED9918C77C573623A1D78657B95AD2F46423707BE6B4BCC19045645CDB9DDB9090DD8D4715F151B64241E9CD7234759D086CE304559519158305F7EF3048DAA339F5AD7B5B859A3C8239F4A2C3B96D1950F5FAD48D2A1E322A011EF0769A745096E0F03EB571B834B726DC9C6318A0C800EB4184636D46D1ED18269BB92921ACC18F06A189A4676F300001C2FB8A460E24181F281C9A8A7B958863F88F02B268B7648B06404E73C0AA57373B80033ED8EB51CB73B1319F98D3614DC771E49A496A458E97C36BB6CE6E724B8273F4AD9AC8F0F9FF469C7A38FE55AF5E952F811E756569B0A28A2B4330A28A2800A28A2800A28A2800A51494A280128A28A0028A28A0028A28A0028A28A0028A28A0028A2A1BCBB86C6CA6BB9D82C50A1763EC280399F1CF8CA2F0B69DB61DAFA84C0F9687A20FEF1FE9591632F9D04726721D0367EA335E4DE28D62E35AD62EAF2E1B2EFD17B2827803E8057A2784EEBED5E1DB17DD9611053F51C5736236475E13768D9962CF38ED599756BB8671C8F4ADCC6E5E955A6871D338AE53AD9CBCE92A11E8390DDC55BD3B57F298473101B3C62AFCF6CAE318CD62DDE9ED13E42165EA41A6990F4D51D859EA28FC123F3AD486E623800F26BCD2192488E239DA33FDC93A568C1AB5EC6B8F2C330EEA69A9587A33BE69541E587355E796319F9BA7415C87F6DEA2E9810AEEF76A824BBBB646134EAA7D23E48FCE872B8F447437FABC709F2E3F99CF1B456524CE5CC8F9F309FBA0F4AA96D1B48F98D0EE3D647EB8AD6B5B355009EB50D8D216084C982C38EC2B436630288A221B3DAA57C2D24522383C476FA15EDBC17785B7BB72A65FF009E6C3A13EDEB5DA672320E41EF5E25F102E04726991E7EF3393F4C015DAFC35F1136A9A39D3AE1CB5C5A0F9198F2F1F41F974FCABBE8BF711E76257EF19DC514515B180514514005145140051451400528A4A5140094514500145145001451450014514500145148EEB1A1791951072598E00FC68016BC9FC79E2BFED367D3ECE4FF00428DB0CE3FE5AB7F80ED5A3E36F1AA3A3E97A54C19586279D0F07FD953E9EA6BCDA42197A8E7D6901CEDC125AE0E73F3819FA0FF00EBD775F0D2F849677762C7E689F7AFFBADFF00D715C03BE4DD0F4909AD5F06EA8BA6788A2676C473298DF3EFD2B2AAAF166F425CB347B745D3A734AF186078E2A382459143035615782C3F2AE24CF4199CE9863C7D29862126411C8F5AB73A1249039A85305C714EC4B332EB464946E518359ADA2DD21F91C81D706BB48911D7A0AB1F654206467EB4D23367111E8B76EBF3C9B7DEB42D7C3F1A00CE4BB1EE6BA836C00C019A6B461171D0D26868CE8ED123F976E3F0A9634F98E0F3529EB5246BE9516344204DA09A89CE6AC13CD65EAF7F0E9D632DCCCDB52352C4D32E279AFC42BE137896D6D94E45BC596FAB1CFF002029BE17D667D175E1750B0CC6F8656E8CAC3915CA4F7B2EA5AB4F7B2FDF9A4DD8F41D87E55A36AE3FB4255EA4A822BBE9C6D148F2EB4B9A6DA3E94D2757B4D6ACFED16AFD3878CFDE43E87FC6AFD784691AF5DE8B791DDDABE0E00743F75C7A1AF58D1FC63A4EAC91AF9EB6F70C398A538E7D01E86B43237E8A28A60145145001451450014A2929450025145140051451400514557BEBFB4D36DCDC5EDC470443F89CE33F4F5A00B155AF750B4D36033DEDC47047EAE7AFD07535E7FAEFC50DBBA1D1A0F6F3E71FC97FC6BCEB51D56FB529DA7BCB996690F763FE71480F4AD6FE28C30068F4AB6DE738F3A6E9F50BFE35C2EA1E24D4B5B72F7B7724880F11E70B9F6038AC02C40F5278AB200450BE9D7EB400F3212DC9FAD34E09F5A3273FE1428DE4E28039890E2FAE93D4D537CAB706AD6A07CBD5A418E180355A5033C5203D17C11E3500A69DA8BE18E16299BBFB1F7AF4E8A50CBC57CD0A4839AF4AF04F8DFE68F4DD4E5E7858A66EFF00EC9FF1AE6AB4BAA3B68D6BFBB23D464019491F7AA9104B607153F99C0C74A4C073D7E9581D16085BCB6C1EF5A50CA081CD515418C1E0FA1A9150A9E0D589D997DDC01559C9639A728247CC734BD3A0C527A896840D1E0824FE14A3273C53DBDCD4324A154F350CB4C259022939E71F957947C46D6CCCF1E9B1BFCA4EF900F4EC2BB0F12F88A0D26C9E495B2C461133CB1AF17BCBB9350BD96E66399246C9F6F6AD68D3BBB9957A9C91E5EAC2DC61C35685930FED5EBD63AA5180800A9B4F707598C632769AEC479E744AC36E29E92100AB72A6A1604673CF34A0F1914C4741A478BF59D1088E1BB3242BFF002C66F9971FD3F0AEFB48F891A6DE6D8F5089ACE4EEE3E7427F98AF2224B019E48A5538638FAD007D1B6F7305DC2B35B4C9344DD1E36C8A92BE7FD3B59BDD3271359DC490B772A783F51DEBBED17E24872B16AD08F4F3A11FCD7FC2981E854556B2D42CF5287CDB3B88E65EFB4F23EA3A8AB3400528A4A5140094557BCBEB4D3E0335E5C470460672ED8CFD077FC2B88D5BE27DA405A3D2ED8CEDDA59BE55FC0753FA5007A063358DAAF8A747D1C1173788D28FF96317CEFF0090E9F8D790EA9E31D6F562CB35F3A45DE387E45FD3AFE35866407D7DCD203BFD5FE27DE4BB934DB74B64E81DFE773FD07EB5C35F6A577A8CED71773CB34A7BC8C4FF00FAAAAE79CF34BB7D7AF5C668018DC1CF3ED4C2C718E2A6231C541236073D3DA9804403CB93C85AB180467144516D8957B9EB52140383EBDA9011E4820D390F5EF4D3F4A72F0076E7AD3039AD7E331DFC72606186335473915B7E248F75BA3839DA7358719040A402ED04533186E73528EB4D71C5033BDF08F8E9AD82586AB21687858A76EABECDEDEF5E9D0CCB22875604119041CE457CE238AEAFC2DE32B8D15D6DEE0B4D624F4EAD1FBAFF0085615297589D54ABF491EE11B2BAFCD532A7A1CD62586A905E5BA5C5BCAB2C520CAB29AD14BA0C301856074DBB1780E3A5359F02AAB5D85E335565BC2C719C0A4C39596259B1F2E79AE7BC45E22B6D16C9A5998173C2203CB1AA1E22F16DAE871329224BA23E5881E7F1F415E4DA96A575AADDB5CDDC85DCF41D947A0ABA74DCBD08A95953D16E3F54D56E758BE6BABA7C93F757B20F4155E250324D44064D585C05E2BA924B4381B7277623310BD79A4D224275C8FF00DD34D90D3B4319D710F600D52133AB93B64F3D3EB4C1D31C5492A9CFA1FAD464118EA4D021EB81D4FD3141CF3D7E948A71C8A7F5E707F9D30101E3A54884AF538C5443E623B0EE2941C938CD0068D95FDC59CAB35B4EF14ABD1D1B06BBBD1FE23CABB62D521128FF009EB1E037E23A1FD2BCD94E39C1C83EB4A84EEE01F5CD007BFE9FADE9DAA28369751BB1FF009664E1C7E06B42BE7A8AEA488AF278E841E47D2BA8B1F1A6B105B08C5F160A78F31031C7D4F3401C96A3A85DDFDD34B757124B21272CEC4E2A9E3279A795F9DB8E734D0B8F4CD201BB4038F5A5038F5A7E0000E38F7EB4D0A3A5001B79C76EF9A7E79271903DE8EF8DB8FEB48DC28C1F7A6031987F09FAD44AA659BB155E695DB0BEF4FB6DA611B48627EF7B1A009C201D40A6139CE69E5C0E00E2A2273C2F3400BB739EB4A7E5200E4D359B6FCA0FCDFC8D3118904E39CF5A008354877E9F271CE0D72509E0576D7196818631C57158DB23AFA3114809FB6690F22914F6341A061B734DC62A40334A40C50069E85E23BDD06E7740DBE163FBC858FCADF4F43EF5EBDA26B567AE588B9B490F1C3C7FC487D0D78601CE6AD58EA779A45D19ECA53148CBB4FA11EF594E9A96A8DA95671D1EC7B95DDFDB58C465BAB88E251FC523015C1F887C7E8375BE93F331E0CEC381F415C8DA69FACF8AF50710CCB7572ABBFCB7994311FEC8279FC2A8CB6EF04EF14A312236D61E84528D14B5654F10DE911B2CB2DCCAD34CED248C72598E49A455C9A52B838A78E0715AD8E76C5D985E3AD0A7029493D0D340E4E78A00639C8AB1A0A13AA338C12077AAED57BC3F9FB5CDF85342674B229607A54382B8CF03D2AC331278E83F5A8D86E3D00EF4C045C0C8E9ED4A3078C9C7D690F3DB38A453EF8FC2801AC304B7AD3C13C1E31EF43ED452EE7FFAF446498F0463B8E6801C011DFA76A7024F503EB9A400B2F2C73DE973C8C76F5A600783CD5AB771E59C9E73E95588E84F39F6A9635F94E01C669010151BC9C9EA69303271CE3BD3E4FF005878C60D373B718EB9EB400846072700D03AF3CFB52B0C9A5238DDC73C50034E7B6334D7C91D31CFA53BD7814C276FCB9FA8A0444E85B8C702A9CA92452F99136D6EFE87EB578B82085E49ED4C16ECE4971B47EB40C8E0BE49DB6C8BE5C9E98E0FD2ACFDE3F2F029C96D146095500F73D4D03D01C50044460F149820E31C1A7B0DC4E3814CCF1C75068026C62220F5C57177236DF4C3FDA26BB55CB752335C86A6BB354947AE08A1810A9E29D4D51C53C5200CE0D3B19EB49DEA7B5B59AF2EA2B5B7469269582A2A8C924D004124B15BED79559D370CAA9C16F500D76E60F08F8CECE38F4EB74D37548D00007064FF007933F31F7539F6ABF73F0F6CA1D323B7D76DA6B19C1222D5AD2433C2D9ED2276FC307DAB87D7FC19AB786CC77132A4F6321FDCDFDAB6E89FD391F74FB1C1A1810EB1E1DD5FC38EB3CF62A210DF25DC0C5933F51F74FB1C1AB177E29BBD7EDE34D4EDA396EE20156F106D91C7A3FF0078FBF5AEA7C21E319622B61AF3FDA2D241B3ED122EF641E920FF00968BF5E4763573C59E04B7D3617D6348402D061A7815B70881E8E87BC67F4A4981E7FC30F7A403079A8DEE10DD6DE81BA7D6A43CB7BFA5318A4934DC734E1C76A0F5E280227E957BC387FD22E0919C11546438539ABFE1AFF59367B9142133A4241FE1C7A5386DE724629A78207A0CD1C6C231DFB5301E7681918FA546ECA8A18E001D4D3B04F7E00CD38283C7502988CF25AE640EC708BF747F5AB6140DA41A468003B97AFA53C71C1EB40C78072401C9F5A41EFD0D286E8476EE69AD8248273E94002918273CD5A831B09C1E4F6AAC09CE7F954D1394523DFD280227F99C8F7CE6A323E61EE6A4707CC3EB9ED4D66032768E29084E7248E94A464918E075A14719FC69369C1386FF001A603791D8FD7AD4172E5636DA7E603AD4CD9E80F1EF50CA01041E9DE8027B765F2D766002323DEA5EE723B67154AC0E6231FF00CF3623FC2AF01D0AE2801802AE79C64669833D0726A5DBB739C533A9A008882783834D00027207E34E627A74151A8049EB8F6A432CA9C6707A7A5727AEAECD490FF796BA98BDFA0F5AE73C509B25865039068623354F14F14C4C15C8E98CD380E47AD218F5F7AB7A5EADA769BAAC7F6F4BB2A4644B6920592139E187AFD38AA6D88D0B9E83F53E95962D24B9B96D873331C853FC5EC3DE803E8AD1BC5727D83ED32CE9ACE92DF2BDEC0BFBC8FDA68CF5FC7F3AD88F45B596DDEF3427866B2BA189EC5BE6B79C77001FBADEC79F4AF9B346D6752F0FEA02EB4FB892DEE17861D98775653C11EC6BDAFC09E28B2D76E0C9A704B0D5587FA56984FEE6E40EAF17A1EF8EA3B509EA339FF17F82D7458CEA9A6A3FF67B361E26E5AD98F63EABE869FE03F16E66FEC1BCC488EAC2D83F46047CD09FF658671E86BD635158EF2CE46110994A149A16FF00968BDD4FB8F5AF9BFC5FA5CBE15F1029B5998DBB91716530EBB73C7E208C1FA5262454F18E93FD83E269ECE125AD89135BB1EF1B723F2E9F8555B39FCD8C17FBE3EF7BD69F8C7598F5FD52DAE23006D814311D99BE623F024D62A298B6BAF51DBD685B0CD23EB8A43C669A8E2440C0F07A539A98114C32BC77AD1F0E1C4D3301E959B3B6067D0715A7E1A18926CF6C53423A323058F7C518C8C91CD2838EF9CF34E61C6473EB40840ADB724D19EA470691D84519627E526A38EE637182E37771D29812FF00C0BDA9B83CE453B8EDF8D200318A0069C28EF4BF771807DE9922E5003EB5230F90F3C50319B8EFE01E956603FBBEBDEAB36401F313562023CBFBB9E680226FBCDC73BBA537664E4FD49A7BF32301EB4857FBBD7340814718C72280C40E690E71D7927AD213C633400D3B8609A8A4C7271D7F954A4823FF00AD4C2BFBBCE68029DB1F2EF4AF389173D7B8AD34E87273E959736E8E58A4C7DD6F4ED5A48C3B66801EC3907B9EB4C619241CE4F6A5E7A9E39A46E79CD0042CBCEDC8A4C90411DBB629597E6240F6CD20E09CF1DF34864919E08C561F899736E9EA1AB701F907F4ACBF10A03A7B1C64820D0C47356A7E4C1EDC558C1C8C753D2A9C1F7F6FF7B8AB723145F2C6379E0FB0A432299B7B051F717F53EB558AFEF1707073C1F4AB2DF2AD57670A771ED401D55868C3C656412C87FC4E605DD264610A0E3E76EC7D0F7E95662F00F89746BC59844AB3429E7978A603C90A32599891B715E9DF0E3458347F0B5BCB082D737C05C3BB8DBDB8273D140E99FAD721E3FF00170D5125D1F4B90FF6786FDFCE3ADD30FF00D90761DFAD16B01BDE0FF88B17885DE19891A9C3117940181728BD580ECE3AFBD711F142E6DEE6EE0B78195E32FF006984AF40AE3E603DB2335CFF00867C3F75AD7886382D9DA1863FDE5CDC02408A21F78923D4718EE4E2B47C796B0597898410487CBF215920239B75249543EF8C1FC6A7A8CE6228BA7153B28C6295050E302A84471B7932609F909FC8FAD5F1C8CD51601D0D49693160626E5D4617DC50319390C5547739FC2B6BC383E6B8F6C561B7339EF8E056EF8748F3E6EDC8A6846F76E3D297B6724629C7AF07826800007DB8E9408301D406C1F6AAD25946C72B953E839156D07209A42C7711C7E069814A34B8B77009CC6474CE7FFD5568005471D7BD48DCB6D3E9C7151B282DDB8F7A006CA732A28E78A776C1CE4531FF00D7E31C8C54A41241A0631BE5233DEA6B70BE59C8EFDEA171EC01A920E10F04F3400A48DE727B9E94600E074A523058E463A5260123BD0211B1C01CD31BAF00600A71197E69B8DC4F031D28019C8E08C5249D38E7F0A7E7AD46C7E6A00AD7281D1947A75A9ADDC3DBA311CE39A57518F5A82DBE5DF1E790723E86802E9248CF149D88A542186D34857D0FE740119DA3193C8F4A69EBDB03D2A42AB9FAF7A43C76EA3E94862A803E53DCD53D690BE972F6C0AB8A7902A2BF8F759CAA73F74D023854FBD56630076AACA306AC4679A43125E168D32C5F55D6ACEC1012679557819EA69B3B002BB4D363B7F08E8B0EA1E403ADDD022191CFCD0E47551DB0A7AF5C91401D678F3C522D206F0F6992004288EF2643D80C794BEC3BFE55C3691A3DDEBDA8C5A7D8C7BA693A93C2A2F7663D80A8E1B5B8D42F22B6B789E6B899C2A22F2598D7B069D61A57C3FF000BCF7178EB230C7DAA543CDCCBD44319FEE8EE7F1A00CAD565D23E1C7851520559A490E61571F35ECC3FE5A3FF00D335EC3FFAF5E2134F737F753DFDCBBCB2CB2169256EEC79AD2F156BF7BE24D665D46F9C176F95117EEC483A228F415D55A78705AF80B51374A5654B64BA718E56466CA29FF80E0FE353D467131F4A7B2FCA69919E01A95CE56A845743DA865039EF401F352C9400D8979F6ADFF0EE049393D320561C43835BDE1D1CCE7FDAA680DD23278071480F5F989A7E7E5383CD346319FE54085191CFEA29C76F427F1C528E3A372074C500E7B649E6980CC64920D20C93806970A48CF514050791F8500349CCAE47AF6A9368DA33DBAD44BC8CE39CFE15229E79C508631B19C63247AD4B0E761E40E6A27C1239E4FAD490950878CF3D85021E48F9BA75A418DDD3927348E36330A07098E33FCA8108D819E73ED51139240E062A46C6083CE2A238CFB1340C71238A6E3739078ED4A70070793403C640CD0046E00380411F4AAA0EDBBF665C67DEAE119C6073DCD54B8182AE3A86CD005A46E29DC670BDF9A895883CF3F5A99946CDD9E4D003581C8E7EB4D6E00C76E94EE0AE29A4E78E82800CED26A4917CC84E0678EF50F7F71D7356010613CE7B62803CF241B6575F4635345CF4A4BE5297B3A91D1CD1074A919A9A0E9E351D7ADE2750D1A1F31C762179C1F6CE3F5A8F58D58EADAF3488E5A08FF7711FEF0CF2DF89C9FCA8B5D44596997B1404FDAAEB1133FF00722EA40F763C7D07BD75DF0CBC286E6F63D6AE60591124D9650B8F96494725DBFD841C9F7C500773E0BF0E47E1DD31F53D49960BD6877CD230FF008F3848E9FF005D1BD3A8CE2BCFFC6BE2697C45A80601A1B1B7CA5AC19E157FBC7D58F735B9E33F152EAD31D2B4F99A4D3E172D2CDDEEA5EEE7FD91D87E35CE68FE1EB9F126B096301F2D00DF3CCC3E58631D58FF004F534010F843C3D1DF5CCBACEA3116D2EC181F2CFF00CBCCDFC310F5F56F6FAD7A6EA3666DB47B6B5D4486B9D46F04F780F655F9DC7D00551F9D6CE95A3DA2A5BB451AC1A4E9C08B4493A330FBD33FA9EE7DF02B86F1DEBE1747BCD4C92AD7AAD61A6C6C7E61167F7B29FAF4CFAB1F4A9921A3CACDC2DC4D24C8A111DD9828E8A09C81521E56B3ED8E015F4ABE394AA02303E6A24E4D0A79A6B1CB714089A3C05ADDF0E6364FC7F17F4AC3C6D415BBE1B03C894F425C8CE69A036CE0F6FA8A41F7BDA9CD95071D33C1A0025FD47AD0217DF278A3E600B0C71C53874E7A534819E99CF4A6023678CFA7A51850BDB03D0D047CE383F4CD237DC73EDD31400C5C989724FD314E52320FAD391405C1FAD38631C0C9A008D946086C023A54909DA8402719F5A6363A93D78E29D1AE54F03AD003DF3E6373819A69CB71C648E6948667386EFDA9A46E272706810D6CF7C1A839278FC2A7700707A8AAA3396CFAD0344E010B818E98E690718073CF7A45CB70453F8CF4C6D1400C0700E1AA3957CC47E3B75A9362E3D0FA5211CE07208E68020B7625149EBD2AC8E4118E2ABC6A04AEA7D7233DAACAF5DB9E9400D38048E9CFA534F390339A7F439033EF48E39CD0033EF718A9A305931C0CD440F3935221C92391480E27594F2F559C0E84E6A0B7FB9577C40BB7546F75154A004C3C024F603BD219AFE18D0A4D7F54FB386F2E05CC97136388A31D4FD7B0F52457A1F8C35C8F42D31742D3904171342239114F36B6DD562FF7DBAB7D7DE974D8AD7C07E0D5B899524BC720953FF2DEE7190BFEE479C9F56AF3B334F7D772DCDCC8D2CF3397776E4B313480D1D22C6E350BC86CED2232CF336C4403A9AF6FD0BC356FA4E9BFD9B036EC90F7D72A3995FB2AFB0E807E359BE07F0A1D0AC84B3A0FED6BA8F2FBB8FB34479DBEC48E4FA74AEBE666B78520B407CE7E221DC67AB9F73DBD055A4230FC437313C52D81996D74FB64F32FE71F7628D7A20F5F4F7635F3C78B7C40FE24D71EEFCBF26D63510DA41DA2887DD1F5EE7DC9AED3E2378A23BACE83A5CBBACA19375CCEA7FE3E651FFB2AF6F5EB5CEF81BC2BFF000926BC0DCA37F665A625BB61FC433F2C63DD8F1F4C9A8651B29E15165F08DEFE6091DCCD2A5E3B38F98467E48D07B9C96C7B8AE290FCB8AEF7E2EF88775D41E1D81940B7713DE04FBBE6E30B18F645E3EA6BCFE13914201A38269ABCBFE34BD18D2C3CB5311331C0ADEF0E28FB2B9238DE6B9F73D6BA2F0E7FC79F4FE2269A066CE4AAE07AD19DAD8007F8D07248C77ED40C9C93802810E0CD827B76E28182016EA29491B7078E7AE681C7BD30180E5BF1FC6924394E4F538E6970093914C906022E3BF7A009768C06639FA5203B72DB4E29FD62E3191E948589EA7B7A50046572CC1781EF52C0008F9F5F5A898ED20E39FAD4F06761FAD3026F29031C2F7A1E240385EB451480AF2C69B41C738F5A8C449FDDEF451400F4893238EDEB4796BB18E3B8EF451400EF2D3D283126FE9FAD145022BBC482E970BDAA648931D3F5A28A062BC4983F2F6A431271C7EB451400C1121DD91D3DE9E235DDD28A2901CC789608FF00B414EDE76FA9AA365122AC6CA3043020E7DE8A290CECBC7A4BF8896D589305B5B44B0A678405431FCC9249AB5F0D6C2D6E3C5B69E742B208D1E550DC80CA09071DF07D68A2840CF6BD3544912BBFCCD2CD8727F88019C1FC6B9EF175D4F0783F55BA8A5649DD9223203CED638600F6C8A28AB7D40F03B8823C9F97F5AF6CF03DAC1A7F81B4E92D6258DDEDEE2ED88E774CB9018E7AE0018ED451598CF9FAE07DA6692798B492C8C5DDD9892C4F249AB56D0C7B47CBDBD68A2840C6B431E4FCBFAD3E1823DDF77F5A28A6215A18F27E5FD6BA4F0FC118B0FBBFC47BFBD1450819AFE5261BE5EFEB48224C0F97F5A28A62078D42A8C7BF5A72C498FBB4514C00429B54EDE49E6A19517ED0463A5145004BE5260F1FAD46635C118FD68A2980890C67AAF7F5AB1046BB5B8FE2A28A00FFD9";
InputStream is = new ByteArrayInputStream(hexStringToByteArray(photo.substring(2)));
FileOutputStream out = new FileOutputStream("/home/bmartel/test.jpg");
byte[] data = new byte[1024];
int readBytes = 0;
while ((readBytes = is.read(data)) > 0) {
out.write(data, 0, readBytes);
}
out.flush();
out.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
With hexStringToByteArray picked here :
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i + 1), 16));
System.out.print(data[i / 2] & 0xFF);
System.out.print(" ");
}
return data;
}
For Base64 data use :
Base64 base64 = new Base64();
byte[] data = base64.decode(photo);
I currently use the following to read a bluetooth inputstream and save it as a file. It works well with small files but then with larger files its creating a large byte array first. Whats the most efficient way of doing this AND making sure that it reads the only the length specified, no more, no less?
public void getAndWrite(InputStream is, long length, String filename)
throws IOException {
// Create the byte array to hold the data
byte[] bytes = new byte[(int) length];
// Read in the bytes
int offset = 0;
int numRead = 0;
while (offset < bytes.length
&& (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
offset += numRead;
}
// Ensure all the bytes have been read in
if (offset < bytes.length) {
throw new IOException("Could not completely read stream ");
}
// Write the byte array to file
FileOutputStream fos = null;
try {
fos = mContext.openFileOutput(filename, Context.MODE_PRIVATE);
} catch (FileNotFoundException e) {
Log.e(TAG, "Problem finding internal storage", e);
}
try {
fos.write(bytes);
fos.close();
} catch (IOException e) {
Log.e(TAG, "Problem writing file", e);
}
}
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int remaining = length;
int read = 0;
while (remaining > 0
&& (read = in.read(buffer, 0, Math.min(remaining, bufferSize))) >= 0) {
out.write(buffer, 0, read);
remaining -= read;
}
Note that the above makes sure you don't write more that length bytes. But it doesn't make sure you write exactly length bytes. I don't see how you could do this without reading length bytes in memory, or reading length bytes and writing to a temp file, then writing the temp file to the final destination.