Count no of lines between two lines - java

How to achieve the following. Here is a sample text file..
AH
1
2
3
BH
21
BT03
CH
CT02
AT10
This is a sample text file. I need read each line and find the count.. For example, there are 10 Lines within A record.. And 3 lines within B record and two lines within C Record.
How do I get this count. H-Header and T-Trailer. You may say, read the T record to find the count, but that count might be wrong. Hence I am trying to find the count and update the trailer records correctly.
I cannot upload the Java code I have written as I'm on mobile now.. Any suggestions is highly appreciated
Thanks

I'm not sure if I understand your question, you just want to count lines in a file? Try something like this:
Path path = Paths.get("yourFile.txt");
long lineCount = Files.lines(path).count();

use below code and read all file in array.
String[] stringArray = new String[10];
int length = stringArray.length;
for (int i = 0; i < length; i++) {
String stringI = stringArray[i];
if (stringI.contains("H")) {
// Head rec
String headRecName = stringI.replace("H", "");
int count = 1;
for (int j = i + 1; j < length; j++) {
count++;
String stringJ = stringArray[j];
if (stringJ.contains("T") && headRecName.equals(stringJ.replace("T", ""))) {
stringArray[j] = stringArray[j] + count;
}
}
}
}
}

Related

turning an array of strings into a 2d array of chars

my code reads input from a file that has a maze written inside, inside the file looks like this.
7 7
GOOOOXO
XXOXOOX
OXOOOXX
XXXOOXO
XXXXOXX
SOOOOOX
XXXXXXX (these are each on a separate line not sure how to show that here)
the numbers are the dimensions and G is goal S is start, that doesn't really matter for now. I read the file into an array of Strings line by line. So my array looks like this {"GOOOOXO",...,"XXXXXXX"} now I want to convert the strings to a 2d array of chars where the characters are stored the same way as the maze is displayed above.
The first nested for loop just reads the files input and saves each line as a string in the array, the second array is meant to convert the strings into characters to save them into the 2d array and still manage to keep the shape of the maze. I get an array index out of bounds exception. But to be honest with you after hours of being stuck on this my brain is fried, I can't figure out my issue.
int dimensionsX = input.nextInt();
int dimensionsY = input.nextInt();
String[] lines = new String[dimensionsY];
char[][] maze2 = new char[dimensionsX][dimensionsY];
for (int j = 0; j < dimensionsY; ++j) {
if (input.hasNextLine()) {
lines[j] = input.nextLine();
System.out.println(lines[j]);
//System.out.println(j);
}
}
for (int i = dimensionsX; i > 0; --i) {
for (int j = dimensionsY; j > 0; --i) {
maze2[i][j] = lines[i].charAt(j);
System.out.print(maze2[i][j]);
if (i == lines.length) {
System.out.println();
}
}
}
For example:
int dimensionsX = input.nextInt();
int dimensionsY = input.nextInt();
String[] lines = new String[dimensionsY];
char[][] maze2 = new char[dimensionsY][];
for (int j = 0; j < dimensionsY; ++j) {
if (input.hasNextLine()) {
lines[j] = input.nextLine();
if(lines[j].length()<dimensionsX){
System.err.println("we are doomed. Input malformed in line j: it has less then" + dimensionsX + "characters");
System.exit(1);
}
maze2[j] = lines[j].toCharArray();
System.out.println(lines[j]);
//System.out.println(j);
}else{
System.err.println("we are doomed. Input has too few lines");
System.exit(1);
}
}
//taken as is, but makes me wonder if it is intended to have dimensionsX as the Y coordinate but well...
for (int i = dimensionsX; i > 0; --i) {
for (int j = dimensionsY; j > 0; --j) {
System.out.print(maze2[j-1][i-1]);
}
System.out.println();
}
Of course you want to do something different than exiting the program if the input is malformed e.g. throw an exception, or do nothing at all if your input is always correct(well is it?).

CSV reader perils - Java

