BufferedReader.skip() equivalent for lines, not characters - java

Is there in Java some sort of equivalent to BufferedReader.skip(), that would take number of lines as parameter instead of number of characters?
I want to jump to a specific line in a text file and start reading from that point without the need going thru all the lines of the file and checking against the line number (tens of thousands of them - model obj file).
All the examples I saw were dealing with the checking of line number which is not what I want.

So, the solution is to use FileInputStream.skip().
UPDATE: manually adding system-specific new line separator bytes length to line bytes length at each line iteration solved the problem of erroneous bytes skipping, so now it finally works as expected!
Define some Long variable where you will store the number of bytes to skip. I did that in my main application class (App.class):
public static long lineByteOffset = 0;
Then, in your method/function where you read your lines with BufferedReder make it like this (all my files that I read from are encoded as UTF-8):
File objFile = new File(PATH_TO_YOUR_FILE_HERE);
FileInputStream fir = null;
try {
fir = new FileInputStream(objFile);
} catch (FileNotFoundException e) {
System.err.println("File not found!");
}
fir.skip(App.lineByteOffset);//<--- 1ST IMPORTANT PART: SET HOW MANY BYTES TO SKIP, YOU START WITH 0 FOR THE 1ST TIME
BufferedReader reader = new BufferedReader(new InputStreamReader(fir, "UTF-8"));
int nls = System.getProperty("line.separator").getBytes().length;
String line;
try {
while ((line = reader.readLine()) != null) {
App.lineByteOffset += (long) (line.getBytes().length + nls);//<--- 2ND IMPORTANT PART: INCREASE NUMBER OF BYTES TO SKIP FOR NEXT TIME
/*
DO YOUR STUFF HERE...
IN MY CASE IT RETURNS SPECIFIC BLOCK
WHICH IN EFFECT EXIT THE WHILE LOOP AS NEEDED
SO THAT THE NEXT TIME IT CONTINUE WHERE WE LEFT IT
WITHOUT NEED TO READ THE WHOLE FILE FROM THE START ONCE AGAIN
*/
}
reader.close();
} catch (IOException e) {
System.err.println("Error reading the file");
}

Related

Can't read integer file

I'm trying to read data from a file that contains integers, but the Scanner doesn't read anything from that file.
I've tried to read the file from the Scanner :
// switch() blablabla
case POPULATION:
try {
while (sc.hasNextInt()) {
this.listePops.add(sc.nextInt());
}
} catch (Exception e) {
System.err.println("~ERREUR~ : " + e.getMessage());
}
break;
And if I try to print each sc.nextInt() to the console, it just prints a blank line and then stops.
Now when I read the same file as a String:
?652432
531345
335975
164308
141220
1094283
328278
270582
// (Rest of the data)
So, I guess it can't read the file as a list of integers since there's a question mark at the beginning, but the problem is that this question mark doesn't appear anywhere in my file, so I can't remove it. What am I supposed to do?
If the first character in the file is a question mark (?) and its original origin is unknown then it is usually the UTF-8 Byte Order Mark (BOM). This means the file was saved as UTF-8. The Microsoft Notepad application will add a BOM to the saved text file if that file was saved in UTF-8 instead of ANSI. There are also other BOM characters for UTF-16, UTF-32, etc.
Reading a text file as String doesn't look like a bad idea now. Changing the save format of the file can work to but that BOM may have actual intended purpose for another application, so, that may not be a viable option. Let's read the file as String lines (read comments in code):
// Variable to hold the value of the UTF-8 BOM:
final String UTF8_BOM = "\uFEFF";
// List to hold the Integer numbers in file.
List<Integer> listePops = new ArrayList<>();
// 'Try With Resources' used to to auto-close file and free resources.
try (Scanner reader = new Scanner(new File("data.txt"))) {
String line;
int lineCount = 0;
while (reader.hasNextLine()) {
line = reader.nextLine();
line = line.trim();
// Skip blank lines (if any):
if (line.isEmpty()) {
continue;
}
lineCount++;
/* Is this the first line and is there a BOM at the
start of this line? If so, then remove it. */
if (lineCount == 1 && line.startsWith(UTF8_BOM)) {
line = line.substring(1);
}
// Validate Line Data:
// Is the line a String representation of an Integer Number?
if (line.matches("\\d+")) {
// Yes... then convert that line to Integer and add it to the List.
listePops.add(Integer.parseInt(line));
}
// Move onto next file line...
}
}
catch (FileNotFoundException ex) {
// Do what you want with this exception (but don't ignore it):
System.err.println(ex.getMessage());
}
// Display the gathered List contents:
for (Integer ints : listePops) {
System.out.println(ints);
}

assigning properties to strings in text file

