I am having trouble reading object-data from a .txt-file using the readObject()-method from ObjectInputStream.
I am writing multiple User-objects to a .txt to save users when the server for the program is down, and the writing works fine, though when I am trying to read the information back, I don't know how to loop through/read the next line in the file.
public void readObjectFromFile() {
boolean cont = true;
User user;
try {
FileInputStream fileIn = new FileInputStream("files/userlist.txt");
ObjectInputStream objectIn = new ObjectInputStream(fileIn);
while(cont){
Object obj = objectIn.readObject();
if(obj != null) {
registeredUsers.add((User)objectIn.readObject());
user = (User)obj;
userPasswords.put(user.getUsername(), user.getPassword());
System.out.println(user.getUsername());
}else {
cont = false;
}
}
}catch (Exception ex) {
ex.printStackTrace();
}
}
public void addUserToDatabase(User user) {
try(FileOutputStream fos = new FileOutputStream("files/userlist.txt", true);
ObjectOutputStream oos = new ObjectOutputStream(fos)){
oos.writeObject(user);
oos.write('\n');
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
I would want to read the file line-by-line, and store the information of every line in a User-object and store it in the registeredUsers-list.
Okay I solved it!
public void readUsersFromFile() {
try {
FileInputStream fileIn = new FileInputStream("files/userlist.dat");
ObjectInputStream objectIn = new ObjectInputStream(fileIn);
boolean keepReading = true;
try {
while(keepReading) {
User user = (User)objectIn.readObject();
registeredUsers.add(user);
userPasswords.put(user.getUsername(), user.getPassword());
System.out.println(user.getUsername());
objectIn = new ObjectInputStream(fileIn);
}
}catch(EOFException e) {
keepReading = false;
}
}catch (Exception ex) {
ex.printStackTrace();
}
}
Problem: You are reading twice in while loop.
First Call:
objectIn.readObject()
Second Call:
registeredUsers.add((User)objectIn.readObject());
Solution:
Do not call readObject() method twice use the reference that is already been taken.
Other then functional problem, you can also correct the following things to make your code better:
Don't make while loop so complex.
No need to use separate boolean counter in while loop.
Just typecast once to user not multiple times (at the time of readObject() call itself).
Please refer following code:
User user = null;
while((user = (User) objectIn.readObject()) != null){
registeredUsers.add(user);
userPasswords.put(user.getUsername(), user.getPassword());
System.out.println(user.getUsername());
}
Are you already getting the data from the file?
I have done this before with pipe-delimited files ("|"), so:
value1|value2|value3
Not sure of the makeup of your file, but if you are already reading the data then you can skip to next lines & make new User objects like so:
private List <UserEntry> collectFileContents(InputStream is, String fileName) throws Exception {
try {
List <UserEntry> userEntries = new ArrayList <UserEntry>();
String line = "";
BufferedReader br = new BufferedReader(new InputStreamReader(is));
br.readLine();
while ((line = br.readLine()) != null) {
if (line.length() > 0) {
UserEntry entry = new UserEntry();
try {
String[] lineValues = line.split("\\|",-1);
entry.setVal1(lineValues[0]);
entry.setVal2(lineValues[1]);
//etc..
userEntries.add(entry);
} catch (ArrayIndexOutOfBoundsException ex) {
//error handling here
continue;
}
}
}
return userEntries;
}catch(Exception ex) {
//error handling here
}
}
This should create a list of Users, and I save them to the DB in a different method. But you can do it however you like. Also of note - in my file I have a title line as the first line. So this code will skip the first line. Again, not sure about how your file is set up.
Related
I tried to retrieve a single line of text from a text file in java, and indeed i got what i expect but at the end it adds a null reference, but i don't know why. here my code:
public class EncryptDecryptFile {
public void writeDecryptionFile(String message) {
File f;
FileWriter writeArchive;
try {
f = new File("C:\\Users\\Dell\\Training\\DecryptionFile.txt");
writeArchive = new FileWriter(f);
BufferedWriter bw = new BufferedWriter(writeArchive);
PrintWriter text = new PrintWriter(bw);
text.write(message+"\n");
text.close();
bw.close();
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
public String readEncryptionFile() {
File file = new File("C:\\Test\\EncryptionFile.txt");
String line = "";
try (
BufferedReader br = new BufferedReader(new FileReader(file))) {
while (true) {
line = br.readLine();
if (line != null) {
System.out.print(line);
} else {
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
return line;
}
public static void main(String[] args) {
EncryptDecryptFile file = new EncryptDecryptFile();
file.writeDecryptionFile("Hello World!!!");
System.out.println(file.readEncryptionFile());
}
}
The result is as follows
Hello World!!!
null
Where is that null coming from ?
I appreciate any help :(
You are returning line and printing it at the end of System.out.println(file.readEncryptionFile()); at that time it must be null (or the loop would not end). Solution, don't print it. Just do
file.readEncryptionFile();
Note: You also print with-in readEncryptionFile()
Do not do
System.out.println(file.readEncryptionFile());
You are already printing it out in this method, so just calling
file.readEncryptionFile();
should suffice.
Of course you do not need to return a String from this method.
Alternative in the readEncryptionFile, create a StringBuilder Object and append to that if the line is not null, then return the String of the StringBuilder Object.
I have spent the last week trying to figure out how to make this stupid code work. I have managed to get everything to work except for reading from my text file. It can read an individual integer on a line, but when given a line with multiple integers separated by spaces, it freaks out. Now I've gone and tried to fix it and the code won't even compile anymore. Only one line is causing problems.
I'm not good at coding, so I don't know where to begin. Yes, I've looked this up online. Yes, I've checked the forums. Yes, I have tried multiple different methods to make this work....
How do I fix this?? :(
ArrayList<Integer> list = new ArrayList<Integer>();
// the above line is in a different method in the same class, but it's relevant here
File file = new File("C:\\Users\\Jocelynn\\Desktop\\input.txt");
BufferedReader reader = null;
try
{
reader = new BufferedReader(new FileReader(file));
String text = null;
while ((text = reader.readLine()) != null)
{
// I want the following line to read "218 150 500 330", and to store each individual integer into the list. I don't know why it won't work :(
list.add(Integer.parseInt(src.next().trim()));
}
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
try
{
reader.close();
}
catch (IOException e)
{
e.printStackTrace();
}
//print out the list
System.out.println(list);
Thank you for the help! I'm sure that I'm just missing something really simple...
You can use a Scanner(String) like
while ((text = reader.readLine()) != null) {
Scanner scanner = new Scanner(text);
while (scanner.hasNextInt()) {
list.add(scanner.nextInt());
}
}
Of course, your entire method could be simplified by using a try-with-resources Statement and the diamond operator and just Scanner(File) like
public static void main(String[] args) {
File file = new File("C:\\Users\\Jocelynn\\Desktop\\input.txt");
List<Integer> list = new ArrayList<>();
try (Scanner scanner = new Scanner(file);) {
while (scanner.hasNextInt()) {
list.add(scanner.nextInt());
}
} catch (Exception e) {
e.printStackTrace();
}
// print out the list
System.out.println(list);
}
Do this inside the while loop
String[] individualArray = text.split(" ");//note space
for(String individual:individualArray){
yourList.add(individual);//You need to parse it to integer here as you have already done
}
In the above code, individualArray will contain each individual integers that are separated by space. And inside the for loop each string needs to be parsed to integer and then added to your list
try this :
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<Integer>();
File file = new File("C:\\Users\\Jocelynn\\Desktop\\input.txt");
BufferedReader reader = null;
try
{
reader = new BufferedReader(new FileReader(file));
String text = null;
while ((text = reader.readLine()) != null)
{
// you need only this for loop in you code.
for (String value : text.split(" ")) { // get list of integer
if(!value.equals("")) // ignore space
list.add(Integer.parseInt(value)); // add to list
}
}
} catch (FileNotFoundException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
try
{
reader.close();
} catch (IOException e)
{
e.printStackTrace();
}
// print out the list
System.out.println(list);
}
I have few text files. Each text file contains some path and/or the reference of some other file.
File1
#file#>D:/FilePath/File2.txt
Mod1>/home/admin1/mod1
Mod2>/home/admin1/mod2
File2
Mod3>/home/admin1/mod3
Mod4>/home/admin1/mod4
All I want is, copy all the paths Mod1, Mod2, Mod3, Mod4 in another text file by supplying only File1.txt as input to my java program.
What I have done till now?
public void readTextFile(String fileName){
try {
br = new BufferedReader(new FileReader(new File(fileName)));
String line = br.readLine();
while(line!=null){
if(line.startsWith("#file#>")){
String string[] = line.split(">");
readTextFile(string[1]);
}
else if(line.contains(">")){
String string[] = line.split(">");
svnLinks.put(string[0], string[1]);
}
line=br.readLine();
}
} catch (Exception e) {
e.printStackTrace();
}
}
Currently my code reads the contents of File2.txt only, control does not come back to File1.txt.
Please ask if more inputs are required.
First of all you are jumping to another file without closing the current reader and when you come back you lose the cursor. Read one file first and then write all its contents that match to another file. Close the current reader (Don't close the writer) and then open the next file to read and so on.
Seems pretty simple. You need to write your file once your svnLinks Map is populated, assuming your present code works (haven't seen anything too weird in it).
So, once the Map is populated, you could use something along the lines of:
File newFile = new File("myPath/myNewFile.txt");
// TODO check file can be written
// TODO check file exists or create
FileOutputStream fos = null;
OutputStreamWriter osw = null;
BufferedWriter bw = null;
try {
fos = new FileOutputStream(newFile);
osw = new OutputStreamWriter(fos);
bw = new BufferedWriter(osw);
for (String key: svnLinks.keySet()) {
bw.write(key.concat(" my separator ").concat(svnLinks.get(key)).concat("myNewLine"));
}
}
catch (Throwable t) {
// TODO handle more gracefully
t.printStackTrace();
if (bw != null) {
try {
bw.close();
}
catch (Throwable t) {
t.printStackTrace();
}
}
Here is an non-recursive implementation of your method :
public static void readTextFile(String fileName) throws IOException {
LinkedList<String> list = new LinkedList<String>();
list.add(fileName);
while (!list.isEmpty()) {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(new File(list.pop())));
String line;
while ((line = br.readLine()) != null) {
if (line.startsWith("#file#>")) {
String string[] = line.split(">");
list.add(string[1]);
} else if (line.contains(">")) {
String string[] = line.split(">");
svnLinks.put(string[0], string[1]);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
br.close();
}
}
}
Just used a LinkedList to maintain the order. I suggest you to add some counter if you to limit the reading of files to a certain number(depth). eg:
while (!list.isEmpty() && readCount < 10 )
This will eliminate the chance of running the code to infinity(in case of circular reference).
I was wondering how do you manipulate big Textfiles in Java, if we assume that the Filesize is larger than the memory. I googled that topic and it shows that most people recommend java.niofor such a task.
Unfortunately I haven't found any documentation on how to manipulate the File. For example read every Line, modify it, write it. I tried something like this, but this doesn't work:
FileChannel fileChannel = null;
try {
fileChannel = new RandomAccessFile(file, "rw").getChannel();
ByteBuffer buffer = ByteBuffer.allocate(256);
while (fileChannel.read(buffer) != -1) {
buffer.rewind();
buffer.flip();
String nextLine = buffer.asCharBuffer().toString();
if (replaceBackSlashes) {
nextLine = nextLine.replace("\\\\", "/");
}
if (!(removeEmptyLines && StringUtils.isEmpty(nextLine))) {
buffer.flip();
buffer.asCharBuffer().put(nextLine);
}
buffer.clear();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (fileChannel != null) {
try {
fileChannel.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
So what are your recommendations? Also the String nextline, doesn't match anything in my File. Maybe I need to set the encoding?
Line by line. Something like this ...
public static void main(String[] args) throws Exception {
File someFile = new File("someFile.txt");
File temp = File.createTempFile(someFile.getName(), null);
BufferedReader reader = null;
PrintStream writer = null;
try {
reader = new BufferedReader(new FileReader(someFile));
writer = new PrintStream(temp);
String line;
while ((line = reader.readLine())!=null) {
// manipulate line
writer.println(line);
}
}
finally {
if (writer!=null) writer.close();
if (reader!=null) reader.close();
}
if (!someFile.delete()) throw new Exception("Failed to remove " + someFile.getName());
if (!temp.renameTo(someFile)) throw new Exception("Failed to replace " + someFile.getName());
}
Kudos to xagyg for a nice, clean answer! The following just didn't fit into a comment:
If you're running Java 7 already, you can save a lot of boilerplate code by using try-with-resources for the processing loop:
File source = ...
File target = ...
try (BufferedReader in = new BufferedReader(new FileReader(source));
PrintStream out = new PrintStream(target)) {
String line;
while ((line = in.readLine()) != null) {
// manipulate line
out.println(line);
}
}
// no catch or finally clause!
No more of that initalize-to-null-try-catch-finally-close-if-not-null mess, Java will take care of that for you now. Less code, less potential to forget or screw up that crucial call to close().
I'm sure there is a fairly simple answer to this question, so here we go.
I'm trying to use a FileWriter to write text to a file. My program reads text in from an already existing file, specified by the user and then asks whether to print the text to the console or to a new file, also to be named by the user.
I believe my problem is with passing the FileWriter to the "FileOrConsole" method. Am I not passing or declaring the FileWriter in the "FileOrConsole" method correctly? The file is always created but nothing is written to it.
Here is the code:
import java.io.*;
import java.util.*;
public class Reader {
public static void main(String[] args) throws IOException {
Scanner s = null, input = new Scanner(System.in);
BufferedWriter out = null;
try {
System.out.println("Would you like to read from a file?");
String answer = input.nextLine();
while (answer.startsWith("y")) {
System.out.println("What file would you like to read from?");
String file = input.nextLine();
s = new Scanner(new BufferedReader(new FileReader(file)));
System.out
.println("Would you like to print file output to console or file?");
FileOrConsole(input.nextLine(), s, input, out);
System.out
.println("\nWould you like to read from the file again?");
answer = input.nextLine();
}
if (!answer.equalsIgnoreCase("yes")) {
System.out.println("Goodbye!");
}
} catch (IOException e) {
System.out.println("ERROR! File not found!");
// e.printStackTrace();
} finally {
if (s != null) {
s.close();
}
if (out != null) {
out.close();
}
}
}
public static void FileOrConsole(String response, Scanner s, Scanner input,
BufferedWriter out) {
if (response.equalsIgnoreCase("console")) {
while (s.hasNext()) {
System.out.println(s.nextLine());
}
} else if (response.equalsIgnoreCase("file")) {
System.out.println("Name of output file?");
response = input.nextLine();
try {
out = new BufferedWriter(new FileWriter(response));
} catch (IOException e) {
e.printStackTrace();
}
while (s.hasNext()) {
try {
out.write(s.nextLine());
out.newLine();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
} else {
System.out.println("Sorry, invalid response. File or console?");
response = input.nextLine();
FileOrConsole(response, s, input, out);
}
}
}
you make classic error forgetting that parameters passed by value in case of java it is a value of the reference. The thing is that your assignment
out = new BufferedWriter(new FileWriter(response));
actually does not change the variable declared in main() it stays null
BufferedWriter out = null;
and then in finally it skips the close() by the if(out==null)
and as it is Buffered and you do no flush nothing is written to file.
what you got to do is out.close(); in side the FileOrConsole method call
OR
do the out = new BufferedWriter(new FileWriter(response));
outside of it. You choose :-)
Try flushing your stream, but more importantly, remember to close it.
Here's a code example of recommended practice for handling streams. Same approach can be used for input streams too and things like database code where it's important to always clean up after yourself to get the expected results.
BufferedWriter out = null;
try {
out = // ... create your writer
// ... use your writer
} catch(IOException ex) {
// maybe there was a problem creating or using the writer
} finally {
if (null != out) {
out.flush();
out.close();
out = null;
}
}