I built a classic Hoffman code, with encoder and decoder. I noticed that I had a problem, I use code in "bitset", to compress the input file. But the "bitset" - does not decode all the files I send to, for example when I send a txt file, it works great, but when I send other files like BMP. It doesn't work.
Before I used bitset - the code worked - but without any compression - so I'm afraid the problem is with bitset.
The decoder I built is:
public void Decompress(String[] input_names, String[] output_names) {
HuffmanVerticle tree = new HuffmanVerticle();
tree = readTreeFile(output_names);
restoreInput(tree, output_names, input_names);
}
public static void restoreInput(HuffmanVerticle tree, String[] binary_names, String[] original_names) {
BitSet huffmanCodeBit;
try {
FileOutputStream to_original = new FileOutputStream(original_names[0]);
FileInputStream binary = new FileInputStream(binary_names[0]);
ObjectInputStream s = new ObjectInputStream(binary);
huffmanCodeBit = (BitSet) s.readObject();
System.out.println(huffmanCodeBit.toString());
int index = 0;
while(huffmanCodeBit.length() > index)
{
HuffmanVerticle tmp = tree;
while (!tmp.isNullTree())
{
boolean bit = huffmanCodeBit.get(index);
index++;
System.out.println(bit);
if (!bit)
tmp = tmp.left;
else
tmp = tmp.right;
}
to_original.write(tmp.character);
}
binary.close();
to_original.close();
} catch (Exception e) {
e.printStackTrace();
}
}
What am I missing here? Why doesn't the code work for certain files? I'm trying to run the code on some files but it doesn't work, the files that come back don't work.
The code does not work for bmp files at all, even after half an hour, for example txt files, it runs very fast.
Thank for your help.
I have this DownloadFile.java and downloads the file as it should:
import java.io.*;
import java.net.URL;
public class DownloadFile {
public static void main(String[] args) throws IOException {
String fileName = "setup.exe";
// The file that will be saved on your computer
URL link = new URL("http://onlinebackup.elgiganten.se/software/elgiganten/setup.exe");
// The file that you want to download
// Code to download
InputStream in = new BufferedInputStream(link.openStream());
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int n = 0;
while (-1 != (n = in.read(buf))) {
out.write(buf, 0, n);
}
out.close();
in.close();
byte[] response = out.toByteArray();
FileOutputStream fos = new FileOutputStream(fileName);
fos.write(response);
fos.close();
// End download code
System.out.println("Finished");
}
}
I want to execute this from a mouse event in Gui.java.
private void jLabel17MouseClicked(java.awt.event.MouseEvent evt){
}
How do I do this?
Your current method is a static method, which is fine, but all the data that it extracts is held tightly within the main method, preventing other classes from using it, but fortunately this can be corrected.
My suggestion:
re-write your DownloadFile code so that it is does not simply a static main method, but rather a method that can be called by other classes easily, and that returns the data from the file of interest. This way outside classes can call the method and then receive the data that the method extracted.
Give it a String parameter that will allow the calling code to pass in the URL address.
Give it a File parameter for the file that it should write data to.
Consider having it return data (a byte array?), if this data will be needed by the calling program.
Or if it does not need to return data, perhaps it could return boolean to indicate if the download was successful or not.
Make sure that your method throws all exceptions (such as IO and URL excptions) that it needs to throw.
Also, if this is to be called by a Swing GUI, be sure to call this type of code in a background thread, such as in a SwingWorker, so that this code does not tie up the Swing event thread, rendering your GUI frozen for a time.
I'm writing an endpoint that dynamically generates a GIF file. I'll go from the ground up.
I have a class named Function that works like an abstract class and I have several classes, in this example AddFunction, that represent small chunks of functionality. In this case, the AddFunction adds some numbers together. When the end point is hit, the ID of the AddFunction is passed to it (it could be any, in this example it's the add function). The code in the controller is as follows:
/**
* Returns the image for a function
*/
#RequestMapping(value = "/function/{functionId}/image.gif", produces = "image/gif")
public void getImage(#PathVariable(value = "functionId") String functionId, HttpServletResponse response) throws IOException {
Function function = functionService.getFunction(Integer.valueOf(functionId));
Logger logger = Logger.getLogger(FunctionController.class);
ServletOutputStream servOut = response.getOutputStream();
// Uses default values if you pass in nulls.
function.getImage(servOut, null, null);
servOut.flush();
servOut.close();
}
First, the Function is found by it's ID. I have checked, and the correct function is being found. This code is in need of some validation (for example checking the id passed in is a valid number) but I'll get to that later. I then grab the servlet output stream and pass it to the getImage methods of the function. This method generates the GIF that describes the function. This code looks like this:
public void getImage(OutputStream out, String staticContent, String changedContent) throws IOException {
String[] data = {"2", "+", "2", "=", "4"};
Logger logger = Logger.getLogger(AddFunction.class);
logger.info("Getting the add image.");
ImageUtils.writeSequenceToImage(ImageIO.createImageOutputStream(out), data, 5, Constants.IMAGE_HEIGHT / 2);
}
As you can see, it ignores the values and it is using stock data at the moment. It creates an array of values. Each of these values which appear in each frame of the GIF. So what I do is I take the ServletOutputStream and I use the ImageIO.createImageOutputStream to wrap that with an ImageOutputStream object. This is when passed into the writeSequenceToImage method in my own ImageUtils class. The last two values are coordinates for where to write from. In this case, the vertical middle of the image, on the far left. The code for the writeSequenceToImage method is as follows:
public static void writeSequenceToImage(ImageOutputStream out, String[] contentList, int x, int y) throws IOException {
StringBuilder dataBuilder = new StringBuilder();
Test test = new Test(out, BufferedImage.TYPE_INT_RGB, 500, true);
Logger logger = Logger.getLogger(ImageUtils.class);
logger.info("Writing sequence to image.");
for (String content : contentList) {
dataBuilder.append(content);
logger.info("writing " + dataBuilder.toString() + " to the gif.");
test.writeToSequence(generateAndWriteToImage(dataBuilder.toString(), x, y));
}
}
In this code, I am using the class Test (temporary name) which contains code that writes data to a GIF file. All I'm doing here is looping through and adding each value to a frame in the GIF. The code for class Test can be found here. What I do is I build up the String, so in our example the logs would output:
2014-12-31 14:37:15 INFO ImageUtils:48 - Writing sequence to image.
2014-12-31 14:37:15 INFO ImageUtils:53 - writing 2 to the gif.
2014-12-31 14:37:15 INFO ImageUtils:53 - writing 2+ to the gif.
2014-12-31 14:37:15 INFO ImageUtils:53 - writing 2+2 to the gif.
2014-12-31 14:37:15 INFO ImageUtils:53 - writing 2+2= to the gif.
2014-12-31 14:37:15 INFO ImageUtils:53 - writing 2+2=4 to the gif.
This will give the appearance in each frame of the GIF of it building up the string. Now, I write this to the GIF and I expect it to be pushed straight into the ServletOutputStream, only when I attempt to reference it with the following HTML:
<div class="panel columns large-12" ng-show="selectedFunction">
<h2>{{selectedFunction.name}}</h2>
<p>{{selectedFunction.description}}</p>
<p>This function expects a {{selectedFunction.expectedParameterType}} as a parameter.</p>
<p>This function will return a {{selectedFunction.expectedReturnType}}</p>
<img src="/autoalgorithm/functions/function/{{selectedFunction.id}}/image.gif" alt="{{selectedFunction.name}}"/>
</div>
I am seeing the following data returning in Chrome:
And I am seeing no image on my page:
What I have tried
I've tried to see the size of what is coming back. To do this, I have replaced the ServletOutputStream with a ByteArrayOutputStream so I can get the size of the data. If I do this, my code looks like this:
/**
* Returns the image for a function
*/
#RequestMapping(value = "/function/{functionId}/image.gif", produces = "image/gif")
public #ResponseBody byte[] getImage(#PathVariable(value = "functionId") String functionId, HttpServletResponse response) throws IOException {
Function function = functionService.getFunction(Integer.valueOf(functionId));
Logger logger = Logger.getLogger(FunctionController.class);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// Uses default values if you pass in nulls.
function.getImage(baos, null, null);
logger.info("The number of bytes returned is " + baos.toByteArray().length);
return baos.toByteArray();
}
And the log outputs:
2014-12-31 15:34:09 INFO FunctionController:85 - The number of bytes returned is 0
So that is telling me that it isn't being written too. So I changed up my approach and refactored the code so I maintained a reference to the ImageOutputStream in my controller. This meant that I had complete control over the object, so now the log outputted:
2014-12-31 15:39:56 INFO FunctionController:85 - The number of bytes returned is 2708
Which was encouraging! And 2KB sounds about right for a very very simple GIF. However, when I check the response from Google, similar story:
Although this time it has a content length, but there is no preview available and the image still is not appearing.
I was wondering if anyone on here had tackled a similar issue? I suspect it is to do with the encoding of the GIF, but ImageIO doesn't support conversion from one stream to another, only from one BufferedImage type to another. So I used the ImageIO.read method to read it into a BufferedImage and used ImageIO.write to write it as a gif onto the ServletOutputStream. This yielded the following error:
java.lang.IllegalArgumentException: image == null!
At this point, I'm stumped. I'm hoping a fresh set of eyes can help me out. Does anyone have any ideas?
As already noted in the comments your question is a little bit unconcise but I'll try to show you how it can work.
First try the following:
#RequestMapping(value = "/function/{functionId}/image.gif", produces = "image/gif")
public void getImage(#PathVariable(value = "functionId") String functionId, HttpServletResponse response) throws IOException {
BufferedImage firstImage = ImageIO.read(new File("/bla.jpg"));
response.setContentType("image/gif"); // this should happen automatically
ImageIO.write(firstImage, "gif", response.getOutputStream());
response.getOutputStream().close();
}
Place some file named bla.jpg in your root directory or change the path to some existing image file (can also be a GIF). Make sure you have at least read access rights.
This should work in any case, regardless if jpg or gif file. If this doesn't work there may be something wrong with your Spring configuration. You should rule that out.
If this is working, you can use your method generateAndWriteToImage() to replace ImageIO.read(new File("/bla.jpg"));. And you should be done.
Now, I don't know what your generateAndWriteToImage() method does but I assume that it creates an instance of BufferedImage, writes some text into the image and returns it.
Something like this:
public static BufferedImage generateAndWriteToImage(String string, int x, int y) {
BufferedImage image = new BufferedImage(x,y,BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
g.setPaintMode();
g.setFont(g.getFont().deriveFont(30f));
g.drawString(string, 100, 100);
g.dispose();
return image;
}
If you create the image with the type BufferedImage.TYPE_INT_RGB this shouldn't cause any problems.
TL;DR Another thing you already found out yourself is that a little refactoring gives you the ability to close the ImageOutputStream.
Assume the following method:
#RequestMapping(value = "/function/{functionId}/image.gif", produces = "image/gif")
public void getImage(#PathVariable(value = "functionId") String functionId, HttpServletResponse response) throws IOException {
Function function = functionService.getFunction(Integer.valueOf(functionId));
ServletOutputStream servOut = response.getOutputStream();
// Uses default values if you pass in nulls.
function.getImage(servOut, null, null);
servOut.flush();
servOut.close();
}
and this method:
public void getImage(OutputStream out, String staticContent, String changedContent) throws IOException {
String[] data = {"2", "+", "2", "=", "4"};
Logger logger = Logger.getLogger(AddFunction.class);
logger.info("Getting the add image.");
ImageUtils.writeSequenceToImage(ImageIO.createImageOutputStream(out), data, 5, Constants.IMAGE_HEIGHT / 2);
}
In the second method, you are creating a local instance of ImageOutputStream with ImageIO.createImageOutputStream(out) (last line).
I guess the main problem is, that you aren't closing this ImageOutputStream, this may result in data not beeing written to any other OutputStream (because of buffering).
To make it work you can refactor your methods to this:
#RequestMapping(value = "/function/{functionId}/image.gif", produces = "image/gif")
public void getImage(#PathVariable(value = "functionId") String functionId, HttpServletResponse response) throws IOException {
Function function = functionService.getFunction(Integer.valueOf(functionId));
ImageOutputStream servOut = ImageIO.createImageOutputStream(response.getOutputStream());
// Uses default values if you pass in nulls.
function.getImage(servOut, null, null);
servOut.close();
}
and this:
public void getImage(ImageOutputStream out, String staticContent, String changedContent) throws IOException {
String[] data = {"2", "+", "2", "=", "4"};
Logger logger = Logger.getLogger(AddFunction.class);
logger.info("Getting the add image.");
ImageUtils.writeSequenceToImage(out, data, 5, Constants.IMAGE_HEIGHT / 2);
}
The same thing applies here for the generateAndWriteToImage() method. If it correctly returns an instance of BufferedImage, this should work (with the refactoring).
I did not try with spring but tried with J2EE instead. Below approach works for me !
private void process(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
String baseServletPath = httpServletRequest.getServletContext().getRealPath("/");
System.out.println("Base Servlet Path :"+baseServletPath);
String relativeInputFilePath = "images/Tulips.gif";
String imageFilePath = baseServletPath + relativeInputFilePath;
File file = new File(imageFilePath);
BufferedImage bufferedImage = null;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try {
bufferedImage = ImageIO.read(file);
ImageIO.write(bufferedImage, "GIF", byteArrayOutputStream);
} catch (IOException e) {
e.printStackTrace();
}
byte[] imageData = byteArrayOutputStream.toByteArray();
String relativeOutFilePath = "images/TulipsOut.gif";
String imageOutFilePath = baseServletPath + relativeOutFilePath;
File fileOut = new File(imageOutFilePath);
FileOutputStream fileOutputStream=null;
try {
fileOutputStream = new FileOutputStream(fileOut);
fileOutputStream.write(imageData);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
httpServletResponse.getOutputStream().write( imageData );
} catch (IOException e) {
e.printStackTrace();
}
}
I have written a Java program to write the ByteArray in to a file. And that resulting ByteArray is a resulting of these three ByteArrays-
First 2 bytes is my schemaId which I have represented it using short data type.
Then next 8 Bytes is my Last Modified Date which I have represented it using long data type.
And remaining bytes can be of variable size which is my actual value for my attributes..
So I have a file now in which first line contains resulting ByteArray which will have all the above bytes as I mentioned above.. Now I need to read that file from C++ program and read the first line which will contain the ByteArray and then split that resulting ByteArray accordingly as I mentioned above such that I am able to extract my schemaId, Last Modified Date and my actual attribute value from it.
I have done all my coding always in Java and I am new to C++... I am able to write a program in C++ to read the file but not sure how should I read that ByteArray in such a way such that I am able to split it as I mentioned above..
Below is my C++ program which is reading the file and printing it out on the console..
int main () {
string line;
//the variable of type ifstream:
ifstream myfile ("bytearrayfile");
//check to see if the file is opened:
if (myfile.is_open())
{
//while there are still lines in the
//file, keep reading:
while (! myfile.eof() )
{
//place the line from myfile into the
//line variable:
getline (myfile,line);
//display the line we gathered:
// and here split the byte array accordingly..
cout << line << endl;
}
//close the stream:
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
Can anyone help me with that? Thanks.
Update
Below is my java code which will write resulting ByteArray into a file and the same file now I need to read it back from c++..
public static void main(String[] args) throws Exception {
String os = "whatever os is";
byte[] avroBinaryValue = os.getBytes();
long lastModifiedDate = 1379811105109L;
short schemaId = 32767;
ByteArrayOutputStream byteOsTest = new ByteArrayOutputStream();
DataOutputStream outTest = new DataOutputStream(byteOsTest);
outTest.writeShort(schemaId);
outTest.writeLong(lastModifiedDate);
outTest.writeInt(avroBinaryValue.length);
outTest.write(avroBinaryValue);
byte[] allWrittenBytesTest = byteOsTest.toByteArray();
DataInputStream inTest = new DataInputStream(new ByteArrayInputStream(allWrittenBytesTest));
short schemaIdTest = inTest.readShort();
long lastModifiedDateTest = inTest.readLong();
int sizeAvroTest = inTest.readInt();
byte[] avroBinaryValue1 = new byte[sizeAvroTest];
inTest.read(avroBinaryValue1, 0, sizeAvroTest);
System.out.println(schemaIdTest);
System.out.println(lastModifiedDateTest);
System.out.println(new String(avroBinaryValue1));
writeFile(allWrittenBytesTest);
}
/**
* Write the file in Java
* #param byteArray
*/
public static void writeFile(byte[] byteArray) {
try{
File file = new File("bytearrayfile");
FileOutputStream output = new FileOutputStream(file);
IOUtils.write(byteArray, output);
} catch (Exception ex) {
ex.printStackTrace();
}
}
It doesn't look like you want to use std::getline to read this data. Your file isn't written as text data on a line-by-line basis - it basically has a binary format.
You can use the read method of std::ifstream to read arbitrary chunks of data from an input stream. You probably want to open the file in binary mode:
std::ifstream myfile("bytearrayfile", std::ios::binary);
Fundamentally the method you would use to read each record from the file is:
uint16_t schemaId;
uint64_t lastModifiedDate;
uint32_t binaryLength;
myfile.read(reinterpret_cast<char*>(&schemaId), sizeof(schemaId));
myfile.read(reinterpret_cast<char*>(&lastModifiedDate), sizeof(lastModifiedDate));
myfile.read(reinterpret_cast<char*>(&binaryLength), sizeof(binaryLength));
This will read the three static members of your data structure from the file. Because your data is variable size, you probably need to allocate a buffer to read it into, for example:
std::unique_ptr<char[]> binaryBuf(new char[binaryLength]);
myfile.read(binaryBuf.get(), binaryLength);
The above are examples only to illustrate how you would approach this in C++. You will need to be aware of the following things:
There's no error checking in the above examples. You'll need to check that the calls to ifstream::read are successful and return the correct amount of data.
Endianness may be an issue, depending on the the platform the data originates from and is being read on.
Interpreting the lastModifiedDate field may require you to write a function to convert it from whatever format Java uses (I have no idea about Java).
So I have implemented a working program which searches a file using the binary search method:
public int BSearch(int x1, int x2) throws IOException {
int current_key;
middle=(x1+x2)/2;
if(x1>x2) {
middle=-1; //middle==-1 is condition of 'key not found'
return middle;
}
MyFile.seek(middle*4);
current_key=MyFile.readInt();
da++;
if(current_key==key) {
return middle;
}
else if(key<current_key) {
x2=middle-1;
return BSearch(x1,x2);
}
else {
x1=middle+1;
return BSearch(x1,x2);
}
}
Now I want to transform it so it reads the file piece-by-piece (say 1KB each time) into a buffer, and then binary search that buffer. If key is not found in that buffer I read further the file and so on. I want to clarify though that the buffer is a handmade buffer like this (correct me):
byte[] buf = new byte[1024];
MyFile.read(buf);
ByteArrayInputStream bis= new ByteArrayInputStream(buf1);
DataInputStream ois= new DataInputStream(bis);
current_key=ois.readInt();
A big problem (among others) is I don't know how I'll read from a certain position of the buffer
OK I think I managed to do it by copying the buffer to a new int[] array element-by-element. I want to believe it is still faster than accessing the disc every time I want to load a buffer.