Hopefully my explanation does me some justice. I am pretty new to java. I have a text file that looks like this
Java
The Java Tutorials
http://docs.oracle.com/javase/tutorial/
Python
Tutorialspoint Java tutorials
http://www.tutorialspoint.com/python/
Perl
Tutorialspoint Perl tutorials
http://www.tutorialspoint.com/perl/
I have properties for language name, website description, and website url. Right now, I just want to list the information from the text file exactly how it looks, but I need to assign those properties to them.
The problem I am getting is "index 1 is out of bounds for length 1"
try {
BufferedReader in = new BufferedReader(new FileReader("Tutorials.txt"));
while (in.readLine() != null) {
TutorialWebsite tw = new TutorialWebsite();
str = in.readLine();
String[] fields = str.split("\\r?\\n");
tw.setProgramLanguage(fields[0]);
tw.setWebDescription(fields[1]);
tw.setWebURL(fields[2]);
System.out.println(tw);
}
} catch (IOException e) {
e.printStackTrace();
}
I wanted to test something so i removed the new lines and put commas instead and made it str.split(",") which printed it out just fine, but im sure i would get points taken off it i changed the format.
readline returns a "string containing the contents of the line, not including any line-termination characters", so why are you trying to split each line on "\\r?\\n"?
Where is str declared? Why are you reading two lines for each iteration of the loop, and ignoring the first one?
I suggest you start from
String str;
while ((str = in.readLine()) != null) {
System.out.println(str);
}
and work from there.
The first readline gets the language, the second gets the description, and the third gets the url, and then the pattern repeats. There is nothing to stop you using readline three times for each iteration of the while loop.
you can read all the file in a String like this
// try with resources, to make sure BufferedReader is closed safely
try (BufferedReader in = new BufferedReader(new FileReader("Tutorials.txt"))) {
//str will hold all the file contents
StringBuilder str = new StringBuilder();
String line;
while ((line = in.readLine()) != null) {
str.append(line);
str.append("\n");
} catch (IOException e) {
e.printStackTrace();
}
Later you can split the string with
String[] fields = str.toString().split("[\\n\\r]+");
Why not try it like this.
allocate a List to hold the TutorialWebsite instances.
use try with resources to open the file, read the lines, and trim any white space.
put the lines in an array
then iterate over the array, filling in the class instance
the print the list.
The loop ensures the array length is a multiple of nFields, discarding any remainder. So if your total lines are not divisible by nFields you will not read the remainder of the file. You would still have to adjust the setters if additional fields were added.
int nFields = 3;
List<TutorialWebsite> list = new ArrayList<>();
try (BufferedReader in = new BufferedReader(new FileReader("tutorials.txt"))) {
String[] lines = in.lines().map(String::trim).toArray(String[]::new);
for (int i = 0; i < (lines.length/nFields)*nFields; i+=nFields) {
TutorialWebsite tw = new TutorialWebsite();
tw.setProgramLanguage(lines[i]);
tw.setWebDescription(lines[i+1]);
tw.setWebURL(lines[i+2]);
list.add(tw);
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
list.forEach(System.out::println);
A improvement would be to use a constructor and pass the strings to that when each instance is created.
And remember the file name as specified is relative to the directory in which the program is run.

Check if large list of words has specific length

I have a dictionary text file of around 60000 words. I would like to read in that text file and see if it has a certain amount of n words, provided by the user. At the recommendation of my Professor, I'm going to create a method that expands the array to compensate the different n values. I know how to do that. My question is, how do I initially read the text file and determine if each of the 60000 words has a specific n length?
I know I have to use a loop and import the file: (although I've never done throw exception)
Scanner inputFile = new Scanner(new File("2of12inf.txt"));
for(int i = 0; i < sizeWord; i++) {
}
But what I would normally do is use a charAt(i) , and check if the word has n many characters. But I can't possibly do that for 60000 words. Suggestions?
try{
BufferedReader br = new BufferedReader(new FileReader(new File("2of12inf.txt")));
String line;
while ((line = br.readLine()) != null) {
// process the line.
int lineLength = line.length();
// assuming each line contains one word, do whatever you want to with this length
}
} catch (Exception e) {
System.out.println("Exception caught! Should handle it accordingly: " + e);
} finally {
be.close();
}

Reading Integer values from a file (Java)

I'm working on a simple level editor for my Android game. I've written the GUI (which draws a grid) using swing. You click on the squares where you want to position a tile and it changes colour. Once you're done, you write everything to a file.
My file consists of something like the following (this is just an example):
I use the asterisks to determine the level number being read and the hyphen to tell the reader to stop reading.
My file reading code is below, Selecting which part to read works OK - for example. if I pass in 2 by doing the following:
readFile(2);
Then it prints all of the characters in the 2nd section
What I can't figure out is, once I've got to the 'start' point, how do I actually read the numbers as integers and not individual characters?
Code
public void readFile(int level){
try {
//What ever the file path is.
File levelFile = new File("C:/Temp/levels.txt");
FileInputStream fis = new FileInputStream(levelFile);
InputStreamReader isr = new InputStreamReader(fis);
Reader r = new BufferedReader(isr);
int charTest;
//Position the reader to the relevant level (Levels are separated by asterisks)
for (int x =0;x<level;x++){
//Get to the relevant asterisk
while ((charTest = fis.read()) != 42){
}
}
//Now we are at the correct read position, keep reading until we hit a '-' char
//Which indicates 'end of level information'
while ((charTest = fis.read()) != 45){
System.out.print((char)charTest);
}
//All done - so close the file
r.close();
} catch (IOException e) {
System.err.println("Problem reading the file levels.txt");
}
}
Scanner's a good answer. To remain closer to what you have, use the BufferedReader to read whole lines (instead of reading one character at a time) and Integer.parseInt to convert from String to Integer:
// get to starting position
BufferedReader r = new BufferedReader(isr);
...
String line = null;
while (!(line = reader.readLine()).equals("-"))
{
int number = Integer.parseInt(line);
}
If you use the BufferedReader and not the Reader interface, you can call r.readLine(). Then you can simply use Integer.valueOf(String) or Integer.parseInt(String).
Perhaps you should consider using readLine which gets all the chars up the the end of line.
This part:
for (int x =0;x<level;x++){
//Get to the relevant asterisk
while ((charTest = fis.read()) != 42){
}
}
Can change to this:
for (int x =0;x<level;x++){
//Get to the relevant asterisk
while ((strTest = fis.readLine()) != null) {
if (strTest.startsWith('*')) {
break;
}
}
}
Then, to read the values another loop:
for (;;) {
strTest = fls.readLine();
if (strTest != null && !strTest.startsWith('-')) {
int value = Integer.parseInt(strTest);
// ... you have to store it somewhere
} else {
break;
}
}
You also need some code in there to handle errors including a premature end of file.
I think you should have look at the Scanner API in Java.
You can have a look at their tutorial

Read a single file with multiple BufferedReaders

I'm working on a program that needs to update a line that depends its value on the result of a line that goes read after. I thought that I could use two BufferedReaders in Java to position the reader on the line to update while the other one goes for the line that fixes the value (it can be an unknown number of lines ahead). The problem here is that I'm using two BufferedReaders on the same file and even if I think I'm doing right with the indexes the result in debug doesn't seem to be reliable.
Here's the code:
String outFinal
FileName=fileOut;
File fileDest=new File(outFinalFileName);
try {
fout = new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream(fileDest)));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
FileReader inputFile=null;
try {
inputFile = new FileReader(inFileName);
} catch (FileNotFoundException e2) {
e2.printStackTrace();
}
BufferedReader fin = new BufferedReader(inputFile);
BufferedReader finChecker = new BufferedReader(inputFile); //Checks the file and matches record to change
String line="";
String lineC="";
int lineNumber=0;
String recordType="";
String statusCode="";
try {
while ((lineC = finChecker.readLine()) != null) {
lineNumber++;
if (lineNumber==1)
line=fin.readLine();
recordType=lineC.substring(0,3);//Gets current Record Type
if (recordType.equals("35")){
while(!line.equals(lineC)){
line=fin.readLine();
if (line==null)
break;
fout.write(line);
}
}else if (recordType.equals("32")){
statusCode=lineC.substring(4,7);
if(statusCode.equals("XX")){
updateRecordLine(line,fout);
}
}
}
returnVal=true;
} catch (IOException e) {
e.printStackTrace();
}
Thanks in advance.
Well, the BufferedReader only reads stuff, it doesn't have the ability to write data back out. So, what you would need is a BufferedReader to get stuff in, and a BufferedWriter that takes all the input from the BufferedReader, and outputs it to a temp file, with the corrected/appended data.
Then, when you're done (i.e. both BufferedReader and BufferedWriter streams are closed), you need to either discard the original file, or rename the temp file to the name of the original file.
You are basically copying the original file to a temp file, modifying the line in question in the temp file's output, and then copying/renaming the temp file over the original.
ok, i see some problem in your code exactly on these lines-->
recordType=lineC.substring(0,3);//Gets current Record Type
if (recordType.equals("35")){
if you see on the first line, you are getting the substring of recordType into recordType. Now recordType length is 3. If at all the recordType has only 2 characters, then substring throws arrayIndexOutOfBoundsException. So when no runtime exceptions, its length is 3 and on the next line you are calling the equals method that has a string with 2 characters.
Will this if block ever run ?

Categories