I'm trying to remove an item from an Text file using an arrayList. The ArrayList get's its values from the Text File, and then it displays it in a ListView.
I have a contextual menu that pops up, and gives me an option to remove the item from the list.
In the text file, all the items are on a new line.
How will I go about removing specific items from the file? The ArrayList will clear it's self, and pull the data into the ArrayList when ever the action has been performed, so that is sorted.
Code to remove item from array:
int id = info.position;
for(int i = array.size()-1; i >=0; i--){
array.remove(id);
}
File != ArrayList, ArrayList don't know anything about File and File don't know anything about ArrayList.
A way to do what you want is to rewrite again the data inside the file when you need it (when you delete an item from an ArrayList, call a method which updates the TextFile)
You should call it before ArrayList clear (or you will lose every value!)
An example:
List<String> values = new ArrayList<String>();
values.add("A");
values.add("B");
values.add("C");
values.add("D");
values.add("E");
values.add("D");
BufferedWriter fileWriter = null;
try
{
fileWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("fileName.txt")));
for (String value : values)
{
fileWriter.write(value + System.getProperty("line.separator"));
}
}
finally
{
if (fileWriter != null)
fileWriter.close();
}
I think it's a safe way to do this without depend much to the fact that the file is not changed by another source (in any way)
If each item in the ArrayList is equivalent to each line in the file, then just keep track of the index of the position of deleted item in the ArrayList. Then rewrite the entire file except that tracked index (which should be that same line).
Basically, once you delete the item from you ArrayList, then just write over the file as you loop through your updated ArrayList.
Related
I use while loop to read a text file and create new arraylists out of portions of the text file and then place those arraylists inside another arraylist. My problem is that I don't know how to add my temporary arraylist parse into the mainAList and then clear it for the next loop without affecting all the parse arraylists inside the arraylist<arraylist> mainAList. More info inside the comments below in the code.
This is a sample code, it is from larger file. It is shortened but has all the moving parts
ArrayList<ArrayList<String>> mainAList = new ArrayList<ArrayList<String>>();
ArrayList<String> parse = new ArrayList<>();
try (Scanner filereader = new Scanner(Paths.get("name_of_file.txt"))) {
while (filereader.hasNextLine()) {
parse.add(filereader.nextLine());
if (parse.get(parse.size()-1).length() == 0 || !filereader.hasNextLine()) {
// if the file reader detects empty line or has no more lines
// the arraylist called parse gets added to the mainAList
mainAList.add(parse);
}
parse.clear();
// here is my problem. How do I clear parse so for the next patch of lines
// so I don't add the same things + more into the next slot of mainAList
// every time the loop runs?
// I understand my issue is not how to correctly clear the parse but
// how to add the arraylists correctly into the mainAList so I can alter them individually
}
}
The file that is read is like this:
a
b
c
d
f
g
h
i
j
k
l
etc..
There are two problems with your current approach:
parse will use the same reference for all inner ArrayLists, so when you call parse.clear() it will empty all inner lists of your mainAList. This can be solved by creating a copy of the parse list when you add it (i.e. mainAList.add(new ArrayList<>(parse));)
You want to clear the list inside the if as well, after you've added the copy to your mainAList.
In addition, I assume you don't want the empty lines added to the individual inner Lists, so you could read the line first, and either add the entire list to mainAList and clear parse inside the if-statement, or add the line to the parse-list.
A slightly better alternative, is to just create a new list instead, so you won't need the clear and creating a copy of the list.
In total:
ArrayList<ArrayList<String>> mainAList = new ArrayList<ArrayList<String>>();
ArrayList<String> parse = new ArrayList<>();
try (Scanner filereader = new Scanner(System.in)) {
while (filereader.hasNextLine()) {
String line = filereader.nextLine();
if (line.length() == 0 || !filereader.hasNextLine()) {
// if the file reader detects empty line or has no more lines
// the arraylist called parse gets added to the mainAList
mainAList.add(parse);
// and then a new parse-list is created for the next group of inputs:
parse = new ArrayList<>();
} else{
parse.add(line);
}
}
}
Try it online.
Try this instead of clearing the list everytime.
ArrayList<ArrayList<String>> mainAList = new ArrayList<ArrayList<String>>();
try (Scanner filereader = new Scanner(Paths.get("name_of_file.txt"))) {
while (filereader.hasNextLine()) {
ArrayList<String> parse = new ArrayList<>();
parse.add(filereader.nextLine());
if (parse.get(parse.size()-1).length() == 0 || !filereader.hasNextLine()) {
mainAList.add(parse);
}
}
}
Your problem is that your mainAList will be empty in the end because objects are reference types. In order to fix that problem, you have to add a copy of parse to the mainAList and not the parse arraylist itself
replace this line
mainAList.add(parse);
with this
mainAList.add(new ArrayList<>(parse));
I have a JTable with three columns, each of which is filled with an array made from an ArrayList. I am trying to make a search system, where the user will search for a value in the first column, and the rows of the JTable will filter out, so that only the rows that contain the specified String from the search box show up on the table after a button is pressed. On another table, this worked by filtering the ArrayList used using this loop:
String s = searchBar.getText();
ArrayList<String> fn = new ArrayList<>();
fn.addAll(names); //names is the arraylist that contains all the values that will be filtered
for(Iterator<String> it = fn.iterator(); it.hasNext(); ) {
if (!it.next().contains(s)) {
it.remove();
}
This code works to filter out the array, but what I am trying to do is filter 3 ArrayLists based on only if one of the ArrayLists does not contain the s String.
I tried doing this:
String s = searchBar.getText();
ArrayList<String> fn = new ArrayList<>();
ArrayList<String> fp = new ArrayList<>();
fn.addAll(names); //names is the arraylist that contains all the values that will be filtered
fp.addAll(numbers)//one of the other arraylists that I want to filter
for(Iterator<String> it = fn.iterator(), itp = fp.iterator(); it.hasNext() && itp.hasNext(); ) {
if (!it.next().contains(s)) {
itp.remove();
it.remove();
}
When I run this code I get a Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException on the line where I write "itp.remove();".
Is there a way I can remove from both the arrays based on only one of them?
I'm happy that you fix your exception. Anyway, when I said about back iteration I meant something like that
Firstly, Some of check like
if(fn.size()==fp.size()){
// and after that go to delete.
for (int i=fn.size(); i>0;i--) {
if (fn.contains(s)) {
fn.remove(i);
fp.remove(i);
} }}
Anyway, your and my method isn't good for multithreading, because ArrayList doesnt't concurrent object also it's remove method
So I managed to fix it by using the remove method from the ArrayList instead of the remove method from the Iterator. I know this isn't the recommended way of doing it, but it seems to not have brought any negatives with it, so I will keep it for now.
The code I used is:
int i = 0;
for (Iterator<String> it = fn.iterator(); it.hasNext(); i++) {
if (!it.next().contains(s)) {
it.remove(); //Iterator's remove
fp.remove(i);// ArrayList's remove which avoids the error
}
}
Thank you to all who helped
I have an ArrayList<List<String>> that I'm trying to iterate through and print, however, I keep getting a ConcurrentModificationException.
My ArrayList<List<String>> represents lines of text, where each inner list is a line of a book and contains the strings that make up that line. I want to print the book out line by line. Here's the code that's causing the error:
public void print(ArrayList<List<String>> book) {
if (book == null) {
return;
}
for (List<String> lst : book) {
StringBuilder line = new StringBuilder();
for (String s : lst) {
line.append(s + " ");
}
// delete the extra space at the end
line.deleteCharAt(line.length() - 1);
// print out the line
System.out.println(line.toString());
}
// print out an extra newline to get ready for next input
System.out.println();
}
Note: This print function takes as input the book, which is the output of another function. This other function is only used to parse the text file and put the words in the ArrayList<List<String>> format.
A concurrent modification exception is raised when a list modification is done while at the same time iterating through the list.
Above you are just iterating through the list, but at the same time elsewhere someone alters the list.
Maybe a CopyOnWriteArrayList might be interesting. But several solutions are imaginable depending on your code.
Here is your error :
you cannot edit a reference holds by an arraylist inside your for loop
String s = line;
// delete the extra space at the end
s.deleteCharAt(s.length() - 1);
Line is a string from your lst and Since strings are immutable it would be more suitable to declare a new String
I am reading from a text file and saving the lines into an ArrayList. But I have had no success in how to go through and read all of the specific characters in the ArrayList, how many columns and rows there are.
This is the code I have written so far:
String line;
BufferedReader br = new BufferedReader(r);
ArrayList<String> myArrayList = new ArrayList<String>();
while ((line = br.readLine()) != null)
{
myArrayList.add(line);
.........
}
If I am reading your post right you are wanting to further break apart your lines (your reference to columns). Since you are storing String objects you will need to further break apart those entries into another List to truly parse through your words and characters appropriately.
Java used to have something called the StringTokenizer which could do what you want but that is now deprecated and replaced by the String.Split() method. By iterating through your ArrayList and splitting the String Object by specific delimiters (such as a space or a period), you should be able to further breakdown your existing ArrayList and create a new List with individual words, or even characters.
I do not know why you use "store.add(line)". You should use myArrayList instead of this.
After you have stored everything in the ArrayList you can use a for-each loop to traverse through the list:
for (String string : myArrayList) {
// do everything with the strings here
}
You aren't calling the List myArrayList, I think you want to change this
ArrayList<String> myArrayList = new ArrayList<String>();
to (using the diamond operator and the interface type) -
List<String> store = new ArrayList<>(); // <-- match the name.
You can count the "rows" by getting the size of the List -
int rows = store.size();
To count "columns" you would need to iterate the List and examine the lines. (or you could do that while you read the input) -
for (String line : store) {
// count columns in line
}
If you want to go through a ArrayList there are many ways that you can try
You can easily get number of elements in the ArrayList using size() method.
e.g.
//traditional way
for(int i = 0; i< arrayList.size(); i++){
System.out.println(arrayList.get(i));
}
//enhanced forloop
if your ArrayList is String type
for(String row : arrayList)
System.out.println(row);
With Java 8 you cane have more easier iterator that can use to go through the ArrayList
Edited
If you wanna read character by character
for(String row : arrayList){
char []letters = row/toCharArray();
for(char character : letters)
System.out.print(character + " ") ;
}
I am creating an android application, and I created a list of available files in the internal memory with this instruction:
final String[] files =fileList();
I need to remove a file from this list and I don't know how, can you help me?
To "remove" something you can just set it back to null, or you can do it the hard way with a loop that shifts everything behind it up a place.
public void remove( int index ) {
for(int i=index; i<sarr.length()-1; i++) {
sarr[i] = sarr[i+1]
}
sarr[sarr.length()-1] = null;
System.out.println("Removed!");
}
When using primitive arrays like this, there is no removal method. If you built a more complex datatype you could have the "remove" method available to you.
Use a List<String> instead. That way you can remove the file that you want using the remove() method.
index = 0//location of item to be removed, with the first item in the list at 0
List<String> files = Arrays.asList(getFiles());
files.remove(index)
in this example, index is the location of the item that you want to remove. Alternatively, you could do this instead
item = "fileLocation";
List<String> files = Arrays.asList(getFiles());
files.remove(item)