InputStreamReader and reading random lines from .txt file - java

I have a method for my app to read a random line from a text file and return it. Im using the randTxt() to read and return a random line from the txt file.
but it only shows the same line (1st line) everytime.
public String randTxt(){
// Read in the file into a list of strings
InputStreamReader inputStream = new InputStreamReader(getResources().openRawResource(R.raw.randomstuff));
//ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
String theLine="";
int i;
try {
i = inputStream.read();
while (i != -1) {
i = inputStream.read();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
LineNumberReader rdr = new LineNumberReader(inputStream);
int numLines = 30;
Random r = new Random();
rdr.setLineNumber(r.nextInt(numLines));
try {
theLine = rdr.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return theLine;
}
How can I fix it? and Can someone explain what's wrong in my code?

Here's the framework for doing what you need using BufferedReader. In this case, you don't need to store the values in a temp array.
InputStreamReader inputStream = new InputStreamReader
(getResources().openRawResource(R.raw.randomstuff));
BufferedReader br = new BufferedReader(inputStream);
int numLines = 30;
Random r = new Random();
int desiredLine = r.nextInt(numLines);
String theLine="";
int lineCtr = 0;
while ((theLine = br.readLine()) != null) {
if (lineCtr == desiredLine) {
break;
}
lineCtr++;
}
...
Log.d(TAG, "Magic line is: " +theLine);

You have gotten an answer of how to fix your code, but no explanation of why our original code did not work.
LineNumberReader.setLineNumber(int) does not go to the actual line, it just changes what number you call the current line.
So, say you read two lines, getLineNumber() will now return 2 (it started at 0 and increased by 1 each time a newline was encountered). if you now setLineNumber(10), getLineNumber() will return 10. Reading yet another line (your third) will cause getLineNumber() to return 11.
This is described in the Java Doc.

inputStream.read does not return a line number. it returns the byte that was read. this isn't how you would read line by line. to read line by line, you should use buffered reader's readLine method. its probably easier at that point to read it all into a local array and use that array to randomly get an entry, rather than using a line number reader.

I think Random() function returns a value between 0 and 1. hence, you may have to multiply it with 100 to get an integer value. May even consider a MOD "your upper limit" operation to guarentee that the index you finally get is between 0 and your upper limit
Use the index you calculated thus, in your setLineNumber() method.
Edit:
As john said, we can get whole number using Random() object.

public String getRandomLine(String fileLoc) throws IOException
{
BufferedReader reader = new BufferedReader(new FileReader(fileLoc));
ArrayList<String> lines = new ArrayList<String>();
String line =null;
while( (line = reader.readLine())!= null )
lines.add(line);
// Choose a random one from the list
return lines.get(new Random().nextInt(lines.size()));
}
public String getRandomLineOpt(String fileLoc)throws IOException
{
File f=new File(fileLoc);
RandomAccessFile rcf=new RandomAccessFile(f, "r");
long rand = (long)(new Random().nextDouble()*f.length());
rcf.seek(rand);
rcf.readLine();
return rcf.readLine();
}

Related

How to piece together String using file reader and char array

Wrote a file in another class and now I'm trying to piece together the file into a JLabel, so I need to convert the name in the file into a string. Using FileReader and a char array to separate each character into an array to be put together in the JLabel.
I'm getting this error on NamePieces[x] = (char)nr;:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 0
at clients.initialize(clients.java:197)
at clients.<init>(clients.java:72)
This is the code that I want to read the file:
try(FileReader nameReader = new FileReader(NamePath)) {
int nr = nameReader.read();
int x = 0;
while(nr != -1) {
namePieces[x] = (char)nr;
nr = nameReader.read();
x++;
}
}
catch (FileNotFoundException e) {}
catch (IOException e1) {}
String name = String.valueOf(namePieces[0]) + namePieces[1];
Doesn't work
Most likely, your problem occurs because namePieces is not initialized. As was already mentioned in the comments, you should not use char[] as a container for your characters (because in real world you won't know the length of the files' contents every time, so you will probably need to resize your container), it is way more better to use StringBuilder, provided by Java standard library. It will protect you from getting out of bounds.
StringBuilder namePieces = new StringBuilder();
File file = new File(filePath);
BufferedReader reader = new BufferedReader(
new InputStreamReader(new FileInputStream(file),
Charset.forName("UTF-8")));
int c;
while((c = reader.read()) != -1) {
namePieces.append((char) c);
}
String nameString = namePieces.toString(); // Use this string as a complete array of needed characters
As you see I changed an approach by using not only StringBuilder, but also BufferedReader. However, for your task you can leave FileReader as it is. Just consider appending characters to builder.
If your file just contains a String there is a straightforward way to read it:
public String readMyFile( String fileName) throws IOException {
Path path = Paths.get(fileName);
return Files.readAllLines(path).get(0);
}

Error with file reader [duplicate]

This question already has an answer here:
What does "Incompatible types: void cannot be converted to ..." mean?
(1 answer)
Closed 6 months ago.
I'm getting an error with
PersonsInfoData[i] = PersonsInfoin.setPersonsInfo(temp[0],temp[1],temp[2],temp[3],temp[4]);
"Incompatible types: void cannot be coverted to PersonsInfo"
public void readFile(String fileName)
{
// Try to read in the data and if an exception occurs go to the Catch section
try
{
FileInputStream fstream = new FileInputStream(fileName);
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
int i = 0; // i is used as the line counter
String line; // line is used to temporarily store the line read in from the data file
// Read a line from the data file into the buffer and then check whether
// it is null. The while loop continues until a line read in is null.
while ((line = br.readLine()) != null)
{
// Split the line of data (from the text file) and put each entry into the
// temporary array - temp[]
String[] temp = line.split(",");
// Save each entry into its respective PCDataRecord object.
PersonsInfoData[i] = PersonsInfoin.setPersonsInfo(temp[0],temp[1],temp[2],temp[3],temp[4]);
i++; // Increment i so we can keep a count of how many entries have been read in.
}
numberOfEntries = i; // Set numberOfEntries equal to i, to remember how many entries are now in the array
br.close(); // Close the BufferedReader
in.close(); // Close the DataInputStream
fstream.close(); // Close the FileInputStream
}
catch (Exception e)
{
System.err.println("Error Reading File: " + e.getMessage());
}
}
this is a setter statement:
PersonsInfoin.setPersonsInfo(temp[0],temp[1],temp[2],temp[3],temp[4]);
so, not all setters return objects, in your case that method returns returns nothing (void) making your statement equivalent to doing:
PersonsInfoData[i] = void
which is invalid...
I guess you are trying to write the values to PersonsInfoData[i]. If yes, then replace the line with -
PersonsInfoData[i].setPersonsInfo(temp[0],temp[1],temp[2],temp[3],temp[4]);

Reading a specific set of lines in a file [duplicate]

In Java, is there any method to read a particular line from a file? For example, read line 32 or any other line number.
For small files:
String line32 = Files.readAllLines(Paths.get("file.txt")).get(32)
For large files:
try (Stream<String> lines = Files.lines(Paths.get("file.txt"))) {
line32 = lines.skip(31).findFirst().get();
}
Unless you have previous knowledge about the lines in the file, there's no way to directly access the 32nd line without reading the 31 previous lines.
That's true for all languages and all modern file systems.
So effectively you'll simply read lines until you've found the 32nd one.
Not that I know of, but what you could do is loop through the first 31 lines doing nothing using the readline() function of BufferedReader
FileInputStream fs= new FileInputStream("someFile.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fs));
for(int i = 0; i < 31; ++i)
br.readLine();
String lineIWant = br.readLine();
Joachim is right on, of course, and an alternate implementation to Chris' (for small files only because it loads the entire file) might be to use commons-io from Apache (though arguably you might not want to introduce a new dependency just for this, if you find it useful for other stuff too though, it could make sense).
For example:
String line32 = (String) FileUtils.readLines(file).get(31);
http://commons.apache.org/io/api-release/org/apache/commons/io/FileUtils.html#readLines(java.io.File, java.lang.String)
You may try indexed-file-reader (Apache License 2.0). The class IndexedFileReader has a method called readLines(int from, int to) which returns a SortedMap whose key is the line number and the value is the line that was read.
Example:
File file = new File("src/test/resources/file.txt");
reader = new IndexedFileReader(file);
lines = reader.readLines(6, 10);
assertNotNull("Null result.", lines);
assertEquals("Incorrect length.", 5, lines.size());
assertTrue("Incorrect value.", lines.get(6).startsWith("[6]"));
assertTrue("Incorrect value.", lines.get(7).startsWith("[7]"));
assertTrue("Incorrect value.", lines.get(8).startsWith("[8]"));
assertTrue("Incorrect value.", lines.get(9).startsWith("[9]"));
assertTrue("Incorrect value.", lines.get(10).startsWith("[10]"));
The above example reads a text file composed of 50 lines in the following format:
[1] The quick brown fox jumped over the lazy dog ODD
[2] The quick brown fox jumped over the lazy dog EVEN
Disclamer: I wrote this library
Although as said in other answers, it is not possible to get to the exact line without knowing the offset (pointer) before. So, I've achieved this by creating an temporary index file which would store the offset values of every line. If the file is small enough, you could just store the indexes (offset) in memory without needing a separate file for it.
The offsets can be calculated by using the RandomAccessFile
RandomAccessFile raf = new RandomAccessFile("myFile.txt","r");
//above 'r' means open in read only mode
ArrayList<Integer> arrayList = new ArrayList<Integer>();
String cur_line = "";
while((cur_line=raf.readLine())!=null)
{
arrayList.add(raf.getFilePointer());
}
//Print the 32 line
//Seeks the file to the particular location from where our '32' line starts
raf.seek(raf.seek(arrayList.get(31));
System.out.println(raf.readLine());
raf.close();
Also visit the Java docs on RandomAccessFile for more information:
Complexity: This is O(n) as it reads the entire file once. Please be aware for the memory requirements. If it's too big to be in memory, then make a temporary file that stores the offsets instead of ArrayList as shown above.
Note: If all you want in '32' line, you just have to call the readLine() also available through other classes '32' times. The above approach is useful if you want to get the a specific line (based on line number of course) multiple times.
Another way.
try (BufferedReader reader = Files.newBufferedReader(
Paths.get("file.txt"), StandardCharsets.UTF_8)) {
List<String> line = reader.lines()
.skip(31)
.limit(1)
.collect(Collectors.toList());
line.stream().forEach(System.out::println);
}
No, unless in that file format the line lengths are pre-determined (e.g. all lines with a fixed length), you'll have to iterate line by line to count them.
In Java 8,
For small files:
String line = Files.readAllLines(Paths.get("file.txt")).get(n);
For large files:
String line;
try (Stream<String> lines = Files.lines(Paths.get("file.txt"))) {
line = lines.skip(n).findFirst().get();
}
In Java 7
String line;
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
for (int i = 0; i < n; i++)
br.readLine();
line = br.readLine();
}
Source: Reading nth line from file
If you are talking about a text file, then there is really no way to do this without reading all the lines that precede it - After all, lines are determined by the presence of a newline, so it has to be read.
Use a stream that supports readline, and just read the first X-1 lines and dump the results, then process the next one.
It works for me:
I have combined the answer of
Reading a simple text file
But instead of return a String I am returning a LinkedList of Strings. Then I can select the line that I want.
public static LinkedList<String> readFromAssets(Context context, String filename) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(context.getAssets().open(filename)));
LinkedList<String>linkedList = new LinkedList<>();
// do reading, usually loop until end of file reading
StringBuilder sb = new StringBuilder();
String mLine = reader.readLine();
while (mLine != null) {
linkedList.add(mLine);
sb.append(mLine); // process line
mLine = reader.readLine();
}
reader.close();
return linkedList;
}
Use this code:
import java.nio.file.Files;
import java.nio.file.Paths;
public class FileWork
{
public static void main(String[] args) throws IOException {
String line = Files.readAllLines(Paths.get("D:/abc.txt")).get(1);
System.out.println(line);
}
}
You can use LineNumberReader instead of BufferedReader. Go through the api. You can find setLineNumber and getLineNumber methods.
You can also take a look at LineNumberReader, subclass of BufferedReader. Along with the readline method, it also has setter/getter methods to access line number. Very useful to keep track of the number of lines read, while reading data from file.
public String readLine(int line){
FileReader tempFileReader = null;
BufferedReader tempBufferedReader = null;
try { tempFileReader = new FileReader(textFile);
tempBufferedReader = new BufferedReader(tempFileReader);
} catch (Exception e) { }
String returnStr = "ERROR";
for(int i = 0; i < line - 1; i++){
try { tempBufferedReader.readLine(); } catch (Exception e) { }
}
try { returnStr = tempBufferedReader.readLine(); } catch (Exception e) { }
return returnStr;
}
you can use the skip() function to skip the lines from begining.
public static void readFile(String filePath, long lineNum) {
List<String> list = new ArrayList<>();
long totalLines, startLine = 0;
try (Stream<String> lines = Files.lines(Paths.get(filePath))) {
totalLines = Files.lines(Paths.get(filePath)).count();
startLine = totalLines - lineNum;
// Stream<String> line32 = lines.skip(((startLine)+1));
list = lines.skip(startLine).collect(Collectors.toList());
// lines.forEach(list::add);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
list.forEach(System.out::println);
}
EASY WAY - Reading a line using line number.
Let's say Line number starts from 1 till null .
public class TextFileAssignmentOct {
private void readData(int rowNum, BufferedReader br) throws IOException {
int n=1; //Line number starts from 1
String row;
while((row=br.readLine()) != null) { // Reads every line
if (n == rowNum) { // When Line number matches with which you want to read
System.out.println(row);
}
n++; //This increments Line number
}
}
public static void main(String[] args) throws IOException {
File f = new File("../JavaPractice/FileRead.txt");
FileReader fr = new FileReader(f);
BufferedReader br = new BufferedReader(fr);
TextFileAssignmentOct txf = new TextFileAssignmentOct();
txf.readData(4, br); //Read a Specific Line using Line number and Passing buffered reader
}
}
for a text file you can use an integer with a loop to help you get the number of the line, don't forget to import the classes we are using in this example
File myObj = new File("C:\\Users\\LENOVO\\Desktop\\test.txt");//path of the file
FileReader fr = new FileReader(myObj);
fr.read();
BufferedReader bf = new BufferedReader(fr); //BufferedReader of the FileReader fr
String line = bf.readLine();
int lineNumber = 0;
while (line != null) {
lineNumber = lineNumber + 1;
if(lineNumber == 7)
{
//show line
System.out.println("line: " + lineNumber + " has :" + line);
break;
}
//lecture de la prochaine ligne, reading next
line = bf.readLine();
}
They are all wrong I just wrote this in about 10 seconds.
With this I managed to just call the object.getQuestion("linenumber") in the main method to return whatever line I want.
public class Questions {
File file = new File("Question2Files/triviagame1.txt");
public Questions() {
}
public String getQuestion(int numLine) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(file));
String line = "";
for(int i = 0; i < numLine; i++) {
line = br.readLine();
}
return line; }}

NumberFormatException being thrown by Integer.parseInt()

For my assignment, I'm trying to read a sequence of integers into an array and calculate a few things about the array. I'm restricted to using InputStreamReader and BufferedReader to read from the file, and Integer.parseInt() is throwing NumberFormatException after the first line read.
Everything works if I input each number individually by keyboard, but it doesn't work at all if I try and read directly from the file.
Here's the code so far
int[] array = new int[20];
try {
int x, count = 0;
do{
x = Integer.parseInt((new BufferedReader(new InputStreamReader(System.in)).readLine()));
array[count] = x;
count++;
}
while (x != 0);
}
catch (IOException e){
System.out.println(e);
}
catch (NumberFormatException e){
System.out.println(e);
}
The case to be tested is
33
-55
-44
12312
2778
-3
-2
53211
-1
44
0
When I try and copy/paste the whole test case, the program only reads the first line and then throws
NumberFormatException. Why does readLine() only read the first value and ignore everything else?s
You are reopening System.in each time. I don't know what this does but I assume it can't be good.
Instead, you should use one BufferedReader, and in your loop, read lines one by one from it.
The way that I think this is happening is that you create a reader, read one line, and then on the next iteration you create a new one, which is empty but still tries to read, therefore it reads "", passes it to the parser and Integer.parseInt() throws NumberFormatException because it can't be parsed. The correct way to do this is:
int[] array = new int[20];
try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
int x, count = 0;
do {
String s = reader.readLine();
x = Integer.parseInt(s);
array[count] = x;
count++;
}
while (x != 0);
} catch (IOException | NumberFormatException e) {
e.printStackTrace();
}

