I've been working on this app in Android for a while now and suddenly encountered the following issue even though it has not been a problem many times before.
I am reading a CSV file in Java, but when I print a log of each line of that CSV file, there appears to be a blank line even though there is not one in the actual CSV file.
This is how I'm reading the file:
InputStreamReader inputStreamReader;
try {
inputStreamReader = new InputStreamReader(getActivity().getAssets().open("My_file.csv"));
Scanner inputStream = new Scanner(inputStreamReader);
inputStream.nextLine(); // Ignores the first line
while (inputStream.hasNext()) {
String data = inputStream.nextLine(); // Gets a whole line
String[] line = data.split(","); // Splits the line up into a string array
array.add(line[1]);
}
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
When I run it, I get an ArrayIndexOutOfBoundsException and after putting in a log message before array.add(line[1]) which printed the line, I found that there was a blank line in my CSV file (and there wasn't when I checked it).
Any ideas?
First of All:
array.add(line[1]) is going to throw an ArrayIndexOutOfBoundsException every time you have a line without a , ... Might be a good idea to check for that before trying to read it. i.e. if(line.length > 1) { array.add(line[1]);}
Just doing this will fix multiple errors for you.
Related
I am trying to create an authentication system of sorts that uses a file called Users.dat to store user data. Currently, I am developing a method to remove users by rewriting the Users.dat file, omitting the user specified. The code below works in a basic environment with an all-encompassing directory containing the .java files and the Users.dat file in the same spot. The old Users.dat file is deleted and Users.dat.tmp is renamed to User.dat. (No problems here, everything works as intended).
public static boolean RemoveUser(String userName) {
// TODO remove username from Users.dat
try {
File originalFile = new File("Users.dat");
System.out.println(originalFile.getAbsolutePath());
BufferedReader read = new BufferedReader(new FileReader("Users.dat"));
String line = null;
while ((line = read.readLine()) != null) {
if (line.indexOf(userName) != -1) {
break;
}
}
String[] userInfo = line.split(", ");
if (!userName.equals(userInfo[2])) {
System.out.println("Username not found. No users removed.");
read.close();
return false;
}
File tempFile = new File(originalFile.getAbsolutePath() + ".tmp");
PrintWriter print = new PrintWriter(new FileWriter(tempFile));
String lineToRemove = line;
BufferedReader read2 = new BufferedReader(new FileReader("Users.dat"));
while ((line = read2.readLine()) != null) {
if (!line.trim().equals(lineToRemove)) {
print.println(line);
print.flush();
}
}
print.close();
read.close();
read2.close();
System.out.println(originalFile.getAbsolutePath());
originalFile.delete(); //This line is not executing correctly
tempFile.renameTo(originalFile); //Nor is this line
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
return true;
}
Users.dat file format:
Joe, Last, jlast, 58c536ed8facc2c2a293a18a48e3e120, true
Sam, sone, samsone, 2c2a293a18a48e3e12058c536ed8facc, false
Jane, Best, jbest, 293a18a48e3e12052058c536ed8facc2c, false
Andrew, Estes, Aestes, 63a490d69aa544fd1272a976014ad570, true
Test, User, tuser, 63a490d69aa544fd1272a976014ad570, true
I have two System.out.println(originalFile.getAbsolutePath()) statements, one at the beginning, one at the end to make sure the path isn't getting screwed up in the process of everything somehow.
Like I said, the code works, however, when I try to implement it in my project, it creates the Users.dat.tmp and it writes the correct data to it, but it does not delete the old Users.dat file, nor does it rename the Users.dat.tmp file to replace Users.dat. I'm certain the directory is correct, as I am literally displaying it as the code executes. I can't figure out any other reason why originalFile.delete() and tempFile.renameTo(originalFile) aren't functioning properly.
EDIT:
Using java.nio.file, I was able to produce an error message. it reads:
java.nio.file.FileSystemException: C:\Path\Users.dat: The process cannot access the file because it is being used by another process.
I don't have the file open when this error message is shown, and I don't get this error using java.nio in my testing environment mentioned at the beginning. I'm not sure what other process the message is referring to.
EDIT 2:
I tried running the code on other machines, one a Mac, the other a Windows laptop, and the code functioned on the Mac just fine, but I was still seeing the same issue on the Windows laptop.
I had the similar issue. My problem was not closing all the streams I read and written to the file. Thanks for your Edit #1, that was helpful
When you wrap
BufferedReader read = new BufferedReader(new FileReader("Users.dat"));
don't you need to close the inner readers too?
If not for the author, but for those who stambled upon this question (like me), hope this suggestion will be useful
I had an earlier function that I was calling in main that was accessing Users.dat, but I never closed the BufferredReader in that function.
I have two csv files.
CSV File1=csvFrom, //It has two columns, column1=Email(only 5 emails), Column2=Password
CSV File2=csvSendTo //It has only one column = Email. (Thousands of emails).
I am trying to read csvFrom file, I want first email id and its password from first file. Then 20 emails from second csvSendTo file. Want to send emails from first email id and password to these 20 emails. I am able to send email manually with one email id. But when I tried to read it from csv file, its giving me a NullPointerException. Below is my code:I am just pasting the part over here which is giving me an error. Can anyone guide me here? This for loop is wrong here but I am bit confused,so not able to replace with accurate loop.
BufferedReader br1=null;
BufferedReader br2=null;
String line1="",line2="";
String csvSplitBy=",";
String strMailFrom="",strPassword="";
int countCSVFrom=0,countCSVSendTo=0;
System.out.println("strCSVFrom=" + strCSVFrom + ", strcsvSendTo=" + strCSVSendTo);
try{
br1=new BufferedReader(new FileReader(strCSVFrom));
br2=new BufferedReader(new FileReader(strCSVSendTo));
String[] strarrFromEmail;
while((line1=br1.readLine())!=null){
countCSVFrom+=1;
strarrFromEmail=line1.split(csvSplitBy);
// for(int i=countCSVFrom-1;i<=countCSVFrom;i++){
// strMailFrom=strarrFromEmail[i];
// strPassword=strarrFromEmail[i+1]; //While here its ArrayIndexOutOfBounds Exception
// }
//what is the correct thing to write it over here instead of for loop?
}
System.out.println("countcsvfrom="+countCSVFrom + ", line1=" + line1.toString()); //Giving me an error of NullPointerException over here.
System.out.println("strFrom="+strMailFrom + ", strPassword="+strPassword);
while((line2=br2.readLine())!=null){
countCSVSendTo+=1;
}
System.out.println("countcsvsendto="+countCSVSendTo);
}catch(FileNotFoundException fnfe){
fnfe.printStackTrace();
}catch(IOException ioe){
ioe.printStackTrace();
}
The second System.out.println, just after the closing brace of the first while loop, gives the NPE. It uses line1, which the terminating condition of said while loop guarantees will be null at that point.
You could write:
//your code here and try catch block below
try {
List<String[]> csvLines = new ArrayList<String[]>();
Files.lines(Paths.get(strCSVFrom)).map(e -> e.split(csvSplitBy)).forEach(csvLines.add(e));
} catch (Exception) {
//exception handling
}
Im trying to read deck.txt which is in the src directory of the application.
The error I get is:
Exception in thread "main" java.lang.NullPointerException
at Deck.(Deck.java:15)
at TwentyOne.main(TwentyOne.java:7)
Line 7 in TwentyOne is just:
Deck deck = new Deck();
The file has a single integer on each line and is 104 lines long.
Where cards[i].suit.... is the line throwing the exception
try (BufferedReader br = new BufferedReader(new FileReader("src/deck.txt"))) {
for (int i = 0; i < 104; i++) {
cards[i].suit = Integer.parseInt(br.readLine());
cards[i].rank = Integer.parseInt(br.readLine());
}
} catch (IOException e) {
e.printStackTrace();
}
To try see what was wrong I copied this code out of eclipse into another directory with the file, this time just println(br.readLine()) rather than assigning it to the array and it worked fine.
Have I got the file in the wrong location or is there something else I'm missing?
Thanks for your help
You are attempting to read 208 lines from your 104-line file. Each time you call br.readLine() the next line is read.
I'm assuming the format of the file is alternate lines for suit and rank, so try reducing the number of iterations to 52.
Edit:
From the comments, the card array was declared but the card objects not initialised. Initialising the objects in the array before use fixed the NullPointerException.
The code below reads from a file 'helpFile.txt' and checks for an index represented by '#'.
The variable read from the file is stored in the integer c and compared with '#' if the read character is '#' without casting the integer into character. I want to know if the comparison is valid as the compiler is not showing any error.
Also, suppose '#' is found by the program in the file and a string called 'topic' immediately follows '#' and it is read using readLine(). Will the 'String info = br.readLine()' be just 'topic' or '#'+'topic'?
Sorry for such a lengthy question. Help much appreciated.
boolean helpOn(String what){
private BufferedReader br;
private String info, topic;
private static PrintWriter pw = new PrintWriter(System.out, true);
int c;
br = new BufferedReader(new FileReader("helpFile.txt"));
try{
do{
//read characters until '#' is found
c = br.read();
if(***c=='#'***){ //check if the character is '#'
pw.println(c);
if((**topic=br.readLine()**).equalsIgnoreCase(what)){ //check if 'what' string is equal to 's' which is the string after '#'
while((info=br.readLine())!=null){ //print info until the end of info
if(info!=null)
pw.println(info);
}
return true;
}
}
}
while(c!=-1);
}
catch(IOException ex){
pw.println("File error.");
ex.printStackTrace();
try{
br.close();
}
catch(IOException e){
pw.println("Error closing file.");
e.printStackTrace();
}
return false;
}
try{
br.close();
}
catch(IOException ex){
pw.println("Error closing file.");
ex.printStackTrace();
}
return false; //topic not found
}
I tried your code, it is woking fine with me, i think u need to check your "helpFile.txt". i used this in it.
adad#hello
howareyou
and this is the outout i am getting.
c: 35
topic: hello
info: howareyou
i printed all the three vars u used. c, topic, info.
Now since you are using readline() after reading a character, u must give your "info" from next line in "helpFile.txt"
info will contain anything after topic, as you are using readline() function, it will go to the next line. try with my example.
As soon as "#" is encountered, your var
C will have "#" (35).
then
topic will have anything after the "#" till the end of line, because of readline();
then
info will have the next line after topic.
If you format your helpFile.txt properly, this will work fine
EDIT
i have to specify the full file name everytime
You are using eclipse, and you are saving the file in the "SRC" folder i guess. Save them in your Project folder. just one above the SRC folder and then do this.
br = new BufferedReader(new FileReader("helpFile.txt"));
it should work.
EDIT2
you don't need to check info for null twice
while((info=br.readLine())!=null){
//print info until the end of
// if(info!=null) noT needed, u alreay did that above
pw.println("info"+info);
}
If it is NULL, it will automatically come out of loop.
EDIT3
i don't want to print all the texts
As you used # to mark the begining of the block, you could use anything to mark the end of it. eg
helpFile.txt
adad#hello
howareyou
$
Other text here
blah blah blah...
...
Now, you can modify your while as:
while(!(info=br.readLine()).equals("$")){
pw.println("info"+info);
}
The loop will exit as soon as it gets "$", and it won't print anything after that.
You may wanna read the javadoc for the class you are using (BufferedReader), it can be found here, but i think it's ok to compare the characters with == because a char is really a numeric type. But i suggest you read more about enconding, because i think FileReader will use the default plataform encoding to read your file and that may not be your file encoding. It's always good practice to inform the encoding of the file.
About the second question, acoording to javadoc (again), it will read the entire line (not from the point you read the char). Hope that helps, i'm goona try to run this later to see the results
I am working through an assignment and have run into a few snags.
My program prints output to the screen, (not how I need it yet) but only prints the first entry to the file. Below is a snippet of the code. The file appears to be reading in the data from the input file, but the loop does not output to the file past the first entry.
Scanner in = new Scanner(System.in); //Scanner object to read input from the file
System.out.println("Enter filename to read "); //file name prompt
String inputFileName = in.nextLine(); //line input reads next line
/*
* TODO 2) Use an unbuffered file input stream to open listings.txt file
* and read in property listings.
*/
Scanner reader = null;
try {
reader = new Scanner(new File(inputFileName));
} catch (FileNotFoundException e) {
System.out.println("Try Again"); //error window if name is null
JOptionPane.showMessageDialog(null, "You must enter a filename", "File input error", JOptionPane.ERROR_MESSAGE);
return;
}
PrintWriter out = new PrintWriter("agentreport.txt"); //This method prints out the file readfile.txt a word at a time
while (reader.hasNextLine()) { //It needs to output to the text file. Currently a file is created, but it is empty?
Scanner s2 = new Scanner(reader.next());
#SuppressWarnings("unused")
boolean b;
while (b = s2.hasNext()) {
String output = s2.next();
String output2 = output.toUpperCase(); //converts output to upper case
System.out.println(output2);
out.print(output2); //only printing the first entry to the agentsreport.txt file. Not stepping thru the file for some reason?
}
Even if you are using automatic flushing, which you aren't in this case, the PrintWriter object would output anything in its internal buffer unless you do one of two things:
1) Use the println(), printf(), or format() to methods
2) Make a call to the flush() method every time you print, this way all of the data in the internal buffer gets written out.
Note: The print() method does not cause the PrintWriter object to flush() its buffer.
try adding a call to flush() after you call print()
Example of split()
PrintWriter out = new PrintWriter("agentreport.txt");
while (reader.hasNextLine()) {
String words = reader.nextLine().split();
#SuppressWarnings("unused")
boolean b;
for(String word : words) {
String output = word ;
String output2 = output.toUpperCase(); //converts output to upper case
System.out.println(output2);
out.print(output2);
}
One thing that immediately jumps out is that you aren't handling your resources properly.
Any time you use an IO resource such as a reader/database connection/etc., you should always close it using a finally block, using this sort of pattern:
Reader reader = /* construct it however */
try {
/* do something with the reader */
}
finally {
reader.close();
}
If you don't do this, there's no guarantee that the reader will actually be closed, and your application will leak file descriptors/connection pool connections/etc., until eventually it won't be able to get hold of any more and your app crashes. (This won't always have fatal consequences, but it's such a straightforward pattern you should use it every time until it becomes automatic).
In this case, you aren't closing your writer at all, which means that it's not guaranteed that it ever actually flushes its output to the file. It would be perfectly in accordance with the Writer interface for it to write everything or nothing - without the flush, you have no guarantees. Note that closing the writer will automatically call flush, so that's the best bet once you're done with it.
So the latter part of your code should look like:
PrintWriter out = new PrintWriter("agentreport.txt");
try {
// Existing code here
}
finally {
// This closes the file and frees the descriptor, but also flushes the buffers
out.close();
}
Also, how are you handling the IOExceptions that can be thrown by the reading and writing? Are you catching them and swallowing them somewhere? If so, it's possible that your code is throwing an exception telling you exactly why it can't write, and you're just ignoring it and then looking puzzled.
Not to put too fine a point on it, error handling is probably the most significant part of good software development. It's not too hard to write software that works when everything's fine; the most challenging part is handling things well when you run out of space on the hard drive, or the network is temporarily down, etc.
In this case the most pragmatic approach would be to just let the exception be thrown out of the top of your main method. In this case your application will "crash", and you'll get a stacktrace + error message on the console, which will make it immediately clear that something went wrong, and give you a very good idea of what it was.
try
out.println(output2);
http://docs.oracle.com/javase/6/docs/api/java/io/PrintWriter.html
also I'd use a var other than "out" as when system.out is imported to use the shortcode 'out.println()', this could cause variable confusion
edit: good point #Hunter McMillen, changed to println as append is for a CharSequence.
try (
Scanner reader = new Scanner(new File(inputFileName));
PrintWriter writer = new PrintWriter(new FileOutputStream("agentreport.txt"), true);
) {
while (reader.hasNextLine()) {
String output = reader.nextLine().toUpperCase();
System.out.println(output);
writer.println(output);
}
} catch (FileNotFoundException e) {
System.out.println("Try Again"); //error window if name is null
JOptionPane.showMessageDialog(null, "You must enter a filename", "File input error", JOptionPane.ERROR_MESSAGE);
}