Printing a single and specific method to a file in Java - java

I am working on a basic encryption program for a school project, and I want to have easily interchangable keys. As it stands, I have a encryption class and a decryption class, with multiple methods. One of those methods is the key that I want to print to a file. Because I will be making many changes to those two classes (apart from the keys), I want to be able to print just that one method to a file. I also need to be able to load it again. Is there any easy way to do this?

You could use java serialization, as you commented that you have a String array to save, you could do something like this:
// save object to file
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("/tmp/file")));
oos.writeObject(myArray); // where myArray is String[]
// load object from file
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("/tmp/file")));
String[] read = (String[]) ois.readObject();
A working example ;), saving the arguments received with the application execution.
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Arrays;
public class TestSerialization {
public static void main(final String[] array) throws FileNotFoundException, IOException, ClassNotFoundException {
// save object to file
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("/tmp/file")));
oos.writeObject(array); // where myArray is String[]
// load object from file
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("/tmp/file")));
String[] read = (String[]) ois.readObject();
System.out.println(Arrays.toString(read));
}
}

Serialization pointed out by user Speath is a very good approach I find.
If you want to be more selective in what you write into your files you can use simple File I/O to write into a file like follows:
Create a new file on the file system withe the FileWriter class and then initiate an I/O stream with BufferedWriter to write into this file:
// create a new file with specified file name
FileWriter fw = new FileWriter("myFile.log");
// create the IO strem on that file
BufferedWriter bw = new BufferedWriter(fw);
// write a string into the IO stream
bw.out("my log entry");
// don't forget to close the stream!
bw.close();
The whole thing must be surrounded with a try/catch in order to catch IO Exception.
Hope this helps.

Related

Adler32 generated checksum doesnt match the .txt files checksum

