This is a quick one that stumps me. I've got a Java Program with the following code:
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
String file1 = args[0];
String file2 = args[1];
String output = args[2];
Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(output), "utf-8"));
// Get the file
BufferedReader br1 = new BufferedReader(new FileReader(file1));
ArrayList<String> masterRBT = new ArrayList<String>();
// Read the files
while(br1.readLine() != null) {
masterRBT.add(br1.toString());
System.out.println(br1.toString());
}
Read the file (in this case, a .csv), and output it to the command line.
I use the command line to run the program, plus three parameters, using so (it only really uses the first one):
java -jar csvdiff.jar mainfile.csv subfile.csv output.csv
But then, it returns this:
java.io.BufferedReader#17dfafd1
Repeatedly, as if on loop. I tried putting in a Try/Catch error, but it still does the same - no errors. I've opened the .csv files, and verified its contents.
The CSV files are located in the same directory as the .jar file.
What am I missing?
because you are attempting to print an instance of BufferedReader not the data you are reading from it
Change
while(br1.readLine() != null) {
masterRBT.add(br1.toString());
System.out.println(br1.toString());
}
to
while((String line = br1.readLine()) != null) {
masterRBT.add(line);
System.out.println(line);
}
You're printing out br1.toString() - you're calling toString() on the BufferedReader itself. BufferedReader doesn't override toString(), so you're getting the implementation from Object, as documented:
The toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character #, and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of:
getClass().getName() + '#' + Integer.toHexString(hashCode())
That's not what you want. Presumably you actually want to print out the line that you've just read - but you've thrown that away by now. You want:
String line;
while((line = br1.readLine()) != null) {
masterRBT.add(line);
System.out.println(line);
}
Or as a for loop:
for (String line = br1.readLine(); line != null; line = br1.readLine()) {
masterRBT.add(line);
System.out.println(line);
}
As a general matter, if you start seeing ClassName#Number in output, that's almost certainly a similar problem of calling toString() on an object which doesn't override it.
You are not printing the line but the reader itself, to print the line change your code like this:
// Read the files
String line;
while((line = br1.readLine()) != null) {
masterRBT.add(line);
System.out.println(line);
}
Use this,
String str;
while((str=br1.readLine()) != null) {
masterRBT.add(str);
System.out.println(str);
}
Because BufferedReader.toString() just returns the class name and hash value of the object.
Use BufferedReader.readLine() to get the String instead.
Related
First off I am new at coding in java. I have done extensive research prior to posting this question but have not found the exact answer to my question. I am sure it is my lack of experience, but any assistance the community can provide would be much appreciated.
I am trying to debug a utility class that I have coded. The code is working except for the bit about adding a new line to the substituted text.
Here is the piece of code that is generating an error in NetBeans IDE. The error is incompatible types: Boolean can't be converted to int
try (BufferedWriter bw = new BufferedWriter(new FileWriter (NewCSVFile),true))
What I am trying to do is get this code to read a CSV text file, substitute and the write the new csv data to a new file but preserve the original new lines in the file. And, I want to ensure that the method used is platform independent thus why I am using BufferedWriter.
Here is all the code for your review.
public class TxtFileConverter {
public static void main (String[] args) {
// Location of the file you want to work with.
File CSVFile = new File("/Users/data.csv");
File NewCSVFile = new File("/Users/NewData.csv");
String search = "[,](?!\\w)";
String replace = ",0";
try{
FileReader fr = new FileReader(CSVFile);
String s;
String totalStr = "";
try (BufferedReader br = new BufferedReader(fr)) {
while ((s = br.readLine()) != null) {
totalStr += s;
}
totalStr = totalStr.replaceAll(search, replace);
try (BufferedWriter bw = new BufferedWriter(new FileWriter
(NewCSVFile),true)) {
bw.write(totalStr);
bw.newLine();
}
}
}catch(IOException e){
}
}
}
I think you are trying to read some lines from a file and write it to another file. In the output file, you get all the code in a single line.
I think the bug is in this piece of code.
while ((s = br.readLine()) != null) {
totalStr += s;
}
If you add a statement to add a new line character after reading a line from input file, you should get the desired output.
while ((s = br.readLine()) != null) {
totalStr += s;
totalStr += "\n";
}
The following code adds a newline character at the end of the file.
bw.newLine();
What do you think that true argument is doing in the BufferedWriter constructor? The second and optional argument is the buffer size, an integer. You probably don't even need to supply that argument unless you're doing something rather odd.
try (BufferedWriter bw = new BufferedWriter(new FileWriter(NewCSVFile)))
BufferedWriter has only two constructors:
public BufferedWriter(Writer out) //sz = defaultCharBufferSize = 8192
public BufferedWriter(Writer out, int sz) //sz Output-buffer size, a positive integer
There is no option with second boolean argument. I recommend to use first constructor in your case.
I'm trying to learn java and this is the method of this employee project i'm trying to learn, I need to take in a file ( which i have and it works because I can print the results ) and assign the correct lines to either a technician object or a salesman object, noted by a leading T or S in the beginning of the line like :
For a Technician : T,String,int,int,String, for the appropriate fields.
For a Salesman : S,String,int,double,String, for the appropriate fields.
file.txt
S,Mohamed,274533,56000.0,CEO,
T,Mike,19283748,2,CFO,
So once it reads each line it should put it in either a Salesman Object or Technician Object. So far i can just output the file as is. How do I assign it and then return an Employee array?
public Object[] loadArray(String fileName) throws IOException {
String line = null;
BufferedReader bufferedReader = null;
bufferedReader = new BufferedReader(new FileReader(fileName));
while ((line = bufferedReader.readLine()) != null) {
list.add(line);
System.out.println(line);
}
if (bufferedReader != null) {
bufferedReader.close();
}
return employees;
}
You can just split each line using the comma as a delimiter
eg.
String[] tokens = line.split(",");
You can then assign each token as needed.
I have a function.
public ArrayList<String> readRules(String src) {
try (BufferedReader br = new BufferedReader(new FileReader(src))) {
String sCurrentLine;
while ((sCurrentLine = br.readLine()) != null) {
System.out.println(sCurrentLine);
lines.add(sCurrentLine);
}
} catch (IOException e) {
e.printStackTrace();
}
return lines;
}
My file have 26.400 lines but this function just read 3400 lines at end of file.
How do I read all lines in file.
Thanks!
Why don't you use the utility method Files.readAllLines() (available since Java 7)?
This method ensures that the file is closed when all bytes have been read or an IOException (or another runtime exception) is thrown.
Bytes from the file are decoded into characters using the specified charset.
public ArrayList<String> readRules(String src) {
return Files.readAllLines(src, Charset.defaultCharset());
}
while ((sCurrentLine = br.readLine()) != null)
It is likely that you have an empty line or a line that is treated as null.
Try
while(br.hasNextLine())
{
String current = br.nextLine();
}
Edit: Or, in your text file, when a line is too long, the editor automatically wraps a single line into many lines. When you don't use return key, it is treated as a single line by BufferedReader.
Notepad++ is a good tool to prevent confusing a single line with multiple lines. It numbers the lines with respect to usage of return key. Maybe you could copy/paste your input file to Notepad++ and check if the line numbers match.
You can also cast into a List of strings using readAllLines() and then loop through it.
List<String> myfilevar = Files.readAllLines(Paths.get("/PATH/TO/MY/FILE.TXT"));
for(String x : myfilevar)
{
System.out.println(x);
}
So I tracked down the bugger, but I am no closer to understanding what is wrong. Here is what the compiler says:
Exception in thread "main" java.lang.NullPointerException at
BasicFile.Search(BasicFile.java:215) at
TestFile.main(TestFile.java:42)
Line 215 is the one that starts with while, first one.
String Search(String key) throws IOException {
int lines = 0;
String line = "";
String foundAt = "";
BufferedReader BF = new BufferedReader(new FileReader(f));
try {
while ((line = BF.readLine().toLowerCase()) != null) {
lines++;
//create tokenizer words with what is in line
StringTokenizer words = new StringTokenizer(line);
while(words.hasMoreTokens()) { //while words has tokens left
//go to next token and compare to key
if (words.nextToken().equals(key.toLowerCase()))
foundAt = foundAt + "\n" + lines + ":" + line;
//do nothing continue loop
}
}
BF.close();
} catch(FileNotFoundException e) {
}
return foundAt;
}
When your buffer reader runs out of lines it returns null. You are trying to call toLowerCase method on null which ends up throwing the null pointer exception.
Refactor your code in a way that it doesn't require you to execute toLowerCase before ensuring the line is non-null.
For example:
String next;
while ((next = BF.readLine()) != null) {
String line = next.toLowerCase();
// ...
}
while ((line = BF.readLine().toLowerCase()) != null)
What happens if BF.readline() returns null?
remove .toLowerCase() from the test
Please, stop it, your code is giving me cancer! There are a number of stylistic errors in the code that you need to fix.
First off in java, method names always begin with a lowercase letter. You are programming in Java, not C#, so you need to use the Java naming conventions. That means your method should be called search, not Search.
The same goes for variable names. What is BF supposed to mean, anyway? Replace it with in, please.
Next up, unless this method is in an object that itself represents that particular file, the global variable f should be passed as a parameter instead.
BufferedReader is AutoCloseable, so you should use a try-with-resources to deal with closing it.
You need to add a javadoc comment to it, documenting its parameters with #param, its return with #return, and exactly why it might need to throw an IOException with #exception.
Here is a mostly-fixed version of your code:
/**
* Needs Javadoc
*/
String search(String key, File f) throws IOException {
int lines = 0
String line = "";
String foundAt = "";
try(BufferedReader in = new BufferedReader(new FileReader(f)) {
while ((line = in.readLine().toLowerCase()) != null) { //the line in question
lines++;
StringTokenizer words = new StringTokenizer(line);
while(words.hasMoreTokens())
if (words.nextToken().equals(key.toLowerCase()))
foundAt = foundAt + "\n" + lines + ":" + line;
}
} catch(FileNotFoundException e){}
return foundAt;
}
Now, the problem here is that in.readline() returns a null sometimes. Calling a method on a null is always a NullPointerException. Therefore you get a NullPointerException when you attempt to call that null's missing toLowerCase() method.
You need to convert it toLowerCase after you ensure it is non-null.
I am currently learning Java and I have faced this problem where I want to load a file that consists a huge number of lines (I am reading the file line by line ) and the thing I want to do is skip certain lines (pseudo-code).
the line thats starts with (specific word such as "ABC")
I have tried to use
if(line.startwith("abc"))
But that didn't work. I am not sure if I am doing it wrong, that's why I am here asking for a help, below part of the load function:
public String loadfile(.........){
//here goes the variables
try {
File data= new File(dataFile);
if (data.exists()) {
br = new BufferedReader(new FileReader(dataFile));
while ((thisLine = br.readLine()) != null) {
if (thisLine.length() > 0) {
tmpLine = thisLine.toString();
tmpLine2 = tmpLine.split(......);
[...]
Try
if (line.toUpperCase().startsWith("ABC")){
//skip line
} else {
//do something
}
This will converts the line to all the Upper Characters by using function toUpperCase() and will check whether the string starts with ABC .
And if it is true then it will do nothing(skip the line) and go into the else part.
You can also use startsWithIgnoreCase which is a function provided by the Apache Commons . It takes the two string arguments.
public static boolean startsWithIgnoreCase(String str,
String prefix)
This function return boolean.
And checks whether a String starts with a specified prefix.
It return true if the String starts with the prefix , case insensitive.
If the case isn't important try using the StringUtils.startsWithIgnoreCase(String str,
String prefix) of Apache Commons
This function return boolean.
See javadoc here
Usage:
if (StringUtils.startsWithIgnoreCase(line, "abc")){
//skip line
} else {
//do something
}
If you have large a input File, you code will create a OutOfMemoryError. there is nothing you can do against it without editing te code (adding more memory will fail, if the file gets bigger).
I beleave you store the selected lines in memory. If the file gets lager (2GB or so) you'll have 4GB in memory. (The old Value of the String and the new one).
You have to work with streams to solve this.
Create a FileOutpuStream, and write the selcted line into that Stream.
Your method must be changed. For a large input yo cannot return a String:
public String loadfile(...){
You can return a Stream or a file.
public MyDeletingLineBufferedReader loadFile(...)
you can use:
BufferedReader br = new BufferedReader(new FileReader("file.txt"));
String lineString;
try{
while((lineString = br.readLine()) != null) {
if (lineString.toUpperCase().startsWith("abc")){
//skip
} else {
//do something
}
}
}
or
static boolean startsWithIgnoreCase(String str, String prefix) method in org.apache.commons.lang.StringUtils like below.
BufferedReader br = new BufferedReader(new FileReader("file.txt"));
String lineString;
try{
while((lineString = br.readLine()) != null) {
if (StringUtils.startsWithIgnoreCase(lineString, "abc")){
//skip
} else {
//do something
}
}
}