I am making a 2D game in Java for the PC and this game has data like sprites, sound effects, music, and text.
The problem is that I need to store it somehow.
For now I need to store my sprites in an encrypted format and I need my Java game To decrypt and load the encrypted images To bufferedimages to display them on my game.
I don't want to encapsulate everything into a single executable .jar or .exe file.
I need to make my images(Resources,Spritesheets) encrypted and secure because I don't want to the player to interfere with them or use them.
I can't use ZIP files even encrypted or protected ones by using some
sort of a Java library because Java have to export them first on the disc
before it uses it
I have searched many forums and I can't find a clear answer.
Depending upon what sort of encryption you had in mind - you can use ImageIO to write/read the image to Output and Input Streams, taking the resulting bytes and decrypt/encrypt.
To save the image, use ImageIO to write the Image to an OutputStream (for example a ByteArrayOutputStream ). From the bytes written, you can encrypt, and then save
ByteArrayOutputStream os = null;
OutputStream fos = null;
try{
os = new ByteArrayOutputStream();
ImageIO.write(image, "jpg", os);
byte[] bytes = os.toByteArray();
encrypt(bytes);
fos = new FileOutputStream(outputfile);
fos.write(bytes);
}catch(IOException e){
e.printStackTrace();
}finally{
if ( fos != null ){try{fos.close();}catch(Exception e){}}
if ( os != null ){try{os.close();}catch(Exception e){}}//no effect, but hear for sanity's sake
}
To read the and decrypt, just read the file as bytes, decrypt the bytes, then send the byte stream to ImageIO
InputStream is = null;
ByteArrayOutputStream os = null;
ByteArrayInputStream input = null;
try{
is = new FileInputStream(inputFile);
os = new ByteArrayOutputStream ();
byte[] buffer = new byte[500];
int len = -1;
while ( ( len = is.read(buffer) ) != -1 ){
os.write(buffer, 0, len);
}
byte[] fileBytes = os.toByteArray();
decrypt(fileBytes);
input = new ByteArrayInputStream(fileBytes);
Image image = ImageIO.read(input);
}catch(IOException io){
io.printStackTrace();
}finally{
if ( is != null ){try{is.close();}catch(Exception e){}}
if ( os != null ){try{os.close();}catch(Exception e){}}
if ( input != null ){try{input.close();}catch(Exception e){}}
}
The type of encryption you use is your choice. You can use a simple Cipher to encrypt the byte array using a bitwise exclusive or (^)
for ( int i = 0; i < bytes.length; i++ ){
bytes[i] = (byte)(bytes[i] ^ 123);
}
Or more fancy encryption using a Cipher
Note that for animated gif's, you may need to search for a way to save the frames of the gif (for instance see this)
Related
I want to use java(httpurlconnection class) to download a pdf file,but have some thing puzzle,the core code is:
BufferedInputStream inputStream = new BufferedInputStream(httpConn.getInputStream());
OutputStream output = new FileOutputStream("F:/httpclient-tutorial.pdf");
byte[] infoBytes = new byte[BUFFER];
while(inputStream.read(infoBytes) != -1){
output.write(infoBytes, 0, BUFFER);
}
Question:when the BUFFER is 1024,get the pdf file is larger than real one;but the BUFFER is 8,then it's ok. I don't know why it is? Has anyone know about that?
You're unconditionally writing out the whole of the buffer on each iteration. You should only write out as many bytes as you've just read:
int bytesRead;
while((bytesRead = inputStream.read(infoBytes)) != -1){
output.write(infoBytes, 0, bytesRead);
}
What is the efficient way to encode and decode an audio file in android
I have tried the Base64 as below but after decoding the file size get increased.
Encode
ByteArrayOutputStream objByteArrayOS = new ByteArrayOutputStream();
File file = new File(path);
FileInputStream objFileIS;
try {
objFileIS = new FileInputStream(file);
byte[] byteBufferString = new byte[1024];
for (int readNum; (readNum = objFileIS.read(byteBufferString)) != -1;) {
objByteArrayOS.write(byteBufferString, 0, readNum);
System.out.println("read " + readNum + " bytes,");
byte[] bytes = FileUtils.readFileToByteArray(file);
strAttachmentCoded = Base64.encodeToString(bytes,
Base64.DEFAULT);
Decode
byte[] decoded = Base64.decode(strAttachmentCoded,
Base64.DEFAULT);
// byte[] decoded1 = Base64.decode(byteBinaryData1, 0);
File file1 = new File(pathAudio);
FileOutputStream os = new FileOutputStream(file1, true);
os.write(decoded);
os.close();
i want audio in String format to send to server and retrieve the same as per the user requirement.
wikipedia:base64 (rfc3548) is the right method to choose I would think. It is most common now I think having taken over from wikipedia:uuencoding.
To answer the question . . .
You could add some padding. The wikipedia article on base64 gives a good example of padding.
Or you could add a header to your audio string including length. The header could also include other control data so it may be something you want to include anyway.
I am using the code provided by this accepted answer to send a list of files over a socket in Java. My goal is to be receiving a list of images. What I would like to do is read these images directly into memory as BufferedImages before writing them to disk. However, my first attempts, which was to use ImageIO.read(bis) (again, see the attached question) failed, as it attempted to continue reading beyond the end of the first image file.
My current idea is to write the data from the socket to a new output stream, then read that stream from an intput stream that is passed to ImageIO.read(). This way, I can write it byte by byte as the program is currently doing, but send it to the BufferedImage rather than the file. however I'm not sure how to link the output stream to an input stream.
Can anyone recommend simple edits to the code above, or provide another method of doing this?
In order to read the image before writing it to disk, you'll need to use a ByteArrayInputStream. http://docs.oracle.com/javase/6/docs/api/java/io/ByteArrayInputStream.html
Basically, it creates a inputstream that reads from a specified byte array. So, you'd read the image length, then it's name, then the length-amount of bytes, create the ByteArrayInputStream, and pass it to ImageIO.read
Example snippet:
long fileLength = dis.readLong();
String fileName = dis.readUTF();
byte[] bytes = new byte[fileLength];
dis.readFully(bytes);
BufferedImage bimage = ImageIO.read(new ByteArrayInputStream(bytes));
Or using the code from the other answer you cited:
String dirPath = ...;
ServerSocket serverSocket = ...;
Socket socket = serverSocket.accept();
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
DataInputStream dis = new DataInputStream(bis);
int filesCount = dis.readInt();
File[] files = new File[filesCount];
for(int i = 0; i < filesCount; i++)
{
long fileLength = dis.readLong();
String fileName = dis.readUTF();
byte[] bytes = new byte[fileLength];
dis.readFully(bytes);
BufferedImage bimage = ImageIO.read(new ByteArrayInputStream(bytes));
//do some shit with your bufferedimage or whatever
files[i] = new File(dirPath + "/" + fileName);
FileOutputStream fos = new FileOutputStream(files[i]);
BufferedOutputStream bos = new BufferedOutputStream(fos);
bos.write(bytes, 0, fileLength);
bos.close();
}
dis.close();
I have a BufferedImage object of a jpeg which needs to be streamed as servlet response.
The existing code streams the jpeg using JPEGImageEncoder which looks like this :
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(resp.getOutputStream());
resp.reset();
resp.setContentType("image/jpg");
resp.setHeader("Content-disposition", "inline;filename=xyz.jpg");
JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(image);
param.setQuality(jpegQuality, false);
encoder.setJPEGEncodeParam(param);
encoder.encode(image);
I have noticed that this is resulting in the file size of the streamed jpeg to be tripled , unable to figure why.So I have tried using ImageIO to stream the jpeg
ImageIO.write(image, "jpg", out);
This works just fine, I am unable to decide why my predecessor has gone with the choice of JPEGImageEncoder and was wondering what issues would arise if I change to using ImageIO, I have compared both jpegs and couldn't really spot differences. Any thoughts?
To be clear, you've already a concrete JPEG image somewhere on disk or in database and you just need to send it unmodified to the client? There's then indeed absolutely no reason to use JPEGImageEncoder (and ImageIO).
Just stream it unmodified to the response body.
E.g.
File file = new File("/path/to/image.jpg");
response.setContentType("image/jpeg");
response.setHeader("Content-Length", String.valueOf(file.length()));
InputStream input = new FileInputStream(file);
OutputStream output = response.getOutputStream();
byte[] buffer = new byte[8192];
try {
for (int length = 0; (length = input.read(buffer)) > 0;) {
output.write(buffer, 0, length);
}
}
finally {
try { input.close(); } catch (IOException ignore) {}
try { output.close(); } catch (IOException ignore) {}
}
You see the mistake of unnecessarily using JPEGImageEncoder (and ImageIO) to stream image files often back in code of starters who are ignorant about the nature of bits and bytes. Those tools are only useful if you want to convert between JPEG and a different image format, or want to manipulate (crop, skew, rotate, resize, etc) it.
I have a FileInputStream created using Context.openFileInput(). I now want to convert the file into a byte array.
Unfortunately, I can't determine the size of the byte array required for FileInputStream.read(byte[]). The available() method doesn't work, and I can't create a File to check it's length using the specific pathname, probably because the path is inaccessible to non-root users.
I read about ByteArrayOutputStream, and it seems to dynamically adjust the byte array size to fit, but I can't get how to read from the FileInputStream to write to the ByteArrayOutputStream.
This should work.
InputStream is = Context.openFileInput(someFileName);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
while ((int bytesRead = is.read(b)) != -1) {
bos.write(b, 0, bytesRead);
}
byte[] bytes = bos.toByteArray();
This is the easiest way
FileInputStream fis = openFileInput(fileName);
byte[] buffer = new byte[(int) fis.getChannel().size()];
fis.read(buffer);
You can pre-allocate the byte array using
int size = context.getFileStreamPath(filename).length();
This way, you will avoid allocating memory chunks every time your ByteArrayOutputStream fills up.
For the method to work on any device and aplication you just need to replace:
InputStream is = Context.getContentResolver().openInputStream(yourFileURi);
This way you can encode external files as well.