I have a question about a school assignment I need to do it in Java.
I need to load data from a file and check for errors in these files.
I read the file with a bufferedReader which works perfectly until the end of the file: it ignores the last line if that line is empty.
I know how to check for empty lines, but the last line simply doesn't give any result using the readLine() function of bufferedReader.
It's important that I know if the last line is empty as it must be. If the empty line doesn't exist, it should give an error.
So long story short, I need a way to tell the difference between the following situations (where CRLF is the end of the line):
Situation 1 (correct):
line x CRLF
line y CRLF
Situation 2 (wrong):
line x CRLF
line y
Both of these situations will return a null on readline() after line y.
I am counting the lines of the file on the way, so if I have a line counter (Note: that counter must count that empty line too, all the ones I found did not count them)
The files contain empty lines throughout too, if that should make any difference for the code I need (these lines are properly detected as they should be as the EOF isn't on these lines)
Note that the program works with or without that last line, it's purely that the assignment tells me to give an error if it's not there.
If you want to determine if the last line has a CRLF you can read from the end.
public static boolean lastLineisCRLF(String filename) {
RandomAccessFile raf = null;
try {
raf = new RandomAccessFile(filename, "r");
long pos = raf.length() - 2;
if (pos < 0) return false; // too short
raf.seek(pos);
return raf.read() == '\r' && raf.read() == '\n';
} catch (IOException e) {
return false;
} finally {
if (raf != null) try {
raf.close();
} catch (IOException ignored) {
}
}
}
There is no empty line in your "situation 1". The CRLF belongs to line y and after that, there is nothing (which is what readline() tells you too).
It's just that in an editor, this CRLF tells the cursor to go one line down, so it looks like a new, empty line there, but in fact that's just an 'optical illusion' caused by the editor interpreting the characters CR/LF as a hint to show the cursor in a new line.
while ((tmp = br.readLine()) != null) {
strLine = tmp;
}
String lastLine = strLine;
This would give you the last Line of the file. Why not check if the last line is empty or not ?
Related
So, I am writing a program where I am reading from a file one character at a time, doing an operation with the character, then writing the output to a different file.
For some reason I get a different result when I hard code the file path (I did that just so I didn't have to keep typing the file while debugging) and when I pass the files from the command line.
When I pass the file from the command line it will skip input lines sometimes, so if I had a file with 10 lines I may only get 8 lines being processed.
I have a feeling it has something to do with whether or not there are spaces at the end of the input lines but I can't seem to figure it out. Any help would be much appreciated.
Also, I was using NetBeans when I hardcoded the file path, and ran the program from the terminal when I used command-line arguments. I have pasted the I/O code below.
while( ( i = buffRead.read() ) != -1 )
{
try
{
char c = (char) i;
if ( Character.isWhitespace(c) )
{
if(converter.getStackSize() > 1)
{
converter.resetConverter();
throw new IncorrectNumOfOperandsException();
}
buffRead.readLine();
converter.resetConverter();
writeOut.println();
}
else
{
converter.register( c );
}
}
catch (InvalidCharException j)
{
writeOut.println("Invalid Character Entered\n");
buffRead.readLine();
}
catch (IncorrectNumOfOperatorsException k)
{
writeOut.println("Too Many Operators for Number of Operands\n");
buffRead.readLine();
}
catch ( IncorrectNumOfOperandsException m)
{
writeOut.println("Too Many Operands for Number of Operators\n");
buffRead.readLine();
}
}
buffRead.close();
writeOut.close();
I think I see the problem.
You test c to see if it is a whitespace character, and if it is, you then call readLine(). What readLine() does is to read one or more characters until it gets to the next end-of-line sequence.
So what happens when c contains a newline character?
newline is a whitespace character (look it up)
so you read a line, starting at the first character after the newline that you just read
and discard the line.
So you have (accidentally) thrown away a complete line of input.
The solution ... I will leave to you.
When I pass the file from the command line it will skip input lines sometimes ...
I suspect that the same behavior was happening when you were typing the input ... but you didn't notice it. But it is possible that there is something going on with platform specific line termination sequences.
Unfortunately the code you provided seems to have nothing to do with the question!
Where are the 2 different ways of obtaining File?
Also, try using the try-with-resources statement. Something like this:
try(final Reader rdr = new InputStreamReader(System.in);
final BufferedReader brd = new BufferedReader (rdr))
{
/*
* Resources declared above will be automatically closed.
*/
brd.readLine();
}
...it will ensure all files are closed.
So here's the problem. Turn a text file into the correct formatting.
The point of the problem is that I have to read a file, a text file, which contains code in that text file. The code in that has terrible formatting. The formatting issue is that when there is a curly brace like this {, the next line is not 4 spaces to the right, it's just all to the very left. Like this:
while (blah blah blah) {
sysout(blahblahblah);
When it should be this:
while (blah blah blah) {
sysout(blahblahblah);
And there's no other differences between the 2. The only rule is to simply make it so every time there is a curly brace like this {, to make sure the next line is 4 spaces to the right. And vice versa. So every time there's a curly brace like this }, the next line should be 4 spaces to the left. I hope you guys understand this.
This is my issue. I learned how to make a program where a piece of text with multiple spaces and lines is turned into a single line with a single space every time. Wasn't too hard.
For this, though, I have to keep everything on the same line. So if there's 30 lines, the new program I make is also 30 lines. I need to keep very similar spacing, but the simple difference is the whole brace thing. So basically, I just have to make the line after a brace either 4 spaces to the right, and then do the same so it is to the left 4 spaces if it's a } curly brace.
So how do I do this exactly? I don't know how to just fix that without messing up other things. It's such a simple thing I have to do; just make the lines following the braces 4 spaces to the right or left, but I just have no idea what syntax to use to accomplish this. Thanks!
EDIT: This might have just made it easier. So, basically, all lines either end with a right curly brace, a left curly brace, or a semi-colon. No matter what. So every time one of those pops up, it is the end of a line. So maybe if you know how that makes it easier, then I'm just letting you know.
There are programs that will do this for you automatically, so you don't need to reinvent the wheel. For instance, in Eclipse, type: ctrl-a (select all) ctrl-i (auto-indent).
Here's a pseudocode you can start with:
int indentLevel = 0;
while(currentchar = nextchar != null){
printCurrentChar
if(currentchar is '{'){
indentLevel++;
}else if(currentchar is '}'){
indentLevel--;
}else if(currentchar is '\n'){
print indentLevel * 4 spaces
}
}
you might need to deal with escaped braces and other complications though
You can do this pretty easily using regular expressions. If you do not know it and planning to be a programmer, then definitely learn it. It will save for you lots of time in future.
public class TextIndentator
{
public static void main(String[] args) throws IOException
{
File uglyText = new File("ugly.txt");
System.out.println((uglyText.exists() && !uglyText.isDirectory()) ? getNiceText(uglyText) : "FILE \"ugly.txt\" at " + System.getProperty("user.dir") + " do not exists");
}
static String getNiceText(File uglyText) throws IOException
{
// Opening file
FileInputStream inputStream = new FileInputStream(uglyText);
InputStreamReader isr = new InputStreamReader(inputStream);
BufferedReader reader = new BufferedReader(isr);
StringBuilder builder = new StringBuilder();
StringBuffer buffer = new StringBuffer();
// Algorithm starts here
String line;
boolean checkNext = false;
while ((line = reader.readLine()) != null)
{
if(checkNext)
{
// If previous line finished with '{' (And optionally with some whitespaces after it) then, replace any amount (including zero) of whitespaces with 4 witespaces
builder.append(line.replaceFirst("\\s*", " "));
}
else
{
builder.append(line);
}
// Check if line line finishes with { (And optionally with some whitespaces after it)
if(line.matches(".*\\{\\s*")) checkNext = true;
else checkNext = false;
//Append line separator at the end of line
builder.append(System.getProperty("line.separator"));
}
return builder.toString();
}
}
I have a program which searches through a mini-database I have created in a text file, everything works fine, except the fact that whatever is the very last line in the last line of the data is not recognized and whenever I attempt to search for it, it will fail and I am informed that the data does not exist in the database, although it very clearly does when I look at the txt file.
I managed to get a work-around for this, but adding a fake line at the very end that didn't have data, and something I would use such as "xxxxxxxxxx", and then it was able to read the data on top, which originally was the last line before. The problem with this is, I also have to be able to add data to the function straight from my java program, and it would be extremely tedious to have to first remove that fake line, add my information, then put the fake line in again, so I am trying to figure out why it is not searching the last line of my data.
Here is the code for one of my searches:
BufferedReader i = new BufferedReader (new FileReader ("Elements.txt"));
String data=i.readLine();
while (data!=null)
{
String database[]=data.split(",");
data=i.readLine();
if (data!=null)
{
for (int x=0;x<data.length(); ++x)
{
if (database[0].equalsIgnoreCase(elementName))
{
element=database[0];
symbol=database[1];
atomicNumber=database[2];
atomicMass=database[3];
valence=database[4];
found=true;
break;
}
}
}
}
Here is the data that it is searching through:
http://i.imgur.com/GeXQhTh.png
Any idea on how to fix this?
Simply remove your if(data==null) check after you get your last line. You are getting the next line, then checking if that is valid, then continuing, which is unecessary given your while loop. In essence, you are filtering out the last line (since the next line should be null)
Also, you can just get rid of the for loop which is completely superfluous because nothing changes between each invocation (you only interact with your database[] object and x is never used; i.e., you are just doing the same thing data.length() times).
Modify your code like this:
BufferedReader i = new BufferedReader(new FileReader("Elements.txt"));
String data;
while ((data = i.readLine()) != null) {
String database[] = data.split(",");
if (database[0].equalsIgnoreCase(elementName)) {
for (int x = 0; x < data.length(); ++x) {
element = database[0];
symbol = database[1];
atomicNumber = database[2];
atomicMass = database[3];
valence = database[4];
found = true;
break;
}
}
}
for reading text files, put readLine into while condition, so you
only have to write it once and no need for extra null checks and breaks
you do not have to compare database[0]
for each token, so move "if" outside of "for"
File tempFile = new File(loadedFileName);
FileInputStream datStream = new FileInputStream(tempFile);
InputStreamReader readDat = new InputStreamReader(datStream);
int data = readDat.read();
String temp = "";
// keeps reading in one character at a time and returns -1 if there are no more
// characters
while(data != -1){
char datChar = (char)data;
if(temp.length() > 2){
if((temp.substring(temp.length()-1)).equals("\n")){
String[] arrayTemp = temp.split("\\|");
if(Float.valueOf(arrayTemp[columnNumber-1]) > value){
System.out.print(temp);
}
temp = "";
}
}
temp = temp+datChar;
data = readDat.read();
}
The code reads in a file character by character and appends it to a string. Once it reaches a new line it will split the string into an array and then checks to see if a value in that array matches and prints out the string before it was split.
The problem with this code is that even though it gets most of the job done, because of how it is in a while loop where it checks to see if it reaches the end, which if it does it returns -1. This makes it so that I can't print the last line of the file because there is no new line at the end of the file, so it kills the loop before it gets to print out the last line.
An example of a few lines being read in.
This | world | is | brown | and | dirty|
24 | hours | are | in | day| Hello|
Can't store the whole file into an array, can't use a buffered reader, I've tried doing something like counting the number of "|" but I can't seem to get that to work. So in this case if it counted to 6 pipes it would then split and then check before printing. Which I think would solve the problem of not printing the last line. Here is how I tried to implement the count for the |.
while(data != -1){
char datChar = (char)data;
// checks to make sure that temp isn't an empty string first
if(temp.length() > 2){
// checks to see if a new line started and if it did splits the current string into an array.
if((temp.substring(temp.length()-1)).equals("\\|")){
if(count == 6){
String[] arrayTemp = temp.split("\\|");
//then checks the variable in the array col and compares it with a value and prints if it is greater.
if(Float.valueOf(arrayTemp[columnNumber-1]) > value){
System.out.print(temp);
}
temp = "";
count = 0;
}
}
}
temp = temp+datChar;
data = readDat.read();
}
You'd be better off using a BufferedReader and readLine. That will be more efficient in terms of IO, and means you don't need to worry about handling the line breaks yourself:
BufferedReader reader = new BufferedReader(readDat);
String line;
while ((line = reader.readLine()) != null) {
// Handle a line of data - check for it being empty, split it etc.
}
This will give you all the lines in the file, whether or not there's a terminating newline.
EDIT: If you really can't use BufferedReader, I would make your code significantly simpler by checking whether the current character is \n or the end of the file, and processing the "line so far" if so:
StringBuilder line = new StringBuilder();
while (true) {
int next = readDat.read();
if (next == '\n' || next == -1) {
// Handle line here
line = new StringBuilder();
if (next == -1) {
break;
}
} else {
line.append((char) next);
}
}
Note the use of StringBuilder instead of repeated concatenation.
Maybe you can try counting the number of lines in a file and check on that, in addition to checking for newlines.
Also, you could rewrite your code to read a whole line and split that, instead of reading a file character by character. Should you do that, you don't have to check for newlines (and I think you don't even have to check if the current read line is not the last line of the file. I'm not sure if it's faster (but I'm betting it is), but it would definitely result in better readable (and as a result, better maintainable) code.
I may be misunderstanding your question, but it seems to me like some line based scanning using a basic Scanner would be much easier in this situation. Would the following simplify things for you?
Scanner input = new Scanner(new File("FileName.txt"));
while (input.hasNextLine()) {
String[] arrayTemp = input.nextLine().split("\\|");
//etc etc.
}
By referring to https://sourceforge.net/p/opencsv/code/HEAD/tree/trunk/src/au/com/bytecode/opencsv/CSVParser.java
Anyone has idea what is the different among parseLine and parseLineMulti in opencsv's CSVParser?
Looking at the code it seems to determine whether to check the next line for a remainder of quoted text when the quotation doesn't end in the current line.
If you use parseLine it will throw an exception rather than check the subsequent lines.
Following is the relevant code snippet.
if (inQuotes) {
if (multi) {
// continuing a quoted section, re-append newline
sb.append("\n");
pending = sb.toString();
sb = null; // this partial content is not to be added to field list yet
} else {
throw new IOException("Un-terminated quoted field at end of CSV line");
}
}