This was the question asked:
Develop a class Decrypt that derives from FileInputStream and overrides the read() method of FileInputStream such that overriding read method returns a decrypted integer. Use this class to decrypt the file information that is contained out.txt.
I wrote a code for encryption, it worked but for decryption it doesn't. For decryption, i have to XOR the value with 128.
The problem is that after running the program, it doesn't write anything on the output file.
Here's the link for the sample input:
https://www.dropbox.com/s/jb361cxmjc9yd8n/in.txt
This is how the sample output looks like:
How high he holds his haughty head.
The code is below:
//Decrypt class
import java.io.*;
public class Decrypt extends FileInputStream {
public Decrypt(String name) throws FileNotFoundException {
super(name);
}
public int read() throws IOException {
int value = super.read();
int xor = value^128; // exclusive OR to decrypt
return xor;
}
}
//main
import java.io.*;
public class LA4ex3b {
public static void main(String[] args) throws IOException {
Decrypt de=null;
FileOutputStream output=null;
try
{
de = new Decrypt("C:/Users/user/workspace/LA4ex3a/in.txt");
output = new FileOutputStream("C:/Users/user/workspace/LA4ex3a /out.txt");
int a;
while ((a = de.read()) != -1)
{
output.write(a);
}
}
finally
{
if (de!=null)
de.close();
if (output!=null)
output.close();
}
}
}
int value = super.read();
int xor = value^128; // exclusive OR to decrypt
return xor;
In the above you do not check for the special value of -1 returned from super.read(), which you must push through transparently. Without that you'll never receive -1 in your while loop and the program will not terminate normally. The code as below should fix that issue:
int value = super.read();
return value == -1? value : value^128;
Well, I think you should ask in your Overriden method, wether super.read() is -1, too. Because if super.read() is -1, and you xor it with 128, it will not be -1 any longer, so Decrypt.read() wont be -1.
Edit: Ok, I wasn't fast enough!
Two quick corrections:
The output filename should not have a space in it
You listed no restrictions on data in your input file, so I suggest you use the "read data into a byte array" method (just in case a "-1" byte value is legitimate data in the input. Your particular text input is probably ok, but think of problems like these and solve the most inclusive problem you can still simply.
byte[] dataBuffer = new byte[1000];
int bytesRead;
bytesRead = de.read(dataBuffer);
while (bytesRead != -1 ) [
// decrypt each byte
// write the decrypted bytes
bytesRead = de.read(dataBuffer);
}
class Overload
{
public int Add(int a, int b)
{
Console.WriteLine("Int method with Two params executed");
return a + b;
}
public int Add(int a, int b, int c)
{
Console.WriteLine("Int method with three params executed");
return a + b + c;
}
public double Add(double a, double b)
{
Console.WriteLine("double method with Two params executed");
return a + b;
}
}
//class Derived : Overload //over riding//
//{
// public int Add(int a, int b)
// {
// return a + b;
// }
//}
}
Related
I need to hash the inputstream during upload to ensure the integrity of the file. How can I copy the inputstream into two copies and the size of the file is more than 10GB. It need faster time to hash and copy
You have multiple options.
Files.newInputStream, hand that off to your hasher algorithm, obtain the hash, then start over to send. This is the best option if it is highly useful to have the hash available during/before the upload. It requires reading the bytes off of disk twice, of course.
Use an existing implementation of a stream that hashes on the fly, such as guava's HashingInputStream, or write something like this on your own (it's not particularly difficult to do so).
You can't easily have 2 inputstreams that can both be fully streamed through whilst only causing the file to be read once, because the 'user' of an inputstream decides how 'fast' you go through, and you can't have 2 separate lines of code both be in charge.
Hence, one of the two processes needs to not be an inputstream and instead have its control reversed: Instead of allowing the code to ask the inputstream for more data (by calling one of its read methods), you'd have some code that is invoked by the inputstream with: Hey, I just read this data because the 'primary' driver asked for it, before I hand it off to the primary driver, anything you need to do here?
The hashing code should be this secondary driver, because it can trivially deal with 'here are X bytes but we are not done yet please process it'.
Here is an example of what that would look like. Note that FilterInputStream by default just forwards all calls directly to the stream you wrap.
public class HashingInputStream extends FilterInputStream {
private final MessageDigest hash;
public HashingInputStream(InputStream base) {
super(base);
hash = MessageDigest.getInstance("SHA-256");
}
#Override
public int read() throws IOException {
int v = super.read();
if (v == -1) return v;
hash.update((byte) v);
return v;
}
#Override
public int read(byte[] b) throws IOException {
int r = super.read(b);
if (r == -1) return r;
hash.update(b, 0, r);
return r;
}
#Override
public int read(byte[] b, int off, int len) throws IOException {
int r = super.read(b, off, len);
if (r == -1) return r;
hash.update(b, off, r);
return r;
}
public byte[] digest() {
return hash.digest();
}
}
your upload code wraps the inputstream, e.g:
try (var in = Files.newInputStream(pathToYourFile)) {
var hashing = new HashingInputStream(in);
hashing.transferTo(yourOutputStream);
var hash = hashing.digest();
}
And you'll get your hash at the end; the file is only read once.
I'm trying to modify the CharStack class (below) in Eclipse, but I'm unable to get it to do anything in the console when I run it, though it works fine when compiled with javac.exe
Is this something to do with carriage returns, perhaps? How do I signal to Eclipse that I'm ready for it to accept the input and return a result (the -1)?
The algorithm for the class is just:
while (there is a character to read)
push the character onto a stack;
while (there are characters on the stack)
pop off a character and print it;
The concept of a stack is a perfect candidate for becoming a class. It has a well-defined interface (push() and pop()) and some rules to enforce (you can only take data from the top, you can only remove as many elements as you insert). Here is a simple implementation of a stack that holds characters:
import java.io.*;
public class CharStack
{
private char[] m_data;
private int m_ptr;
public CharStack(int size)
{
m_ptr = 0;
m_data = new char[(size > 1 ? size : 10)];
}
public void push(char c)
{
if (m_ptr >= m_data.length)
{
// Grow the array automatically
char[] tmp =
new char[m_data.length * 2];
System.arraycopy(m_data, 0,
tmp, 0,
m_data.length);
m_data = tmp;
}
m_data[m_ptr++] = c;
}
public char pop()
{
return m_data[--m_ptr];
}
public boolean hasMoreElements()
{
return (m_ptr != 0);
}
public static void main(String[] argv)
throws IOException
{
CharStack s = new CharStack(10);
int i;
while ( (i = System.in.read()) != -1 )
{
s.push((char) i);
}
while (s.hasMoreElements())
{
System.out.write(s.pop());
}
System.out.println();
}
}
When I run this in Windows CLI I get:
C:\user>java CharStack
12345
54321
What you're looking for is the EOF character, represented OS-agnostically in this Java class.
In Windows that would be Ctrl-Z. Presumably this is implicit when you're on the Windows CLI version, but not so in Eclipse.
I am not very familiar with exactly all of the implications of bytes or even close to charsets, simply because i have not used them often. However i am working on a project in which i need to convert every Java primitive type (and Strings) to AND from bytes. I want them all with the charset UTF-8, but i'm not sure if i am converting them properly.
Anyways, although i am pretty sure that all number to/from byte conversions are correct, but then again, i need to be 100% sure. If someone has really good experience with bytes with numbers and charsets, could you look over the class below, and point out any issues?
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
public class ByteUtil
{
//TO BYTES FROM PRIMITIVES & STRINGS
public static byte[] getBytes(short i)
{
return ByteBuffer.allocate(2).putInt(i).array();
}
public static byte[] getBytes(int i)
{
return ByteBuffer.allocate(4).putInt(i).array();
}
public static byte[] getBytes(long i)
{
return ByteBuffer.allocate(8).putLong(i).array();
}
public static byte getBytes(boolean i)
{
return (byte) (i ? 1 : 0);
}
public static byte[] getBytes(char i)
{
return getBytes(String.valueOf(i).trim());
}
public static byte[] getBytes(String i)
{
return i.getBytes(StandardCharsets.UTF_8);
}
public static byte[] getBytes(float i)
{
return getBytes(Float.floatToIntBits(i));
}
public static byte[] getBytes(double i)
{
return getBytes(Double.doubleToLongBits(i));
}
//TO PRIMITIVES & STRINGS FROM BYTES
public static short getShort(byte[] b)
{
ByteBuffer wrapped = ByteBuffer.wrap(b);
return wrapped.getShort();
}
public static int getInt(byte[] b)
{
ByteBuffer wrapped = ByteBuffer.wrap(b);
return wrapped.getInt();
}
public static long getLong(byte[] b)
{
ByteBuffer wrapped = ByteBuffer.wrap(b);
return wrapped.getLong();
}
public static boolean getBoolean(byte b)
{
return(b == 1 ? true : false);
}
public static char getChar(byte[] b)
{
return getString(b).trim().toCharArray()[0];
}
public static String getString(byte[] b)
{
return new String(b, StandardCharsets.UTF_8);
}
public static float getFloat(byte[] b)
{
return Float.intBitsToFloat(getInt(b));
}
public static double getDouble(byte[] b)
{
return Double.longBitsToDouble(getLong(b));
}
}
Additionally, all the data put in and returned is read by my source internally, for example the boolean conversion may or may not be the correct way to do something like such, but in the boolean case, it wont matter since i know what i am checking for.
You don't even need to do this. You can use a DataOutputStream to write your primitive types and Strings to a ByteArrayOutputStream. You can then use toByteArray() to get a byte[] that you put into a ByteArrayInputStream. You can wrap that InputStream in a DataInputStream to get back your primitives.
If you're doing a school assignment where you need to implement this yourself (which sounds like a dumb assignment), you can look up the implementations of ByteArrayOutputStream and ByteArrayInputStream on GrepCode. Copy/pasting is a bad idea, but it might give you some hints about considerations to take into account.
I have been studying Decorator pattern and developed simple class ToUpperCaseInputStream. I overrode read() method so it could convert all chars from InputStream to uppercase. Code of the method is shown below (throws OutOfMemoryError):
#Override
public int read() throws IOException {
return Character.toUpperCase((char)super.read());
}
As I figured out later, casting to char is redundant, but it's not the point. I'm having "java.lang.OutOfMemoryError: Java heap space" when the code:
((char) super.read())
evaluates. To make this simpler I wrote the same method (this one throws OutOfMemoryError):
#Override
public int read() throws IOException {
int c =(char) super.read();
return (c == -1 ? c : Character.toUpperCase(c));
}
And this one does not:
#Override
public int read() throws IOException {
int c = super.read();
return (c == -1 ? c : Character.toUpperCase(c));
}
When I remove casting from the assignment the code runs with no errors and results in all text uppercased. As it's said at Oracle tutorials:
An assignment to an array component of reference type (§15.26.1), a method invocation expression (§15.12), or a prefix or postfix increment (§15.14.2, §15.15.1) or decrement operator (§15.14.3, §15.15.2) may all throw an OutOfMemoryError as a result of boxing conversion (§5.1.7).
It seems that autoboxing is used, but as for me it's not the case. Both variants of the same method result in OutOfMemoryError. If I am wrong, please explain this to me, because it will blow up my head.
To provide more info there is the client code:
public class App {
public static void main(String[] args) throws IOException {
try (InputStream inet = new ToUpperCaseInputStream(new FileInputStream("d:/TEMP/src.txt"));
FileOutputStream buff = new FileOutputStream("d:/TEMP/dst.txt")) {
copy(inet, buff);
}
}
public static void copy(InputStream src, OutputStream dst) throws IOException {
int elem;
while ((elem = src.read()) != -1) {
dst.write(elem);
}
}
}
What it does is just prints simple message from one file to another.
Although the case is solved I want to share a really good explanation of how casting is done. https://stackoverflow.com/a/24637624/1923644
Before you cast to char you need to check for -1 (signaling end of input data).
char in Java is an unsigned short, meaning that when -1 is returned, your cast will make it 65535. Even if you did not have OutOfMemory, your code is still broken.
Regarding why you are getting OOM error, it is hard to say without full code, maybe, later in the code there are some memory allocations based on value of the character.
So try this and see if it helps:
#Override
public int read() throws IOException {
int c = super.read();
if (c == -1) return c;
char ch = (char) c;
return Character.toUpperCase(ch);
}
I'm serialising and deserialising a large two dimensional array of objects. Each object contains instructions to creating a BufferedImage - this is done to get around BufferedImage not being directly serializable itself.
The class being serialised is:
public final class MapTile extends TransientImage
{
private static final long serialVersionUID = 0;
private transient BufferedImage f;
transient BufferedImage b;
int along;
int down;
boolean flip = false;
int rot = 0;
public MapTile(World w, int a, int d)
{
// f = w.getMapTiles();
along = a;
down = d;
assignImage();
}
public MapTile(World w, int a, int d, int r, boolean fl)
{
// f = w.getMapTiles();
along = a;
down = d;
rot = r;
flip = fl;
assignImage();
}
public int getA()
{
return along;
}
public int getD()
{
return down;
}
#Override
public void assignImage()
{
if (f == null)
{
f = World.mapTiles;
}
b = f.getSubimage(along, down, World.squareSize, World.squareSize);
if (rot != 0)
{
b = SmallMap.rotateImage(b, rot);
}
if (flip)
{
b = SmallMap.flipImage(b);
}
super.setImage(b);
f.flush();
b.flush();
f = null;
b = null;
}
}
which extends:
public abstract class TransientImage implements Serializable
{
private transient BufferedImage image;
public BufferedImage getImage()
{
return image;
}
public void setImage(BufferedImage i)
{
image = i;
}
public abstract void assignImage();
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
{
in.defaultReadObject();
assignImage();
}
}
This will ultimately be part of a map - usually it is created randomly but certain areas must be the same each time, hence serialising them and reading the array back in. As I will never need to save the image during normal usage I am putting in the write code:
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("verticalroad.necro")))
{
//out.writeObject(mapArray);
//}
//catch (IOException e) {
//}
in the class that creates the map, the read code:
try{
FileInputStream door = new FileInputStream(new File(f.getPath()+ "//verticalroad.necro"));
ObjectInputStream reader = new ObjectInputStream(door);
homeTiles = (MapTile[][]) reader.readObject();
}
catch (IOException | ClassNotFoundException e)
{
System.out.println("Thrown an error" + e.getMessage());
}
in the initialising class and commenting in and out as needed.
However. Each time I run the program the contents of the two dimensional array (mapArray in write, homeTiles in read) is different. Not only different from the one I (thought) I wrote, but also different each time the program is opened.
As can be seen, I'm printing out the toString to System.out which reveals further oddities. As its just a standard array, the toString isn't 100% helpful but it seems to cycle between several distinct values. However, even when the toStringg gives the same value, the contents of the array as displayed are not the same.
An example of a toString is hometiles:[[Lriseofthenecromancer.MapTile;#7681720a Looking at the documentation for Array.toString (here) it seems to be badly formed, lacking a trailing ]. I'm not sure if this is a clue to the issue or if its simply that the array is very large (several thousand objects) and its an issue of display space (I'm using NetBeans).
Any insight as to why this is changing would be appreciated. My working assumption is that its serializing the array but not the contents. But I have no idea a) if that's the case and b)if it is, what to do about it.
EDIT: Looking into this a bit further, it seems that instance variables aren't being set immediately. Printing them out directly after the call to setImage() has them all at zero, printing them from the calling class has them where they should be.
The underlying problem was that I'm an idiot. The specific expression of this in this particular case was that I forgot that subclasses couldn't inherit private methods. As such, the assignImage call wasn't being made and the image wasn't being set up.
Sorry for wasting the time of anyone who looked at this. I feel quite embarrassed.