Reading N lines from a file in java? - java

I am not quite sure how to explain my question but I will try my best. Say for example, I have a file containing 100 numbers, is it possible to read lines 25-50 from this 100 numbers file.
To read N amount from begining, I would do something like this;
ArrayList<Double> array = new ArrayList<Double>();
Scanner input = new Scanner(new File("numbers.txt"));
int counter = 0;
while(input.hasNextLine() && counter < 10)
{
array.add(Double.parseDouble(input.nextLine()));
counter++;
}
But I am not quite sure how I can go about start reading from a given line e.g. lines 25-50 or 25-75 or 75-100 etc.
Any help is much appreciated and please let me know if my question is not clear.
edit:
Some data in the file:
1.45347,1.1545,1.2405
1.467,1.4554,1.2233
1.4728,1.3299,1.1532
1.131,1.5139,1.0044
1.4614,1.7373,1.6235
1.654,1.5544,1.61147

byte[] inputBytes = "line 1\nline 2\nline 3\ntok 1 tok 2".getBytes();
Reader r = new InputStreamReader(new ByteArrayInputStream(inputBytes));
BufferedReader br = new BufferedReader(r);
Scanner s = new Scanner(br);
System.out.println("First line: " + br.readLine());
System.out.println("Second line: " + br.readLine());
System.out.println("Third line: " + br.readLine());
System.out.println("Remaining tokens:");
while (s.hasNext())
System.out.println(s.next());
and add a while loop like Astra suggested

Using Java 8 you have an easy solution. Note that the below code does not make any bounds checking of any kind (this is left as an exercise):
private static final Pattern COMMA = Pattern.compile(",");
public static List<Double> readNumbers(final String file,
final int startLine, final int endLine)
throws IOException
{
final long skip = (long) (startLine - 1);
final long limit = (long) (endLine - startLine);
final Path path = Paths.get(file);
try (
final Stream<String> stream = Files.lines(path, StandardCharsets.UTF_8);
) {
return stream.skip(skip).limit(limit)
.flatMap(COMMA::splitAsStream)
.map(Double::valueOf)
.collect(Collectors.toList());
}
}
It also appears that the problem is unclear; the code above reads all doubles in a given line range. If what you want is to read all doubles from a given start "index" to a given end "index", all you have to do in the code above is change the placement of the .skip().limit() to after the .map().

Assuming you have multiple numbers (unknown number of numbers) on each line:
int start = 25;
int n finish = 50;
String delimit = ",";
List<Double> array = new ArrayList<Double>(finish - start);
Scanner input = new Scanner(new File("numbers.txt"));
int counter = 1;
while(input.hasNextLine() && counter <= finish)
{
String line = input.nextLine();
String[] splits = line.split(delimit);
for (int i=0; i<splits.length; i++){
if (counter >= start && counter <=finish){
array.add(Double.parseDouble(splits[i]));
}
counter++;
}
}

Related

Using Scanner to read Strings in Java

I'm trying to read a file called "CityData.txt" that just has a list of city names in it, one on each line. I've been using scanner in the past to read Strings from a file, and am using it to read ints from another file in this same program, however it doesn't seem to be reading anything from the file.
int counter2 = 0;
File strFile = new File("CityData.txt");
Scanner strScanner = new Scanner(strFile);
Scanner strCountScanner = new Scanner(strFile);
while ((strScanner.hasNext() == true)) {
System.out.println(strScanner.nextLine());
counter2++;
}
System.out.println("This is counter2: " + counter2);
String[] array2 = new String[counter2];
while ((strCountScanner.hasNext() == true)) {
for (int i = 0; i < counter2; i++) {
array2[i] = strCountScanner.nextLine();
}
}
Ideally, counter2 will tell me how many cities are in the file, and I'll then populate array2 with them. However, counter2 remains at 0 after the program has been run. I've been fiddling with this for a while, and am hoping that maybe I've just missed something silly.
Thanks
You are trying to add cities to an array?
public static void readText throws FileNotFoundException {
ArrayList lines = new ArrayList();
Scanner scan = new Scanner(new File("CityData.txt"));
while(scan.hasNextLine()){
String line = scan.nextLine();
lines.add(line);
}
}
or a stream in 8
Stream <String> lines = Files.lines(Paths.get("c:\\demo.txt"));
lines.forEach(System.out::println);
lines.close();
Ideally I would avoid two loops and just use an ArrayList for this purpose. This can give you count as well as the flexibility to make the array more dynamic. Also I would enclose Scanner in try with resources block as it closes the resource itself. Here is the code for reference.
File strFile = new File("CityData.txt");
try (Scanner strScanner = new Scanner(strFile)) {
ArrayList<String> arrayList = new ArrayList<>();
while (strScanner.hasNext()) {
arrayList.add(strScanner.nextLine());
}
System.out.println("number of cities is " + arrayList.size());
System.out.println("cities are " + arrayList);
}catch (Exception e){
e.printStackTrace();
}
Since you are reading in string, using hasNextLine() will be more appropriate. You can try the code below, it should work as intended. HTH.
int counter2 = 0;
File strFile = new File("CityData.txt");
Scanner strScanner = new Scanner(strFile);
Scanner strCountScanner = new Scanner(strFile);
while((strScanner.hasNextLine() == true)) {
System.out.println(strScanner.nextLine());
counter2++;
}
System.out.println("This is counter2: " + counter2);
String[] array2 = new String[counter2];
while((strCountScanner.hasNextLine() == true)) {
for (int i = 0; i < counter2; i++) {
array2[i] = strCountScanner.nextLine();
}
}