Read one line of a csv file in Java

I have a csv file that currently has 20 lines of data.
The data contains employee info and is in the following format:
first name, last name, Employee ID
So one line would like this: Emma, Nolan, 2
I know how to write to the file in java and have all 20 lines print to the console, but what I'm not sure how to do is how to get Java to print one specific line to the console.
I also want to take the last employee id number in the last entry and have java add 1 to it one I add new employees. I thinking this needs to be done with a counter just not sure how.
You can do something like this:
BufferedReader reader = new BufferedReader(new FileReader(<<your file>>));
List<String> lines = new ArrayList<>();
String line = null;
while ((line = reader.readLine()) != null) {
lines.add(line);
}
System.out.println(lines.get(0));
With BufferedReader you are able to read lines directly. This example reads the file line by line and stores the lines in an array list. You can access the lines after that by using lines.get(lineNumber).
You can read text from a file one line at a time and then do whatever you want to with that line, print it, compare it, etc...
// Construct a BufferedReader object from the input file
BufferedReader r = new BufferedReader(new FileReader("employeeData.txt"));
int i = 1;
try {
// "Prime" the while loop
String line = r.readLine();
while (line != null) {
// Print a single line of input file to console
System.out.print("Line "+i+": "+line);
// Prepare for next loop iteration
line = r.readLine();
i++;
}
} finally {
// Free up file descriptor resources
r.close();
}
// Remember the next available employee number in a one-up scheme
int nextEmployeeId = i;
BufferedReader reader =new BufferedReader(new FileReader("yourfile.csv"));
String line = "";
while((line=reader.readLine())!=null){
String [] employee =line.trim().split(",");
// if you want to check either it contains some name
//index 0 is first name, index 1 is last name, index 2 is ID
}
Alternatively, If you want more control over read CSV files then u can think about CsvBeanReader that will give you more access over files contents..
Here is an algorithm which I use for reading csv files. The most effective way is to read all the data in the csv file into a 2D array first. It just makes it a lot more flexible to manipulate the data.
That way you can specify which line of the file to print to the console by specifying it in the index of the array and using a for. I.e: System.out.println(employee_Data[1][y]); for record 1. y is the index variable for fields. You would need to use a For Loop of course, to print every element for each line.
By the way, if you want to use the employee data in a larger program, in which it may for example store the data in a database or write to another file, I'd recommend encapsulating this entire code block into a function named Read_CSV_File(), which will return a 2D String array.
My Code
// The return type of this function is a String.
// The CSVFile_path can be for example "employeeData.csv".
public static String[][] Read_CSV_File(String CSVFile_path){
String employee_Data[][];
int x;
int y;
int noofFields;
try{
String line;
BufferedReader in = new BufferedReader(new FileReader(CSVFile_path));
// reading files in specified directory
// This assigns the data to the 2D array
// The program keeps looping through until the line read in by the console contains no data in it i.e. the end of the file.
while ( (( line = in.readLine()) != null ){
String[] current_Record = line.split(",");
if(x == 0) {
// Counts the number of fields in the csv file.
noofFields = current_Record.length();
}
for (String str : values) {
employee_Data[x][y] = str;
System.out.print(", "+employee_Data[x][y]);
// The field index variable, y is incremented in every loop.
y = y + 1;
}
// The record index variable, x is incremented in every loop.
x = x + 1;
}
// This frees up the BufferedReader file descriptor resources
in.close();
/* If an error occurs, it is caught by the catch statement and an error message
* is generated and displayed to the user.
*/
}catch( IOException ioException ) {
System.out.println("Exception: "+ioException);
}
// This prints to console the specific line of your choice
System.out.println(("Employee 1:);
for(y = 0; y < noofFields ; y++){
// Prints out all fields of record 1
System.out.print(employee_Data[1][y]+", ");
}
return employee_Data;
}
For reading large file,
log.debug("****************Start Reading CSV File*******");
copyFile(inputCSVFile);
StringBuilder stringBuilder = new StringBuilder();
String line= "";
BufferedReader brOldFile = null;
try {
String inputfile = inputCSVFile;
log.info("inputfile:" + inputfile);
brOldFile = new BufferedReader(new FileReader(inputfile));
while ((line = brOldFile.readLine()) != null) {
//line = replaceSpecialChar(line);
/*do your stuff here*/
stringBuilder.append(line);
stringBuilder.append("\n");
}
log.debug("****************End reading CSV File**************");
} catch (Exception e) {
log.error(" exception in readStaffInfoCSVFile ", e);
}finally {
if(null != brOldFile) {
try {
brOldFile.close();
} catch (IOException e) {
}
}
}
return stringBuilder.toString();

Categories