im tasked with written two java programs. One program creates a file called 'userinput.txt', then writes everything the user inputs into the file. Once done a new file is created called 'Checksum.txt' and this file will write down the checksum for the 'userinput.txt' file after reading whats inside of it.
The 2nd program just reads the same 'userinput.txt' file and then generates a checksum and prints it onto the console (i also have to get the program to read the other checksum.txt file and display it int the console to compare the two but i havent gotten around to that yet).
Iv written the program for these two but my problem is they are both different checksum even though they are reading the same file. Im using Adler32 but CRC32 also gives me two different checksums (the one on console is always different to the one stored in checksum.txt) and im not sure whats causing it frankly :/
Here is the code that takes userinput and generates the checksum file:
package attemp2;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
import java.util.zip.Adler32;
import java.util.zip.CheckedInputStream;
public class main {
public static void main(String[] args) throws IOException {
System.out.println("All inputs will be recorded into a sigle file. Enter 'x' when done. A checksum File will aslo be created at the end");
FileWriter fw = new FileWriter("d:/input.txt", false); // clears previous entry in file.
while (true) {
Scanner input = new Scanner(System.in); //get user input
String ch = input.nextLine(); //stores user input
System.out.println(ch); //prints out what user just inputed
if (ch.equals("x")) { //stops running if 'x' is entered
break;
}
BufferedWriter writer = new BufferedWriter(new FileWriter("d:/input.txt", true));
writer.write(ch);
writer.newLine(); // Add new line
writer.close();
}
try {
FileReader reader = new FileReader("d:/input.txt");
BufferedReader br = new BufferedReader(reader);
// read line by line String line;
String read = "";
String line;
while ((line = br.readLine()) != null) {
read = read + line;
//prints out text in file currently
System.out.println(line);
}
//checksum.txt generation
byte buffer[] = read.getBytes();
ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
CheckedInputStream cis = new CheckedInputStream(bais, new Adler32());
byte readBuffer[] = new byte[buffer.length];
cis.read(readBuffer);
FileOutputStream out = new FileOutputStream("d://checksum.txt");
BufferedWriter wrt = new BufferedWriter(new FileWriter("d:/checksum.txt", false));
wrt.write(Long.toString(cis.getChecksum().getValue()));
wrt.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
The code that reads the file and generates a checksum in console:
package check;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Scanner;
import java.util.zip.Adler32;
public class CheckSum {
private Adler32 checksum;
private String filepath;
InputStream inputStream;
public CheckSum(String filepath) throws FileNotFoundException{
this.filepath = filepath;
checksum = new Adler32();
inputStream = new FileInputStream(filepath);
}
public long generateChecksum() throws IOException{
int c;
while((c = inputStream.read())!=-1){
checksum.update(c);
}
return checksum.getValue();
}
public void read() throws IOException{
File file = new File(filepath);
BufferedReader br = new BufferedReader(new FileReader(file));
String st;
while ((st = br.readLine()) != null) {
System.out.println(st);
}
}
public static void main(String[] args) throws Exception{
Scanner scanner = new Scanner(System.in);
String filepath = "d:/input.txt";
CheckSum checksum = new CheckSum(filepath);
checksum.read();
System.out.println("For the file: "+filepath);
System.out.println("The checksum generated is: "+checksum.generateChecksum());
}
}
Please learn how to use a debugger, see What is a debugger and how can it help me diagnose problems?.
That being said, you have some problems with your code. First you are calculating the checksum on an empty array. When you write:
byte readBuffer[] = new byte[buffer.length];
cis.read(readBuffer);
you are reading an empty array of the size of the buffer array. You don't need to create a new array. In fact, you should read the buffer array you already have, since there is your content. In this case you just write:
cis.read(buffer);
The next problem is that you are using readers and writers, which are used for text/string files, but checksum/hash algorithm usually works on byte level. This can result in several errors like encoding (ASCII, UTF-8, etc. stuff) and line-termination issues (\n vs. \r\n vs. \r).
However, in this case you are working with readLine(). This method does not return the line-termination at the end, see the documentation of readLine():
Returns:
A String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached
So, what you are reading from the file is not the same what is actually in the file. But your CheckSum class reads every byte in the saved file (as it should). Assume you enter only the string "abc". Your first calculation will be run on the 3 bytes long array with the values:
[97,98,99]
The line-termination is ignored by the readLine() method, but it is still present in the file. When you check the checksum with the second program, the InputStream you are using will see the following bytes:
[97,98,99,10]
(The bytes at the end depends on the OS you are using)
As you see you run the checksum on different byte arrays, resulting in different checksum values. So, make sure you are running the checksum checks on the same byte array content (or InputStream content) to get the same checksum in both applications.

Use of PrintWriter with streams of bytes

I'am testing the PrintWriter class which can handle streams of characters and streams of bytes. Everything went smooth when i tried with streams of characters, now i was testing it with streams of bytes and whenever i print what it reads it always displays null(exception). Here's the code:
package com.files.ex1;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
public class ex1 {
public static void main(String[] args) {
PrintWriter oPW;
try {
oPW = new PrintWriter(new ObjectOutputStream(new FileOutputStream("data.txt")));
oPW.write("1\n");
oPW.write("2\n");
oPW.write("3\n");
oPW.flush();
oPW.close();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
This is the class that tries to read and always prints null:
package com.files.ex1;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class ex1_2 {
public static void main(String[] args) {
ObjectInputStream oOIS;
try {
oOIS = new ObjectInputStream(new FileInputStream("data.txt"));
String s = (String) oOIS.readObject();
System.out.println(s);
} catch (IOException e) {
System.out.println(e.getMessage());
} catch (ClassNotFoundException e) {
System.out.println(e.getMessage());
}
}
}
Also what are the advantages of using this class? For streams of characters i can just use BuffedReadear or BufferedWriter to optimize reads or writes respectively, and it also has flush() method.
And what is the advantage of using PrintWriter with streams of bytes? Using ObjectOutputStream alone works when i try to do the operations above.
The reason you're getting null is because you're using readObject on ObjectInputString, but you haven't serialized any Java objects. ObjectInputString.readObject is to be used with ObjectOutputString.writeObject.
The PrintWriter docs state explicitly that
It does not contain methods for writing raw bytes, for which a program should use unencoded byte streams.
You should only use PrintWriter for text. It exposes helpful methods that you may be familiar with because System.out has the print interface.
You should only really use ObjectOutput/InputStream when writing and reading serialized Java Objects. The serialization format is binary data (unlike JSON/XML for example). These objects must implement the Serializable interface.
You can improve performance of writing and reading unencoded byte streams by use BufferedOutputStream and BufferedInputStream respectively.
In general, classes with suffix "Reader" and suffix "Writer" are for text encoded streams. They contain helpful methods for parsing strings and lines from text streams. They should never be used for transferring binary data.
In your example you're only writing text data to a file and reading that text data back, so use:
oPW = new PrintWriter(new FileOutputStream("data.txt"));
oPW.println("1");
for writing and
oOIS = new BufferedReader(new FileInputStream("data.txt"));
String s = oOIS.readLine(); // "1"
for reading.
If you were reading and writing binary data, you would do this instead:
os = new FileOutputStream("data.bin");
os.write(new byte[]{ 1, 2, 3 });
and read:
is = new FileInputStream("data.bin");
byte[] buf = new byte[3];
is.read(buf); // buf now equals {1, 2, 3}
If you were reading and writing Java objects, you would do this instead:
oos = new ObjectOutputStream(new FileOutputStream("data.bin"));
Foo foo = new Foo(...);
oos.writeObject(foo);
and read:
ois = new ObjectInputStream(new FileInputStream("data.bin"));
Foo foo = (Foo) ois.readObject();

File I/O producing gibberish on output

I'm learning File I/O using Java.
Following are my codes from two different Java files. One is "File" with the main class, the other is "FileWrite."
I was able to implement string input and output. But the output textfile has gibberish in the beginning and I am not sure why.
[File.Java]
package file;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class File {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("B:\\fileIn.txt")))
{
String stCurrent;
while ((stCurrent = br.readLine()) != null) {
System.out.println(stCurrent);
}
} catch (IOException e) {
e.printStackTrace();
}
FileWrite fW = new FileWrite();
fW.serializeAddress("Boston", "Canada");
}
}
[FileWrite.Java]
package file;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class FileWrite {
public void serializeAddress(String city, String country) {
try {
FileOutputStream fout = new FileOutputStream("B:\\address.txt");
ObjectOutputStream obOut = new ObjectOutputStream(fout);
obOut.writeUTF(city);
obOut.writeUTF(country);
obOut.close();
System.out.println("Output Done");
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
Now, on "obOut.writeUTF(city); obOut.writeUTF(country);" I separated out two string inputs. Is there a way to combine them into one? As in obOut.writeUTF(city, counry) instead of two. Or is this only achievable through making these into an object?
[Update]
Imported a couple more and I tried
PrintStream ps = new PrintStream(new FileWriter("B:\\addressPS.txt"));
ps.println(city);
ps.println(country);
ps.close();
But with errors, any clue?
You are doing the right thing keeping them separate already. City and country are different fields.
A very common mistake is not making a distinction between binary and text files/socket streams. You are a mixing the two which will lead to confusion. I suggest you only sue text Writer/Reader or binary Input/OuptutStream unless you have a very clear idea of what you are doing.
In short if you what to write text use
PrintStream ps = new PrintStream(new FileWriter(textFileName));
ps.println(city);
ps.println(country);
ps.close();
writeUTF takes strings also, you don't have to create new object for city and county.
Cant you do obOut.writeUTF(city +" "+country); ?
The gibberish is because .writUTF() writes data in a modified UTF format which is mentioned in the javadocs.
An ObjectOutputStream is generally used to output OBJECTS but I suppose you can use it for strings as well. You can use the respective .readUTF() method in the ObjectInputStream class in order to read the data in your file back.
Also, you have tried to use the try-with-resources block which is new to Java SE7. You should NOT do it the way you have done so. You should do this instead:
try (FileReader fr = new FileReader("B:\\fileIn.txt"); BufferedReader br = new BufferedReader(fr);) {
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
Splitting the FileReader and the BufferedReader will allow Java SE7 to close both the streams with ease. The way you have done it, only the BufferedReader stream will get closed after the try block finishes.
By definition, ObjectOutputStream produces 'gibberish'. It's not intended for human consumption, it is a format used to write out objects so that you can read them back. You're not supposed to be able to make sense of the results in a text editor. To make human-readable content, just use an OutputStreamWriter or even a PrintWriter. In short, your last example is correct, and if you get errors, please edit your question to tell us what the errors are.

Modify or Delete Data in a File

Today I was trying the algorithm for modifying and deleting data inside a file using Java in Windows platform.
1st : create a temporaryFile
2nd : write the data you wanted inside the originalFile into a String and to the temporaryFile
3rd : rename temporaryFile to originalFile.
The Code:
import java.io.File;
import java.io.IOException;
import java.io.FileWriter;
import java.util.Scanner;
import java.io.FileNotFoundException;
public class testing{
private static String temp;
public static void main(String [] args)
{
try{
File tempFile = File.createTempFile("haha\\temporary", ".txt"); //create a temporary file in haha folder
FileWriter writer = new FileWriter(tempFile);
Scanner input = new Scanner(new File("haha\\testing.txt")); //get input from testing.txt
temp = input.next();
writer.write(temp);
writer.close();
File origFile = new File("haha\\testing.txt");
tempFile.renameTo(origFile);
}
catch ( FileNotFoundException fileNotFoundException ){}
catch(IOException ioException){}
}
}
In the above code , the textFile to be edited is located inside a folder name haha which is located inside another folder together with the testing.class.I've tried this code to no avail , the originalTextFile has no changes .
If you have your file in the same directory, you don't need to pass the path to the File constructor.
Scanner input = new Scanner(new File("testing.txt"));
This should do it.
You need to close the Scanner object to make the changes, the underlying operating system has a file lock that must be released.
input.close();
File origFile = new File("haha\\testing.txt");

What's the difference between File and FileLoader in Java?

So I have the following code where I should read a Text File (This is just the Main Class):
import gui.MenuWindow;
import java.io.IOException;
import javax.swing.JOptionPane;
public class Assessor {
public static void main(String args[]) throws IOException {
FileLoader file = new FileLoader("Example.txt");
try{
new MenuWindow(file.loader());
} catch(Exception exc) {
JOptionPane.showMessageDialog(null, "Error Reading File");
}
}
}
Then I'd have to load the Text into a ListBox using Swing. The thing is that I've found this new code to read a Text File:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileNotFoundException;
import java.io.IOException;
public class ReadTextFileExample {
public static void main(String[] args) {
File file = new File("test.txt");
StringBuffer contents = new StringBuffer();
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(file));
String text = null;
// repeat until all lines is read
while ((text = reader.readLine()) != null) {
contents.append(text)
.append(System.getProperty(
"line.separator"));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
// show file contents here
System.out.println(contents.toString());
}
}
So I'd like to know what is the difference between the following two lines:
FileLoader file = new FileLoader("Example.txt"); //First Code
File file = new File("test.txt"); //Second Code
And... What's the StringBuffer and BufferedReader used to? Thanks!
So I'd like to know what is the difference between the following two lines:
FileLoader file = new FileLoader("Example.txt"); //First Code
File file = new File("test.txt"); //Second Code
The first creates a java.io.FileLoader which Andreas discusses. Since the javadoc says "The constructors of this class assume that the default character encoding and the default byte-buffer size are appropriate", it should never be used.
The second creates a java.io.File which is just a file path with some utility methods that can be used to read directory trees, delete, create, and move files, etc., or it can be used with FileInputStream and other classes to actually access the file contents.
And... What's the StringBuffer and BufferedReader used to? Thanks!
The StringBuffer is used to collect the contents of the file.
The BufferedReader is used to speed up reading of the file. Instead of reading one character at a time, the BufferedReader batches reads using an internal buffer.
This is an exemplary question about learning Java SE, especially regarding the java.io package. I was a bit puzzled in the beginning, but now I am quite sure that you want to compare the FileReader to the File class, which both belong to the same package java.io.
File in the Java SE API:"An abstract representation of file and directory pathnames."In other words, it is there to handle files and directories on the file system within Java. Since Java is an object-oriented language, they made a class for it. Files, i.e. binary and text files, share some attributes in common with directories, as there are: absolute, canonical path and simple name, etc.Of course, File is one of the base classes in the java.io package and many classes like FileReader make use of it for object construction.
FileReader:"Convenience class for reading character files."It comes with a handy constructor that takes a file name or file path as a String. Originally, it was meant to be constructed by a File instance. A Reader instance in general is practical to read text files, in contrast to InputStream, which is used to read binary files. A Reader instance in general is connected to a character set, e.g. "UTF-8" to translate byte to character streams.
Please also have a look at the excellent Java Tutorials provided by Oracle.
I hope the difference between File and FileReader becomes a little clearer. Especially note that there is no I/O, when you instantiate a File instance. To answer your question, the interconnection of the two classes would be:
File file = new File("test.txt"); // 1) Instaniate the file
Reader reader = new FileReader(file); // 2) Instantiate the Reader using the File instance
When you wrap a BufferedReader around a Reader instance, you can read the text file linewise, as:
BufferedReader bufferedReader = new BufferedReader(reader); // 3) Get a "buffered reader" to have access line by line.
StringBuffer comes in, when you want to chain a large number of String objects, since String objects is immutable and string operations like
String s1 = "Star ";
String s2 = "Wars";
s1 = s1 + s2;
are very costly, especially in loops, since at every addition a new String object (left side result) is created, with practically no size limits, apart from the reserved Java VM heap space.
Let me point out that you should better use the StringBuilder class, which is even faster, and is the unsynchronized counter-part of StringBuffer, introduced in the Java 5 release. The feature that StringBuffer is guaranteed to be synchronized among different Thread's is hardly ever used. I never came across it in my whole life as Java programmer.

Categories

Resources