Take values from a text file and put them in a array

For now in my program i am using hard-coded values, but i want it so that the user can use any text file and get the same result.
import java.io.IOException;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.File;
public class a1_12177903
{
public static void main(String [] args) throws IOException
{
if (args[0] == null)
{
System.out.println("File not found");
}
else
{
File file = new File(args[0]);
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
String line = "";
while (br.ready())
{
line += br.readLine();
}
String[] work = line.split(",");
double[] doubleArr = new double[work.length];
for (int i =0; i < doubleArr.length; i++)
{
doubleArr[i] = Double.parseDouble(work[i]);
}
double maxStartIndex=0;
double maxEndIndex=0;
double maxSum = 0;
double total = 0;
double maxStartIndexUntilNow = 0;
for (int currentIndex = 0; currentIndex < doubleArr.length; currentIndex++)
{
double eachArrayItem = doubleArr[currentIndex];
total += eachArrayItem;
if(total > maxSum)
{
maxSum = total;
maxStartIndex = maxStartIndexUntilNow;
maxEndIndex = currentIndex;
}
if (total < 0)
{
maxStartIndexUntilNow = currentIndex;
total = 0;
}
}
System.out.println("Max sum : "+ maxSum);
System.out.println("Max start index : "+ maxStartIndex);
System.out.println("Max end index : " +maxEndIndex);
}
}
}
I've fixed it so it takes in the name of the text file from the command line. if anyone has any ways to improve this, I'll happily accept any improvments.
You can do this with Java8 Streams, assuming each entry has it's own line
double[] doubleArr = Files.lines(pathToFile)
.mapToDouble(Double::valueOf)
.toArray();
If you were using this on production systems (rather than as an exercise) it would be worth while to create the Stream inside a Try with Resources block. This will make sure your input file is closed properly.
try(Stream<String> lines = Files.lines(path)){
doubleArr = stream.mapToDouble(Double::valueOf)
.toArray();
}
If you have a comma separated list, you will need to split them first and use a flatMap.
double[] doubleArr = Files.lines(pathToFile)
.flatMap(line->Stream.of(line.split(","))
.mapToDouble(Double::valueOf)
.toArray();
public static void main(String[] args) throws IOException {
String fileName = "";
File inputFile = new File(fileName);
BufferedReader br = new BufferedReader(new FileReader(inputFile));
// if input is in single line
StringTokenizer str = new StringTokenizer(br.readLine());
double[] intArr = new double[str.countTokens()];
for (int i = 0; i < str.countTokens(); i++) {
intArr[i] = Double.parseDouble(str.nextToken());
}
// if multiple lines in input file for a single case
String line = "";
ArrayList<Double> arryList = new ArrayList<>();
while ((line = br.readLine()) != null) {
// delimiter of your choice
for (String x : line.split(" ")) {
arryList.add(Double.parseDouble(x));
}
}
// convert arraylist to array or maybe process arrayList
}
This link may help: How to use BufferedReader. Then you will get a String containing the array.
Next you have several ways to analyze the string into an array.
Use JSONArray to parse it. For further information, search google for JSON.
Use the function split() to parse string to array. See below.
Code for way 2:
String line="10,20,50";//in fact you get this from file input.
String[] raw=line.split(",");
String[] arr=new String[raw.length];
for(int i=0;i<raw.length;++i)arr[i]=raw[i];
//now arr is what you want
Use streams if you are on JDK8. And please take care of design principles/patterns as well. It seems like a strategy/template design pattern can be applied here. I know, nobody here would ask you to focus on design guidelines.And also please take care of naming conventions. "File" as class name is not a good name.

Count number of sentences in a text file

Sentences I guess being string that end in ! ? .
Excepting thing like Dr. Mr.
It is true that you cannot really know a sentence in java because of grammar.
But I guess what I mean is a period or exclamation mark or question mark and then what follows being a capital letter.
How would one do this.
This be what I have
But its not working.....
BufferedReader Compton = new BufferedReader(new FileReader(fileName));
int sentenceCount=0;
String violet;
String limit="?!.";
while(Compton.ready())
{
violet=Compton.readLine();
for(int i=0; i<violet.length()-1;i++)
{
if(limit.indexOf(violet.charAt(i)) != -1 && i>0 && limit.indexOf(violet.charAt(i-1)) != -1)
{
sentenceCount++;
}
}
}
System.out.println("the amount of sentence is " + sentenceCount);
EDIT
New way that works better
String violet;
while(Compton.ready())
{
violet=Compton.readLine();
sentenceCount=violet.split("[!?.:]+").length;
System.out.println("the number of words in line is " +
sentenceCount);
}
BufferedReader reader = new BufferedReader(new FileReader(fileName));
int sentenceCount = 0;
String line;
String delimiters = "?!.";
while ((line = reader.readLine()) != null) { // Continue reading until end of file is reached
for (int i = 0; i < line.length(); i++) {
if (delimiters.indexOf(line.charAt(i)) != -1) { // If the delimiters string contains the character
sentenceCount++;
}
}
}
reader.close();
System.out.println("The number of sentences is " + sentenceCount);
One liner:
int n = new String (Files.readAllBytes(Paths.get(path))).split ("[\\.\\?!]").length
Uses Java 7 constructs to read whole file to byte array, create a string from that and split into sentence array then gets the length of the array.
A potential way to do this is to scan your file as words and then count words that are not in your exception list that end in your given punctuation.
Here's a possible implementation using Java 8 streams:
List<String> exceptions = Arrays.toList("Dr.", "Mr.");
Iterable<String> iterableScanner = () -> new Scanner(filename);
int sentenceCount = StreamSupport.stream(iterableScanner, false)
.filter(word -> word.matches(".*[\\.\\?!]))
.filter(word -> !exceptions.contains(word))
.count();

Trying to find the nth element to the last from a list (with a file input)

Input would look like
a b c d 4
e f g h 2
where each line would be read like a list and integer representing as an index in the list
I first try to read the file line be line and store it in the list. Heres what i have
public class FileReader {
public static void main(String[] args) {
String line = null;
List<String> list = new ArrayList<String>();
try {
FileInputStream fstream = new FileInputStream("test.txt");
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
// File file = new File("test.txt");
// Scanner scanner = new Scanner(file);
while ((line = br.readLine()) != null) {
list.add(line);
}
System.out.println(list);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Now i want to remove the white spaces from the list and store the values in char array and then i was planning on traversing that array backwards till the nth element, depending on the input for n.
String[] elements = line.trim().split("\\s");
char[] chars = new char[elements.length - 1];
int i= Integer.parseInt(elements[elements.length - 1]);
for (i = 0; i < elements.length - 1; i++)
char[i] = elements[i].charAt(i);
Someone provided me this piece of code earlier and i tried it and it throws a nullpointerexception at String[] elements.
It's because you are running until line is null here
while((line = br.readLine()) != null)
{
list.add(line);
}
And then you are trying to call .trim() on it.
Do you mean to be processing the strings in list instead?
If so try looping over you list, you are already splitting it correctly and getting the last element. All you need to do is caluclate the offset, in this case it will be the length - 1 - the last element, in you String[] elements and you can print that out.
for (int i = 0; i < list.size(); i++)
{
String currentLine = list.get(i);
String[] elements = currentLine.trim().split("\\s");
int lastElement = Integer.parseInt(elements[elements.length - 1]);
String desiredValue = elements[elements.length - 1 - lastElement];
System.out.println("desiredValue = " + desiredValue);
}
You can avoid most of the work you're doing. I don't know if your input will require much flexibility (code to that if necessary) but in your example you only have 1 digit for the index.
Just avoid all the traversing and looping entirely:
String currentLine = file.nextLine();
//Find value from last space in the string, until the end of the string (will be the number)
int index = Integer.parseInt(currentLine.substring(
currentLine.lastIndexOf(' ') + 1, currentLine.length()));
//Remove all spaces from the current line
currentLine = currentLine.replaceAll("\\s+","");
//Remove the index at the end from the string, leaving only the characters
currentLine = currentLine.substring(0, currentLine.indexOf(index + ""));
char desiredValue = currentLine.charAt(currentLine.length() - index);
System.out.println("desiredValue = " + desiredValue);
This saves a lot of adding stuff to arrays if none of that is needed later, just do it all the first time through.

Java Reading 2D array in from file, numbers separated by comma

This is some code that I found to help with reading in a 2D Array, but the problem I am having is this will only work when reading a list of number structured like:
73
56
30
75
80
ect..
What I want is to be able to read multiple lines that are structured like this:
1,0,1,1,0,1,0,1,0,1
1,0,0,1,0,0,0,1,0,1
1,1,0,1,0,1,0,1,1,1
I just want to essentially import each line as an array, while structuring them like an array in the text file.
Everything I have read says to use scan.usedelimiter(","); but everywhere I try to use it the program throws straight to the catch that replies "Error converting number". If anyone can help I would greatly appreciate it. I also saw some information about using split for the buffered reader, but I don't know which would be better to use/why/how.
String filename = "res/test.txt"; // Finds the file you want to test.
try{
FileReader ConnectionToFile = new FileReader(filename);
BufferedReader read = new BufferedReader(ConnectionToFile);
Scanner scan = new Scanner(read);
int[][] Spaces = new int[10][10];
int counter = 0;
try{
while(scan.hasNext() && counter < 10)
{
for(int i = 0; i < 10; i++)
{
counter = counter + 1;
for(int m = 0; m < 10; m++)
{
Spaces[i][m] = scan.nextInt();
}
}
}
for(int i = 0; i < 10; i++)
{
//Prints out Arrays to the Console, (not needed in final)
System.out.println("Array" + (i + 1) + " is: " + Spaces[i][0] + ", " + Spaces[i][1] + ", " + Spaces[i][2] + ", " + Spaces[i][3] + ", " + Spaces[i][4] + ", " + Spaces[i][5] + ", " + Spaces[i][6]+ ", " + Spaces[i][7]+ ", " + Spaces[i][8]+ ", " + Spaces[i][9]);
}
}
catch(InputMismatchException e)
{
System.out.println("Error converting number");
}
scan.close();
read.close();
}
catch (IOException e)
{
System.out.println("IO-Error open/close of file" + filename);
}
}
I provide my code here.
public static int[][] readArray(String path) throws IOException {
//1,0,1,1,0,1,0,1,0,1
int[][] result = new int[3][10];
BufferedReader reader = new BufferedReader(new FileReader(path));
String line = null;
Scanner scanner = null;
line = reader.readLine();
if(line == null) {
return result;
}
String pattern = createPattern(line);
int lineNumber = 0;
MatchResult temp = null;
while(line != null) {
scanner = new Scanner(line);
scanner.findInLine(pattern);
temp = scanner.match();
int count = temp.groupCount();
for(int i=1;i<=count;i++) {
result[lineNumber][i-1] = Integer.parseInt(temp.group(i));
}
lineNumber++;
scanner.close();
line = reader.readLine();
}
return result;
}
public static String createPattern(String line) {
char[] chars = line.toCharArray();
StringBuilder pattern = new StringBuilder();;
for(char c : chars) {
if(',' == c) {
pattern.append(',');
} else {
pattern.append("(\\d+)");
}
}
return pattern.toString();
}
The following piece of code snippet might be helpful. The basic idea is to read each line and parse out CSV. Please be advised that CSV parsing is generally hard and mostly requires specialized library (such as CSVReader). However, the issue in hand is relatively straightforward.
try {
String line = "";
int rowNumber = 0;
while(scan.hasNextLine()) {
line = scan.nextLine();
String[] elements = line.split(',');
int elementCount = 0;
for(String element : elements) {
int elementValue = Integer.parseInt(element);
spaces[rowNumber][elementCount] = elementValue;
elementCount++;
}
rowNumber++;
}
} // you know what goes afterwards
Since it is a file which is read line by line, read each line using a delimiter ",".
So Here you just create a new scanner object passing each line using delimter ","
Code looks like this, in first for loop
for(int i = 0; i < 10; i++)
{
Scanner newScan=new Scanner(scan.nextLine()).useDelimiter(",");
counter = counter + 1;
for(int m = 0; m < 10; m++)
{
Spaces[i][m] = newScan.nextInt();
}
}
Use the useDelimiter method in Scanner to set the delimiter to "," instead of the default space character.
As per the sample input given, if the next row in a 2D array begins in a new line, instead of using a ",", multiple delimiters have to be specified.
Example:
scan.useDelimiter(",|\\r\\n");
This sets the delimiter to both "," and carriage return + new line characters.
Why use a scanner for a file? You already have a BufferedReader:
FileReader fileReader = new FileReader(filename);
BufferedReader reader = new BufferedReader(fileReader);
Now you can read the file line by line. The tricky bit is you want an array of int
int[][] spaces = new int[10][10];
String line = null;
int row = 0;
while ((line = reader.readLine()) != null)
{
String[] array = line.split(",");
for (int i = 0; i < array.length; i++)
{
spaces[row][i] = Integer.parseInt(array[i]);
}
row++;
}
The other approach is using a Scanner for the individual lines:
while ((line = reader.readLine()) != null)
{
Scanner s = new Scanner(line).useDelimiter(',');
int col = 0;
while (s.hasNextInt())
{
spaces[row][col] = s.nextInt();
col++;
}
row++;
}
The other thing worth noting is that you're using an int[10][10]; this requires you to know the length of the file in advance. A List<int[]> would remove this requirement.

Categories