I'm trying to read a CSV file and split each line into 4 different integer values via a two-dimensional array in java.
I'm using openCSV 3.8.
For the sake of simplicity, say this is the contents of the CSV file (the full file contains 306 lines just like these):
76,67,0,1
77,65,3,1
78,65,1,2
83,58,2,2
I can read the file just fine, and I can use System.out.println to output each single value to the console, like this:
76
67
0
1
77
65
3
1
78
65
1
2
85
58
2
2
Unfortunately with my code below, designed to enter each value into a separate array element only saves the 4 values in the last line of the file.
And here is my java code (don't mind the size of the iaData array, it's sized for the full CSV file):
public static void main(String[] args) {
//String outputStr = "";
int[][] iaData = new int[306][4];
int i = 0;
int x = 0;
try
{
//Get the CSVReader instance with specifying the delimiter to be used
CSVReader reader = new CSVReader(new FileReader("haberman.data"),',');
String [] nextLine = new String[1250];
//Read one line at a time
while ((nextLine = reader.readNext()) != null)
{
for (i = 0; i <= 305; i++)
{
for (x = 0; x <= 3; x++)
{
iaData[i][x] = Integer.parseInt(nextLine[x]);
}
}
}
for (int z = 0; z <= 3; z++)
{
System.out.println(iaData[0][z] + "\n");
}
reader.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
With this code, I would expect my System.out.println(iaData[0][z] + "\n"); to output the following to the console (the values in the first line of the file):
76
67
0
1
Unfortunately it's not the case, it actually outputs the following (the 4 values in the last line of the file):
83
58
2
2
What is wrong with my code such that iaData[0][0/1/2/3] actually outputs what I would expect to be held in iaData[**3**][0/1/2/3]?
For every line, you start writing with first index i=0.
So for every line you override all information from the line before:
while ((nextLine = reader.readNext()) != null)
{
for (i = 0; i <= 305; i++)
{
for (x = 0; x <= 3; x++)
{
iaData[i][x] = Integer.parseInt(nextLine[x]);
}
}
}
This should solve your problem:
int i = 0;
while ((nextLine = reader.readNext()) != null) {
for (x = 0; x <= 3; x++) {
iaData[i][x] = Integer.parseInt(nextLine[x]);
}
i++;
}
Your current problem is that for each line you are iterating over the entire 2D array, both rowwise and columnwise. This has the effect that only the last row will reflect the currently read line.
Instead, the row counter i should only be incremented after another line has been read from the CSV file. Currently, you are incrementing i for the same line over and over again.
// Read one line at a time
int i = 0;
while ((nextLine = reader.readNext()) != null) {
for (x = 0; x <= 3; x++) {
iaData[i][x] = Integer.parseInt(nextLine[x]);
}
// increment i once, after having processed a single line from the file
++i;
}
There are various things in your code that simply don't make sense.
First, you are init'ing nextLine to probably hold 1250 lines.
String [] nextLine = new String[1250];
But then, you are pushing a single line into that:
while ((nextLine = reader.readNext()) != null)
Either you don't need the first statement; or something is wrong about the second one.
For the actual bug you are observing: it doesn't help that you keep writing the same lines 395 times, too. And that is what your code is doing; because for each line that you read, you do
for (i = 0; i <= 305; i++)
{
for (x = 0; x <= 3; x++)
{
hiaData[i][x] = Integer.parseInt(nextLine[x]);
So you keep overwriting your data, instead of
line1
line2
...
you keep writing
line i
line i...
Thus, in the end, you only got your last line in there.
My recommendation: don't do all that manual size-dependent iterating yourself. Simply use
List<String[]> allLines = csvreader.readAll();
4 values, 395 lines ... that is nothing. Just push all of that into memory with that one call.
Meaning: the library offers you a nice abstraction that requires you one line of code to read all content. You choose to write 20, 30 lines of code instead. And that is the thing: the more code you write, the higher are chances to create bugs.
And finally: do not use such numbers as 305, 4, 1205 directly in your source code. If at all, use constants there. But hard-coding those values in your loops ... very bad practice - you have to change each and any place that deals with your input when for example 5 columns come in, instead of 4.
If the program is going to read the whole file into an array ... is it not enough to read it into memory, and process it later?
Like so:
import au.com.bytecode.opencsv.CSVReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.List;
public class Csv {
public static void main(String[] args) throws IOException {
String string = "76,67,0,1\n" +
"77,65,3,1\n" +
"78,65,1,2\n" +
"83,58,2,2";
CSVReader reader = new CSVReader(new StringReader(string),',');
List<String[]> lines = reader.readAll();
for (String[] entries : lines) {
for (String entry: entries) {
System.out.println(Integer.parseInt(entry));
}
}
}
}
Beware of memory issues and set an upper bound or process a line a time by changing the loop like so:
String[] entries;
while((entries = reader.readNext()) != null) {
for (String entry : entries) {
System.out.println(Integer.parseInt(entry));
}
}
Problems:
1.
for (i = 0; i <= 305; i++)
This cycle is not needed, as reader.readNext() will gather all the lines without the need of further help. So, this is certainly an improvement:
int i = 0;
while ((nextLine = reader.readNext()) != null)
{
//for (i = 0; i <= 305; i++)
//{
for (x = 0; x <= 3; x++)
{
iaData[i++][x] = Integer.parseInt(nextLine[x]);
}
//}
}
2.
The other problem you have is that you iterate only the elements of the first element:
for (int z = 0; z <= 3; z++)
{
System.out.println(iaData[0][z] + "\n");
}
Instead:
for (i = 0; i < iaData.length; i++)
{
for (int z = 0; z <= 3; z++)
{
System.out.println(iaData[i][z] + "\n");
}
System.out.println("");
}

Data structure usage

I recently faced a question where I need to display the last n lines in a file in java. It is similar to implementing tail function of unix in java but I just have readline() method and a method to check the end of file. No other methods. I was thinking of an approach with Queue data structure like this:
Read n lines starting from the first line of the file.
store the n lines read in the queue.
Check if we have reached the end of file. If yes, print the contents of the queue.
If not, read n more lines and push them in the queue.
Can anyone think of any other approach?
What about a ring buffer of size n where you override the oldest entry?
It would basically look like the code below. I made up the functions to read the file but you should get the idea.
String[] lines = new String[n];
int i = 0;
while(!file.eof()) {
String line = file.readLine();
lines[i] = line;
i = (i + 1) % n;
}
for(int j = 0; j < n; j++) {
if (lines[i] != null) {
System.out.println(lines[i]);
}
i = (i + 1) % n;
}

How to determine ASCII value of a word

I am creating a program that imports a large list of words. This list has been separated by word but I now need to determine the ASCII value of each word in this list, and eventually which one has the highest total ASCII value. I am receiving a few errors and need to know how to get this corrected so that I can get each value.
public static void main(String[] args) throws IOException {
//import list of words
BufferedReader File = new BufferedReader(new FileReader(LOC));
//Create a temporary ArrayList to store data
ArrayList<String> words = new ArrayList<String>();
//Find number of lines in txt file
String line;
String delimiter = "\t";
while ((line = File.readLine()) != null)
//read the file
{
String[] wordsInLine = line.split(delimiter);
//separate the words
for(int i=0, isize = wordsInLine.length; i < isize; i++){
words.add(wordsInLine[i]);//put them in a list
//assess each character in the word to determine the ascii value
int total = 0;
for (int i=0; i < wordsInLine.length(); i++)
Receiving an error on the above line that states - Cannot invoke length() on the array type
String[]
- Duplicate local variable i
{
char c = word.charAt(i);
Receiving an error on the above line that states word cannot be resolved
int j = (int) c;
total += c;
}
I have done some research trying to determine the best way to calculate the ASCII value of each word and I haven't been able to find much information on how to do this. If someone could please take a look at my code I would appreciate it!! Also, before anyone says it let me just say this is NOT a school project. I am on summer break and beginning programming II in the fall and just trying to keep up on coding so that I am not rusty in the fall. THANK YOU!!! :))
Receiving an error on the above line that states - Cannot invoke length() on the array type String[] - Duplicate local variable i
wordsInLine is an array, and length is property of array. So, you have to use:
wordsInLine.length
If wordsInLine was a String, then wordsInLine.length() would have made sense.
Receiving an error on the above line that states word cannot be resolved
Before the line char c = word.charAt(i);, add below:
String word = wordsInLine[i];
For the wordsInLine.length() issue, length() is not a valid method for arrays. You actually have to access the length field thusly: wordsInLine.length without ().
As for word.charAt(i), you haven't declared a variable called word anywhere which is what's causing the problem. What you really want to do is sum up the values for every word in the array, and for that you need a nested loop.
You also said that you wanted to figure out which one had the highest value. To do that, just keep track of the largest one and update it after each iteration like this:
int indexOfMax = 0;
int[] sums = new int[wordsInLine.length];
//Iterate over every word
for(int i = 0; i < wordsInLine.length; i++)
{
//Reset the total for each word
total = 0;
//Iterate over every character in the word
for(int j = 0; j < wordsInLine[i].length(); j++)
{
char c = wordsInLine[i].charAt(j);
total += c;
}
//Remember the sum for this word
sums[i] = total;
//If the word's sum is greater than our previous max,
//make it the new max
if(sums[i] > sums[indexOfMax])
{
indexOfMax = i;
}
}
And now you can get the word with the greatest ASCII value by calling wordsInLine[indexOfMax]. It will have an ASCII sum of sums[indexOfMax].
wordsInLine is an array and therefore it does not have a method to get its length. Instead, to get an array's length, use array.length as opposed to what you were doing: array.length() (which causes an error).
word is not a defined variable, this is why java is saying that it cannot be resolved (it can't find any declaration). Instead you want to use 2 for loops in order to loop over every character in the word in the array wordsInLine. You also have two instances of the variable i, this is not allowed. To fix these errors write the following code after `int total = 0;':
int total = 0; // Don't rewrite this line
int[] totals = new int[wordsInLine.length]; // If you want to add all your totals to an array
for (int j=0; j < wordsInLine.length; j++) {
total = 0;
for (int k=0; k < wordsInLine[j].length(); k++) { // Here wordsInLine[j] is a string so you use .length() instead of .length
char c = wordsInLine[j].charAt(k);
int w = (int) c; // Get ascii of c
total += w; // Add it to total
}
// Do something with the total of this word before it gets reset to 0
// Maybe add it to an array of totals:
totals[j] = total;
}
I hope this helps!
Well your organization of your code needs a little bit of work.
First I would take this whole block of code outside file read in while loop.
for (int i=0; i < wordsInLine.length(); i++)
{
char c = word.charAt(i);
int j = (int) c;
total += c;
}
Why? Lets split what you are doing into two steps. Read in all the words into the word list. After doing this you will find where your core root of the problem is. You aren't reading the words from your word list at all.
Further code cleanup
for(int i=0, isize = wordsInLine.length; i < isize; i++){
This line is a little bit bloated. You don't need isize at all you are essentially doing denoting it for no reason. (Well actually caching the length does improve efficiency, another talk for another day). Cleaning up.
for(int i=0, ; i < wordsInLine.length; i++){
Then fixing the entire project
//import list of words
BufferedReader File = new BufferedReader(new FileReader(LOC));
//Create a temporary ArrayList to store data
ArrayList<String> words = new ArrayList<String>();
//Find number of lines in txt file
String line;
String delimiter = "\t";
// adds all the words into the list.
while ((line = File.readLine()) != null)
{
String[] wordsInLine = line.split(delimiter);
for(int i=0, ; i < wordsInLine.length; i++){
// compute alg and store the value some how to the word.
words.add(wordsInLine[i])
}
}
// notice outside the while loop.
// .size() is used for lists and .length is used for arrays.
for(int i = 0; i < words.size(); i++){
// compare
}

Split a String Twice

Not sure if my mind is just numb or I am just stupid, but for some reason the logic behind this escapes me. Essentially in an android app I am pulling CSV information through a PHP script. That information gets displayed like
value00,value01,value02,value03,value04;value10,value11,value12,value13,value14;value20, etc...
now I want to set up a two dimensional array where thisArray[0][0] = value00, thisArray[1][1] = value11, thisArray[1][4] = value14, etc. The code I have will split by the ";" but I can't figure out how to then split that array into a two dimensional array set up the way I want. This is what I have: (httpMessage is the string containing the above information)
String[][] secondSplit;//
String[] firstSplit;//
String currvalue;//
firstSplit = httpMessage.split(";");
for(int i=0; i<firstSplit.length; i++) {
Log.d("EFFs" + Integer.toString(i),firstSplit[i]);
}
LogCat shows the desired behavior, EFFs0 = line 1, EFFs1 = line 2, just the way I want it. But now, how do I get that second dimension? Also, since I am 100% sure this is a dumb question with an easy answer I'll throw in another, is there an easy way to tell if a string is a number?
You could do the following:
secondSplit = new String[firstSplit.length][];
for(int i=0; i<firstSplit.length; i++){
secondSplit[i] = firstSplit[i].split(",");
}
Pretty sure that would work. Let me know if it doesn't! Hope that helps!
If you know how many rows and columns there are you can use the Scanner class like this (recently learned this from this answer):
Scanner sc = new Scanner(input).useDelimiter("[,;]");
final int M = 5;
final int N = 2;
String[][] matrix = new String[M][N];
for (int r = 0; r < M; r++) {
for (int c = 0; c < N; c++) {
matrix[r][c] = sc.next();
}
}
//Just to see that it worked
for(String[] row : matrix) {
for(String col : row) {
System.out.print(col+",");
}
System.out.println();
}

Categories

Resources