java indexoutofboundexpection in using grep and awk - java

I have a file containing lines with the format of a,b,c,d,e,f.
I wrote the following Java code to return the list myextracting b,c,d,e,f by looking for b as key.
public static List<String> getThirdFourthFifthColumnBySecondColumnByCliTools(String filePath, String key) throws IOException {
List<String> list = new ArrayList<>();
String command = "grep " + key + " " + filePath + " | awk -F ',' '{print $3,$4,$5}'";
Process process = Runtime.getRuntime().exec(command);
Scanner sc = new Scanner(process.getInputStream());
while (sc.hasNextLine()) {
String line = sc.nextLine();
String[] split = line.split(" ");
for (int i = 0; i < split.length; i++) {
list.add(split[i]);
}
}
return list;
}
However I receive IndexOutOfBoundExcecption in my Java.
Can anyone please point out the problem in my code?

Related

Split lines with "," and do a trim on every element [duplicate]

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.

How to read in a file into a specific format

I have a file containing some data that looks like this.
[Todays date] Some text
some more text
even more text
[A different date] Some text
[Another different date] More text
Final text block
I'd like to read this into a List<String> if possible but I don't want to have it exactly like the file. Ideally the List<String> would look like.
[Todays date] some text some more text even more text
[A different date] some text
[Another different date] More text Final text block
If the line of text doesn't start with a squared bracket I want to just concatenate that line to the above line. I can read it in normally using this code. I tried to use String.startsWith but I couldn't figure it out.
List<String> testList = new ArrayList<String>();
BufferedReader br = new BufferedReader(new FileReader("SystemOut.log"));
String line = br.readLine();
while (line!=null) {
testList.add(line);
line=br.readLine();
}
br.close();
I'm looking for either a change to this method that will make it read it in to my desired format or maybe a method that will act on my List<String> and sort this problem. Thanks
A better solution (3rd attempt) which (hopefully) will work better with large files as it avoids reading the whole file into buffer:
public static void main(String[] args) throws IOException {
String input = "[04/06/2021] Some text\n" +
"some more text\n" +
"even more text\n" +
"[01/01/2020] Some text \n" +
"[31/12/2020] More text\n" +
"Final text block";
List<String> testList = new ArrayList<>();
try (BufferedReader br = new BufferedReader(new StringReader(input))) {
br.lines().forEach(
line -> {
if (testList.isEmpty() || line.startsWith("[")) {
testList.add(line + " ");
} else {
testList.set(
testList.size() - 1,
testList.get(testList.size() - 1) + line + " ");
}
}
);
}
testList.forEach(System.out::println);
}
I came up with this tedious method:
public static void main(String[] args) throws IOException {
String input = "[04/06/2021] Some text\n" +
"some more text\n" +
"even more text\n" +
"[01/01/2020] Some text \n" +
"[31/12/2020] More text\n" +
"Final text block";
List<String> testList = new ArrayList<>();
try (BufferedReader br = new BufferedReader(new StringReader(input))) {
String nextLine = br.readLine();
StringBuilder currentLine = new StringBuilder(nextLine + " ");
while (nextLine != null) {
nextLine = br.readLine();
if (nextLine != null) {
if (nextLine.startsWith("[")) {
testList.add(currentLine.toString());
currentLine = new StringBuilder();
}
currentLine.append(nextLine).append(" ");
}
}
if (currentLine.length() > 0) {
testList.add(currentLine.toString());
}
}
testList.forEach(System.out::println);
}
If you can move away from your loop, a better/simpler approach would be:
public static void main(String[] args) throws IOException {
String input = "[04/06/2021] Some text\n" +
"some more text\n" +
"even more text\n" +
"[01/01/2020] Some text \n" +
"[31/12/2020] More text\n" +
"Final text block";
List<String> testList = new ArrayList<>();
String[] inputs = input.split("\\n");
StringBuilder currentLine = new StringBuilder(inputs[0] + " ");
for (int i = 1; i < inputs.length; i++) {
if (inputs[i].startsWith("[")) {
testList.add(currentLine.toString());
currentLine = new StringBuilder();
}
currentLine.append(inputs[i]).append(" ");
}
testList.add(currentLine.toString());
testList.forEach(System.out::println);
}
Output:
[04/06/2021] Some text some more text even more text
[01/01/2020] Some text
[31/12/2020] More text Final text block

Java read specific parts of a CSV

I created the following code to read a CSV-file:
public void read(String csvFile) {
try {
File file = new File(csvFile);
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
String line = "";
String[] tempArr;
while((line = br.readLine()) != null) {
tempArr = line.split(ABSTAND);
anzahl++;
for(String tempStr : tempArr) {
System.out.print(tempStr + " ");
}
System.out.println();
}
br.close();
} catch(IOException ioe) {
ioe.printStackTrace();
}
}
I have a CSV with more than 300'000 lines that look like that:
{9149F314-862B-4DBC-B291-05A083658D69};Gebaeude;TLM_GEBAEUDE;;Schiessstand;{41C949A2-9F7B-41EE-93FD-631B76F2176D};Altdorf 300m;offiziell;Hochdeutsch inkl. Lokalsprachen;Einfacher Name;;684600;295930;400
How can I now only get the some parts out of that? I only need the bold/italic parts to work with.
Without further specifying what your requirements/input limitations are the following should work within your loop.
String str = "{9149F314-862B-4DBC-B291-05A083658D69};Gebaeude;TLM_GEBAEUDE;;Schiessstand;{41C949A2-9F7B-41EE-93FD-631B76F2176D};Altdorf 300m;offiziell;Hochdeutsch inkl. Lokalsprachen;Einfacher Name;;684600;295930;400";
String[] arr = str.split("[; ]", -1);
int cnt=0;
// for (String a : arr)
// System.out.println(cnt++ + ": " + a);
System.out.println(arr[6] + ", " + arr[15] + ", " + arr[16]);
Note that this assumes your delimiters are either a semicolon or a space and that the fields desired are in the fix positions (6, 15, 16).
Result:
Altdorf, 684600, 295930

