I want to read all the information from a randomaccessfile containing integers, with 1 integer a line. eg. It seems to be a problem with my "reading" code.
File Contents:
1
3
5
72
0
My current code gives me an EOFException error and the data that I take in is not correct eg 1 is printed as 857222 etc.
Output:
822751754
856306698
805975306
856306186
java.io.EOFException
822751754
while((tmp = randomFile.readInt()) != -1){
System.out.println(tmp)
}
readInt() and "1 integer a line" don't match.
Either you have a binary file containing bytes that can be read using readInt() (which reads always four bytes for an integer), or you have lines of text where each line contains a readable representation of integer values (which seems to be your case).
To read lines of text containing integer values, you have to rewrite your code like this:
String line;
while ((line = randomFile.readLine()) != null) {
int tmp = Integer.parseInt(line);
System.out.println(tmp);
}
When a RandomAccessFile gets to the end of a file, .nextInt() won't return -1, it will throw an EOFException. Therefore you should do something like this:
while(true){
try{
tmp = randomFile.readInt()
System.out.println(tmp)
}catch(EOFException e){
break;
}
}
Related
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");
}
I have a file named mark_method.json containing ABCDE in it and I am reading this file using the InputStream class.
By definition, the InputStream class reads an input stream of bytes. How does this work? I don't have bytes in the file, but characters?
I am trying to understand how a stream reading bytes is reading characters from the file?
public class MarkDemo {
public static void main(String args[]) throws Exception {
InputStream is = null;
try {
is = new FileInputStream("C:\\Users\\s\\Documents\\EB\\EB_02_09_2020_with_page_number_and_quote_number\\Old_images\\mark_method.json");
}
catch(Exception e) {
e.printStackTrace();
} finally {
if(is != null) {
is.close();
}
}
}
}
Every data on the computer is stored in bits and bytes. Here the content of the files is also stored in bytes.
We have programs which convert these bytes into human-readable forms thus we see the mark_method.json file containing characters and not bytes.
An character is a byte. (At least in ASCII).
Each byte from 0 to 127 has a character value. For example 0 is the Null-character, 0xa is \n, 0xd is \r, 0x41 is 'A' and so on.
The implementation only knows bytes. It doesn't know, that the char 0x2709 is ✉. It only sees it as two bytes: 0x27 and 0x09.
Only the texteditor interprets the bytes and show the matching symbol/letter
I think what you are actually asking here is how to convert the bytes you read from file using FileInputStream in to a Java String object you can print and manipulate.
FileInputStream does not have any read methods for directly producing a String object so if that is what you want, you need to further manipulate the input you get.
Option one is to use the Scanner class:
Scanner scanner = new Scanner(is);
String word = scanner.next();
Another option is to read the bytes and use the constructor of the String class that works with byte array:
byte [] bytes = new byte[10];
is.read(bytes);
String text = new String(bytes);
Note that for simplicity I just assumed you can read 10 valid bytes from your file.
In real code you would need some logic to make sure you are reading correct number of bytes.
Also, if your file is not stored using your system default character set, you will need to specify the character set as a parameter to the String constructor.
Finally, you can use another wrapper class, BufferedReader that has a readLine function which takes care of all the logic needed to read bytes representing a line of text from a file and return them in a String.
BufferedReader in = new BufferedReader(new FileReader("foo.in"));
String line = in.readLine();
can anybody please explain why there have to be exactly 3 empty rows in between sections of text (marked with number) in the txt file my code is reading from ?
I have a code that is reading lines from txt file. The structure of the file is as follows:
1
r
line of text
line of text
line of text
line of text
line of text
2
a
line of text
line of text
line of text
line of text
line of text
A number is a mark that i m using to identify which section to read. When section is identified my code then reads consecutive lines of text and returned values are assigned to String variables.
All works perfectly only and only if there is exactly 3 empty rows separating each section of text is source txt file. I d like to understand why is it so ? Thank you very much
Here's the snippet of my code:
inpStream = getClass().getResourceAsStream("/resources/myFile.txt");
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inpStream,"UTF-16BE"))){
do{
num = Integer.toString(a);
line = reader.readLine();
if(line.equals(num)){
who = reader.readLine();
what = reader.readLine();
sat = reader.readLine();
pow = reader.readLine();
satNo = reader.readLine();
cash = reader.readLine();
break;
}
} while(!line.equals(num) && (line = reader.readLine()) != null );
}
catch(IOException e){}
It is the number and order of calls to readLine().
Your code reads and checks every other line for a match. The three blank lines are not important, it's just that it's an even number since the first index number. It will also work with one, five etc.
The double read occurs once at the beginning of each iteration, and once in the condition.
line = reader.readLine();
and
while(... && (line = reader.readLine()) != null
Thereby skipping two lines each iteration.
I would recommend either moving the first read out of the loop, or change to a while-loop:
String line;
while ((line = reader.readLine() != null) {
if (line.equals(num){
...
break;
}
}
This reads each line, checking against num for each line.
Defining num can also be moved out of the loop, as it does not change inside the loop. Giving a full example of:
InputStream inpStream = getClass().getResourceAsStream("/resources/myFile.txt");
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inpStream, "UTF-8"))) {
num = Integer.toString(a);
String line;
while ((line = reader.readLine()) != null) {
if (line.equals(num)) {
who = reader.readLine();
what = reader.readLine();
sat = reader.readLine();
pow = reader.readLine();
satNo = reader.readLine();
cash = reader.readLine();
break;
}
}
} catch (IOException e) {
}
Note: This example uses UTF-8.
You have to read all the lines whether you need them or not. You can't pretend you read lines, that you didn't. You can skip the lines after the ones you needed.
Lets break up your code line by line and analyze.
Line 1.
You call the getClass() function on an InputStream object which in turn you use to call the getStreamResource() function to return a "stream" to your file data.
Now having access to this stream you enclose your BufferReader in a try/catch statement.
Line2.
next you create a BufferReader with Reader Parameter inpstream and file encoding type UFT-16.
Line 3-13
You haven't shown me where you have declared 'a' so I can't be sure, but you are converting an integer 'a' to a string called num. (This is important because it is the terminating factor of your do statement.) I am assuming a =1 in the first iteration.
Now its all about understanding File Offsets.
when you say
line=reader.readLine();
this returns a String containing the current line characters and sets the file offset to the next line.
your file offset is at 'r' (for 1st iteration).
The same technique for reading who,what,sat,pow,satNo & cash.
Now your while statement checks if both conditions are true or not. i.e line != num (which it is since you haven't redefined num anywhere after reading who,what,sat,pow,satNo & cash.) And also line=line.readLine() != null which is also true.
However here is your first mistake calling line=reader.readLine() the way you did this increments the file offset one more line. Thus in two iterations two lines are read in addition to what you expect. This messes up the order in which you envisioned your variables to be found i.e who,what,sat,pow,satNo & cash etc in your do statement.
Therefore in short you are skipping every other line after your first iteration.
You need to get rid of one of your readLine calls.
The two double counting are:
line = inpstream.readLine() and
line = reader.readLine()) != null
Basicly I was looking for a script that puts some data of an array into a textfile, afterwards this saved data could be red in again.
I achieved to do the first part like so:
public void slaOp(){
try {
File file = new File("savefile.txt");
// Als bestand nog niet bestaat maak je het.
if (!file.exists()) {
file.createNewFile();
}
// Schrijven naar de file
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
// alle x waarden op 1 lijn en alle y waarden op 1 lijn
String xwaarden = "";
for(int i=0; i<positiesX.length;i++){
xwaarden += ""+positiesX[i];
}
String ywaarden="";
for(int s=0; s<positiesY.length;s++){
ywaarden += ""+positiesY[s];
}
bw.write(xwaarden);
bw.newLine();
bw.write(ywaarden);
bw.close();
System.out.println("Bestand werkt correct verwerkt.");
} catch (IOException e) {
e.printStackTrace();
}
}
This first part writes the data into a file like so:
123456
465489
For the second part I found many ways but not one that suits my demand.
First I had a script that red a whole line as a String. This worked except for the part that I don't need a Stringline but the numbers, seperated.
Afterwards I had tried a script that uses hasNextInt() and nextInt().
But for some reason, this script didn't read a thing. I thought that the problem would lay with the fact that the integers in the text file aren't actual integers but strings?
I couldn't resolve this problem so tried a 3th script.
FileInputStream fileInput = new FileInputStream("savefile.txt");
int r;
while ((r = fileInput.read()) != -1) {
int c = (int) r;
System.out.println(c);
}
fileInput.close();
This script reads characters. When a convert them to integers, the output are not the numbers that saved into the file.
Could anybody tell me the proper way of handling this situation? Are there some good explanations with examples?
I agree with #prabugp. If there is only 1 number in each line of the file, then you can read it line by line and convert each line to an Integer using Integer.parseInt.
At the moment I believe the reason the numbers you are getting when reading the file are not the same numbers as you have in the file is because you are converting each character in a line to its integer representation as #srm has mentioned. So you are getting the integer representation of the character '1' which is 49 for example.
To read the file line by line you can use something like the following (as explained here http://www.programcreek.com/2011/03/java-read-a-file-line-by-line-code-example/):
File file = new File("C:\\file.txt");
FileInputStream fis = new FileInputStream(file);
//Construct BufferedReader from InputStreamReader
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
String line = null;
while ((line = br.readLine()) != null) {
// convert to integer
Integer a = Integer.parseInt(line);
}
A quick solution that i can thing of, is converting string into number and then split it as you like. Although its only one thought and it could be done with many ways
a quick link for you.
I can be more specific if you need help after that.
" When a convert them to integers" how do you convert the char into an int? (keep in mind, that a char is already an int).
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