I've got a program that will read from a file and add each line of the file as an element of an array. What I'm trying to do now though is to figure out how to edit certain items in the array.
The problem is my input file looks like this
number of array items
id, artist name, date, location
id, artist name, date, location
so for example
2
34, jon smith, 1990, Seattle
21, jane doe, 1945, Tampa
so if I call artArray[0] I get 34, jon smith, 1990, Seattle but I'm trying to figure out how to just update Seattle when the id of 34 is entered so maybe split each element in the array by comma's? or use a multidimensional array instead?
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class ArtworkManagement {
/**
* #param args
*/
public static void main(String[] args) {
String arraySize;
try {
String filename = "artwork.txt";
File file = new File(filename);
Scanner sc = new Scanner(file);
// gets the size of the array from the first line of the file, removes white space.
arraySize = sc.nextLine().trim();
int size = Integer.parseInt(arraySize); // converts String to Integer.
Object[] artArray = new Object[size]; // creates an array with the size set from the input file.
System.out.println("first line: " + size);
for (int i = 0; i < artArray.length; i++) {
String line = sc.nextLine().trim();
// line.split(",");
artArray[i] = line;
}
System.out.println(artArray[0]);
sc.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
You are almost there, but split returns an array, so you need an array of arrays.
You can change this line
Object[] artArray = new Object[size];
By this one, you also can use String instead of Object since this is indeed an string.
String[][] artArray = new Object[size][];
Then you can add the array to the array of arrays with
artArray[i] = line.split();
And finally access to it using two indexes:
artArray[indexOfTheArray][indexOfTheWord]
Also if you want to print the array use:
System.out.println(Arrays.toString(artArray[0]));
This behavior is explicitly documented in String.split(String regex) (emphasis mine):
This method works as if by invoking the two-argument split method with
the given expression and a limit argument of zero. Trailing empty
strings are therefore not included in the resulting array.
If you want those trailing empty strings included, you need to use String.split(String regex, int limit) with a negative value for the second parameter (limit):
String[] array = values.split(",", -1);
or
String[] array = values.split(",");
so
1. array[0] equals to id
2. array[1] equals to artist name
3. array[2] equals to date
4. array[3] equals to location
String[][] artArray = new String[size][];
System.out.println("first line: " + size);
for (int i = 0; i < artArray.length; i++) {
String line = sc.nextLine().trim();
artArray[i] = new String[line.split(",").length()];
artArray[i]=line.split(",");
}
I think you need to use a better data structure to store the file content so that you can process it easily later. Here's my recommendation:
List<String> headers = new ArrayList<>();
List<List<String>> data = new ArrayList<List<String>>();
List<String> lines = Files.lines(Paths.get(file)).collect(Collectors.toList());
//Store the header row in the headers list.
Arrays.stream(lines.stream().findFirst().get().split(",")).forEach(s -> headers.add(s));
//Store the remaining lines as words separated by comma
lines.stream().skip(1).forEach(s -> data.add(Arrays.asList(s.split(","))));
Now if you want to update the city (last column) in the first line (row), all you have to do is:
data.get(0).set(data.get(0) - 1, "Atlanta"); //Replace Seattle with Atlanta
Related
for instance
user is inputting
1 3
3 4
i want to capture them in array1[] and array2[]
I tried below
for(int index = 0; index < count ; index++){
while(!input.next().equals('\n')){
int n = input.nextInt();
if (n > 0 )
//save to two dimentional array 1st index is outer loop
}
}
A Two Dimensional (2D) Array in Java is basically an Array of Arrays. This means that each array within that 2D Array can each be of different lengths if so desired. This can obviously be very handy for many different situations.
Your question appears to be in regards to only two specific lines consisting of only two numerical values in each entered line but the demo runnable code below demonstrates how you can allow the User to create a 2D int[][] array of any size. That would of course be a 2D int[][] array consisting of any number of Rows with each row consisting of any number of Columns.
As you know, arrays contain a fixed size and can not grow dynamically unless you create a new array to replace the old one. The code below solves this problem by using two ArrayList objects which can grow dynamically, one of int[] (ArrayList<int[]>) and another of Integer (ArrayList<Integer>) then converting those ArrayList once all the data has been collected from the User.
Read the comments in code for additional information:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
public class CreateATwoDimensionalINTArrayDemo {
public static void main(String[] args) {
// Scanner object to open stream for Keyboard Input
Scanner userInput = new Scanner(System.in);
// Declare the desired 2D Array to create...
int[][] numbers2DArray;
/* An ArrayList of int[] arrays. Used so that our
2D Array rows of int[] arrays can 'dynamically'
grow as needed. */
ArrayList<int[]> tmp2DArray = new ArrayList<>();
/* Display what is required by the User to input
via the keyboard to the Console Window. Pasting
each entry into each entry prompt can be done
as well if desired. */
System.out.println("You are required to enter lines of numbers where each\n"
+ "number in a line is separated with at least one space.\n"
+ "You can enter as many numbers as you like on each line.\n"
+ "Enter nothing to stop entry and display the 2D Array\n"
+ "you have created:\n");
int lineCounter = 1; // Just used for line entry prompt count.
String line = ""; // Used to hold each each entry by the User.
// Loop used to contiuously recieve numerical line entries from the User.
while (line.isEmpty()) {
// Get the numerical line from User...
System.out.print("Enter line #" + lineCounter + ": --> ");
// Increment the entry prompt count (by one).
lineCounter++;
/* Get User input. Code flow stops here until the
User hits the ENTER key within the Console Window. */
line = userInput.nextLine().trim();
/* If nothing is entered except the ENTER key
then exit this 'while' loop (quit). */
if (line.isEmpty()) {
System.out.println("< End Of Entery! >");
System.out.println();
break;
}
/* Split the values entered in current entry
line into a String[] Array: */
String[] lineElements = line.split("\\s+");
/* ENTRY VALIDATION for the above lineElements[] String Array!
Only keep VALID value elements (elements that are proper Integer
of 'int' type numerical values) from the current User entered
data line. We don't want to deal elements that do not contain all
numerical digits (typo type entry values). */
/* An ArrayList used to 'dynamically' create our inner int[] arrays.
Ultimately, these will be the columnar values for the Rows of our
2D Array. */
ArrayList<Integer> tmpList = new ArrayList<>();
/* Iterate through the lineElemnts[] String array in order to
carry out validation on each array element and to convert
each element into an integer (int) value. */
for (int i = 0; i < lineElements.length; i++) {
/* Make sure there are no commas in the supplied
numerical element (ex: 2,436). Some people have
a habbit of doing this. */
lineElements[i] = lineElements[i].replace(",", "");
/* Is the supplied numerical element indeed a
signed or unsigned INTEGER numerical value? */
if (lineElements[i].matches("-?\\d+")) {
/* Yes it is so parse the string numerical element into
an Long data type Integer so as to ensure it will meet
the required 'int' data type MAX_VALUE and MIN_VALUE
threshold. */
long tmpLong = Long.parseLong(lineElements[i]);
if (tmpLong >= Integer.MIN_VALUE && tmpLong <= Integer.MAX_VALUE) {
/* Meets 'int' type numerical criteria so Cast the value
in tmpLong to 'int' and add to the tmpList ArrayList. */
tmpList.add((int)tmpLong);
}
}
}
//Convert the tmpList Integer ArrayList to an int[] Array
int[] arr = new int[tmpList.size()];
for (int k = 0; k < tmpList.size() ; k++) {
arr[k] = tmpList.get(k);
}
/* Add the int[] array to the tmp2DArray ArrayList. */
tmp2DArray.add(arr);
/* Clear the User line entry so as not to meet
the 'while' loop condition and the User can
enter another line. */
line = "";
}
// ------------------ END OF WHILE LOOP ---------------------
/* Convert the tmp2DArray<int[]> ArrayList to a
the numbers2DArray[][] 2D Array... */
numbers2DArray = new int[tmp2DArray.size()][];
for (int i = 0; i < tmp2DArray.size(); i++) {
numbers2DArray[i] = tmp2DArray.get(i);
}
// Display the 2D Array (if there is something in it to display)...
System.out.println("===================================");
System.out.println("Your 2D Array (numbers2DArray[][]):");
System.out.println("-----------------------------------");
if (numbers2DArray.length == 0) {
System.out.println("- Nothing in 2D Array to display! -");
}
else {
for (int i = 0; i < numbers2DArray.length; i++) {
System.out.println("Array #" + (i+1) + ": --> " + Arrays.toString(numbers2DArray[i]));
}
}
System.out.println("===================================");
}
}
Play with it for a little while.
Note how the numbers2DArray 2D Array is initialized
numbers2DArray = new int[tmp2DArray.size()][];
See how the second dimension doesn't receive a length value. This leaves things open for internal arrays of any length.
About the Regular Expressions used within the code as arguments for both the String#split() and String#matches() methods:
Expression: "\\s+"
Used as an argument for the String#split() method:
String[] lineElements = line.split("\\s+");
Split the string contained with the String variable line on every one (or more_ white-space (\\s+) into a String Array named lineElements.
Expression: "-?\\\\d+"
Used as an argument for the String#matches() method:
if (lineElements[i].matches("-?\\d+")) {
If the string element held in the lineElements String Array at index i optionally contains the negative or minus (-) character (the ? makes the - optional) followed by a string representation of an integer value of 1 or more digits (\\d+) then carry out the code within that if code block.
Say you have a text file with "abcdefghijklmnop" and you have to add 3 characters at a time to an array list of type string. So the first cell of the array list would have "abc", the second would have "def" and so on until all the characters are inputted.
public ArrayList<String> returnArray()throws FileNotFoundException
{
int i = 0
private ArrayList<String> list = new ArrayList<String>();
Scanner scanCharacters = new Scanner(file);
while (scanCharacters.hasNext())
{
list.add(scanCharacters.next().substring(i,i+3);
i+= 3;
}
scanCharacters.close();
return characters;
}
Please use the below code,
ArrayList<String> list = new ArrayList<String>();
int i = 0;
int x = 0;
Scanner scanCharacters = new Scanner(file);
scanCharacters.useDelimiter(System.getProperty("line.separator"));
String finalString = "";
while (scanCharacters.hasNext()) {
String[] tokens = scanCharacters.next().split("\t");
for (String str : tokens) {
finalString = StringUtils.deleteWhitespace(str);
for (i = 0; i < finalString.length(); i = i + 3) {
x = i + 3;
if (x < finalString.length()) {
list.add(finalString.substring(i, i + 3));
} else {
list.add(finalString.substring(i, finalString.length()));
}
}
}
}
System.out.println("list" + list);
Here i have used StringUtils.deleteWhitespace(str) of Apache String Utils to delete the blank space from the file tokens.and the if condition inside for loop to check the substring for three char is available in the string if its not then whatever character are left it will go to the list.My text file contains the below strings
asdfcshgfser ajsnsdxs in first line and in second line
sasdsd fghfdgfd
after executing the program result are as,
list[asd, fcs, hgf, ser, ajs, nsd, xs, sas, dsd, fgh, fdg, fd]
public ArrayList<String> returnArray()throws FileNotFoundException
{
private ArrayList<String> list = new ArrayList<String>();
Scanner scanCharacters = new Scanner(file);
String temp = "";
while (scanCharacters.hasNext())
{
temp+=scanCharacters.next();
}
while(temp.length() > 2){
list.add(temp.substring(0,3));
temp = temp.substring(3);
}
if(temp.length()>0){
list.add(temp);
}
scanCharacters.close();
return list;
}
In this example I read in all of the data from the file, and then parse it in groups of three. Scanner can never backtrack so using next will leave out some of the data the way you're using it. You are going to get groups of words (which are separated by spaces, Java's default delimiter) and then sub-stringing the first 3 letters off.
IE:
ALEXCY WOWZAMAN
Would give you:
ALE and WOW
The way my example works is it gets all of the letters in one string and continuously sub strings off letters of three until there are no more, and finally, it adds the remainders. Like the others have said, it would be good to read up on a different data parser such as BufferedReader. In addition, I suggest you research substrings and Scanner if you want to continue to use your current method.
My question is -
how to convert a String ArrayList to an Integer ArrayList?
I have numbers with ° behind them EX: 352°. If I put those into an Integer ArrayList, it won't recognize the numbers. To solve this, I put them into a String ArrayList and then they are recognized.
I want to convert that String Arraylist back to an Integer Arraylist. So how would I achieve that?
This is my code I have so far. I want to convert ArrayString to an Int Arraylist.
// Read text in txt file.
Scanner ReadFile = new Scanner(new File("F:\\test.txt"));
// Creates an arraylist named ArrayString
ArrayList<String> ArrayString = new ArrayList<String>();
// This will add the text of the txt file to the arraylist.
while (ReadFile.hasNextLine()) {
ArrayString.add(ReadFile.nextLine());
}
ReadFile.close();
// Displays the arraystring.
System.out.println(ArrayString);
Thanks in advance
Diego
PS: Sorry if I am not completely clear, but English isn't my main language. Also I am pretty new to Java.
You can replace any character you want to ignore (in this case °) using String.replaceAll:
"somestring°".replaceAll("°",""); // gives "sometring"
Or you could remove the last character using String.substring:
"somestring°".substring(0, "somestring".length() - 1); // gives "somestring"
One of those should work for your case.
Now all that's left is to parse the input on-the-fly using Integer.parseInt:
ArrayList<Integer> arrayInts = new ArrayList<Integer>();
while (ReadFile.hasNextLine()) {
String input = ReadFile.nextLine();
try {
// try and parse a number from the input. Removes trailing `°`
arrayInts.add(Integer.parseInt(input.replaceAll("°","")));
} catch (NumberFormatException nfe){
System.err.println("'" + input + "' is not a number!");
}
}
You can add your own handling to the case where the input is not an actual number.
For a more lenient parsing process, you might consider using a regular expression.
Note: The following code is using Java 7 features (try-with-resources and diamond operator) to simplify the code while illustrating good coding practices (closing the Scanner). It also uses common naming convention of variables starting with lower-case, but you may of course use any convention you want).
This code is using an inline string instead of a file for two reasons: It shows that data being processed, and it can run as-is for testing.
public static void main(String[] args) {
String testdata = "55°\r\n" +
"bad line with no number\r\n" +
"Two numbers: 123 $78\r\n";
ArrayList<Integer> arrayInt = new ArrayList<>();
try (Scanner readFile = new Scanner(testdata)) {
Pattern digitsPattern = Pattern.compile("(\\d+)");
while (readFile.hasNextLine()) {
Matcher m = digitsPattern.matcher(readFile.nextLine());
while (m.find())
arrayInt.add(Integer.valueOf(m.group(1)));
}
}
System.out.println(arrayInt);
}
This will print:
[55, 123, 78]
You would have to create a new instance of an ArrayList typed with the Integer wrapper class and give it the same size buffer as the String list:
List<Integer> myList = new ArrayList<>(ArrayString.size());
And then iterate through Arraystring assigning the values over from one to the other by using a parsing method in the wrapper class
for (int i = 0; i < ArrayString.size(); i++) {
myList.add(Integer.parseInt(ArrayString.get(i)));
}
I have a serious problem with extracting terms from each string line. To be more specific, I have one csv formatted file which is actually not csv format (it saves all terms into line[0] only)
So, here's just example string line among thousands of string lines;
test.csv
line1 : "31451 CID005319044 15939353 C8H14O3S2 beta-lipoic acid C1CS#S[C##H]1CCCCC(=O)O "
line2 : "12232 COD05374044 23439353 C924O3S2 saponin CCCC(=O)O "
line3 : "9048 CTD042032 23241 C3HO4O3S2 Berberine [C##H]1CCCCC(=O)O "
I want to extract "beta-lipoic acid" ,"saponin" and "Berberine" only which is located in 5th position.
You can see there are big spaces between terms, so that's why I said 5th position.
In this case, how can I extract terms located in 5th position for each line?
one more thing ;
the length of whitespace between each six terms is not always equal.
the length could be one,two,three or four..five... something like that..
Another try:
import java.io.File;
import java.util.Scanner;
public class HelloWorld {
// The amount of columns per row, where each column is seperated by an arbitrary number
// of spaces or tabs
final static int COLS = 7;
public static void main(String[] args) {
System.out.println("Tokens:");
try (Scanner scanner = new Scanner(new File("input.txt")).useDelimiter("\\s+")) {
// Counten the current column-id
int n = 0;
String tmp = "";
StringBuilder item = new StringBuilder();
// Operating of a stream
while (scanner.hasNext()) {
tmp = scanner.next();
n += 1;
// If we have reached the fifth column, take its content and append the
// sixth column too, as the name we want consists of space-separated
// expressions. Feel free to customize of your name-layout varies.
if (n % COLS == 5) {
item.setLength(0);
item.append(tmp);
item.append(" ");
item.append(scanner.next());
n += 1;
System.out.println(item.toString()); // Doing some stuff with that
//expression we got
}
}
}
catch(java.io.IOException e){
System.out.println(e.getMessage());
}
}
}
if your line[]'s type is String
String s = line[0];
String[] split = s.split(" ");
return split[4]; //which is the fifth item
For the delimiter, if you want to go more precisely, you can use regular expression.
How is the column separated? For example, if the columns are separated by tab character, I believe you can use the split method. Try using the below:
String[] parts = str.split("\\t");
Your expected result will be in parts[4].
Just use String.split() using a regex for at least 2 whitespace characters:
String foo = "31451 CID005319044 15939353 C8H14O3S2 beta-lipoic acid C1CS#S[C##H]1CCCCC(=O)O";
String[] bar = foo.split("\\s\\s");
bar[4]; // beta-lipoic acid
I am getting an error when trying to use a JFileChooser to scan a text file add it to an array and parse one of the strings to a double and two to integers. Does it have to do with the fact that the addEmployee method adds the six parameters to an arrayList? Here is the code...
else if (e.getSource()==readButton){
JFileChooser fileChooser = new JFileChooser("src");
if (fileChooser.showOpenDialog(null)==JFileChooser.APPROVE_OPTION)
{
empFile=fileChooser.getSelectedFile();
}
Scanner scan = new Scanner("empFile");
while(scan.hasNext()){
String[] rowData = scan.next().split(":");
if(rowData.length == 5){
rowData[4] = null;
fName = rowData[0];
lName = rowData[1];
position2 = rowData[2];
firstParam = Double.parseDouble(rowData[3]);
secondParam = Integer.parseInt(rowData[4]);
empNum = Integer.parseInt(rowData[5]);
}
else{
fName = rowData[0];
lName = rowData[1];
position2 = rowData[2];
firstParam = Double.parseDouble(rowData[3]);
secondParam = Integer.parseInt(rowData[4]);
empNum = Integer.parseInt(rowData[5]);
}
if (position2.equals("Manager")){
c.addEmployee(fName, lName, position2, firstParam, 0, empNum);
}
else if(position2.equals("Sales")){
c.addEmployee(fName, lName, position2, firstParam, 0, empNum);
}
else{
c.addEmployee(fName, lName, position2, firstParam, secondParam, empNum);
}
}
}
John:Smith:Manufacturing:6.75:120:444
Betty:White:Manager:1200.00:111
Stan:Slimy:Sales:10000.00:332
Betty:Boop:Design:12.50:50:244
You are trying to fetch empNum = Integer.parseInt(rowData[5]);
row data only having size 5 that means index 0-4, Thats why ArrayIndexOutOfBoundsException is getting
So Initialize String[] rowData = new String[6];
String[] rowData = new String[5]; // edited out of original post
rowData = scan.next().split(":");
The first statement allocates an array of 5 Strings and sets them all to null. The second statement just throws away the array you just allocated. The result of split will return an array of however many items it finds, and then you assign rowData, which is a reference to an array, to a reference to the new array. The old one gets garbage collected. So there's no guarantee that rowData will have 5 elements after this assignment.
You'll have to decide what you want to do if the split doesn't return enough array elements. You could use something like Arrays.copyOf that could put the split result into some of the rowData elements while leaving the rest alone, but then the unassigned elements will still be null, and you'll just get a NullPointerException a few lines later. So you have some design decisions to make here.
More: You may want to consider using the Scanner method nextLine() instead of next(). next() will return just one token, which means it will stop at a space character, which means you will have problems if someone is named "Mary Beth" or something like that.