NoSuchElementException in - Java

I am trying to read data from a text file and then store it to an array. I assume that there is one word per line. I am getting a NoSuchElementException here:
while (s.hasNextLine())
{
text = text + s.next() + " ";
}
This is my code:
public class ReadNote
{
public static void main(String[]args)
{
String text = readString("CountryList.txt");
System.out.println(text);
String[] words = readArray("CountryList.txt");
for (int i = 0; i < words.length; i++)
{
System.out.println(words[i]);
}
}
public static String readString(String file)
{
String text = "";
try{
Scanner s = new Scanner(new File(file));
while (s.hasNextLine())
{
text = text + s.next() + " ";
}
} catch(FileNotFoundException e)
{
System.out.println("file not found ");
}
return text;
}
public static String[] readArray(String file)
{
int ctr = 0;
try {
Scanner s1 = new Scanner(new File(file));
while (s1.hasNextLine())
{
ctr = ctr+1;
s1.next();
}
String[] words = new String[ctr];
Scanner s2 = new Scanner(new File(file));
for ( int i = 0; i < ctr; i++)
{
words [i] = s2.next();
}
return words;
} catch (FileNotFoundException e) { }
return null;
}
}
Here is the message.
Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:862)
at java.util.Scanner.next(Scanner.java:1371)
at ReadNote.readString(ReadNote.java:29)
at ReadNote.main(ReadNote.java:13)
For the specific exception you are getting in readString:
while (s.hasNextLine()) {
text = text + s.next() + " ";
}
You need to either call s.hasNext() in the loop guard, or use s.nextLine() in the body.
As described in this answer.
You have a single extra newline at the end of your file.
hasNextLine() checks to see if there is another linePattern in the buffer.
hasNext() checks to see if there is a parseable token in the buffer, as separated by the scanner's delimiter.
You should modify your code to one of the following
while (s.hasNext()) {
text = text + s.next() + " ";
}
while (s.hasNextLine()) {
text = text + s.nextLine() + " ";
}
There are 2 issues with your code as far as I can tell:
You forgot to check hasNextLine() for your second Scanner s2.
When using Scanner you need to check if there is a next line with hasNextLine(), and it will return null at EOF.
You probably want s.nextLine() instead of s.next() in your while loop since you are checking while (s1.hasNextLine()). In general, you have to match your .hasNext... to your .next....

Trying to concatenate a series of strings via array

having a little bit of an issue. I am looping through a file where by I want to filter out a series of texts and concatenate them at the end of each loop, which then ultimately end up ordering i.e. during the loop phase it does the following:
String A = "A /n"
String A = "A /n U /n"
String A = "A /n U /n B /n"
etc...
The output will be
A
U
B
however i want it to be
A
B
U
I have so far done the following:
public static void organiseFile() throws FileNotFoundException {
ArrayList<String> lines = new ArrayList<>();
ArrayList<String> order = new ArrayList<>();
String directory = "C:\\Users\\xxx\\Desktop\\Files\\ex1";
Scanner fileIn = new Scanner(new File(directory + "_ordered.txt"));
PrintWriter out = new PrintWriter(directory + "_orderesqsd.txt");
String otherStates = "";
while (fileIn.hasNextLine() == true) {
lines.add(fileIn.nextLine());
System.out.println("Organising...");
}
Collections.sort(lines);
for (String output : lines) {
if (output.contains("[EVENT=agentStateEvent]")) {
out.println(output + "\n");
out.println(otherStates + "\n");
otherStates = "";
}
else {
otherStates += output+ "\n";
}
out.close();
}
Now this does output fine, however, with regards to the "otherStates", i want to get this in a numeric order, and the best way I know is using Collections, however this is for arrays. I am unsure how to go about modifying the "otherStates" part of the code to cater for an array that concatanetates the string and then be able to order them accordingly. Any ideas
Hard to give a correct solution without input file data . Just try the below code. At the very least it should give you some ideas on how to solve the issue
public static void organiseFile() throws FileNotFoundException {
ArrayList<String> lines = new ArrayList<>();
ArrayList<String> order = new ArrayList<>();
String directory = "C:\\Users\\xxx\\Desktop\\Files\\ex1";
Scanner fileIn = new Scanner(new File(directory + "_ordered.txt"));
PrintWriter out = new PrintWriter(directory + "_orderesqsd.txt");
String otherStates = "";
ArrayList<String> otherStates_duplicate = new ArrayList<>();
String ordered_new_string.;
while (fileIn.hasNextLine() == true) {
lines.add(fileIn.nextLine());
System.out.println("Organising...");
}
Collections.sort(lines);
for (String output : lines) {
if (output.contains("[EVENT=agentStateEvent]")) {
out.println(output + "\n");
out.println(otherStates + "\n");
otherStates = "";
}
else {
otherStates += output+ "\n";
otherStates_duplicate.add(output);
}
Collections.sort(otherStates_duplicate); // Now this should have a sorted list
//if you need a string instead of an arraylist use code below in addition
for(String s:otherStates_duplicate){
ordered_new_string += s + "\n";
}
/*
I have not printed or stored the string ordered_new_string as it is not
clear to me what you want. print/write to a file and check
if ordered_new_string is what your required
*/
out.close();
}

Categories

Resources