2013-03-08 2 views
3

Я создаю библиотечную системную программу в java без базы данных (напрямую с файлом).Jtable Row delete

У меня возникла странная проблема с удалением строки в моей jtable (которая также удаляется из файла).

Иногда, когда я выбираю строку в своей таблице и нажимаю кнопку «Удалить», больше одной строки удалено!

также в большинстве случаев он работает правильно !!

Мой код:

public final class UserPage extends JFrame implements ActionListener { 

    private AllUser userModel; 
    private JTable uTable; 
    JButton deleteUser; 
    int selectedRow; 

    public UserPage() { 
     titleUserCount(); 
     userModel = new AllUser(); 
     uTable = new JTable(userModel); 
     add(new JScrollPane(uTable), BorderLayout.CENTER); 
     add(buttonPanels(), BorderLayout.PAGE_START); 
     this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     this.setSize(800, 600); 
     this.setLocation(300, 60); 
     this.setResizable(false); 
    } 

    public final JPanel buttonPanels() { 
     JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); 
     deleteUser = new JButton("Delete User"); 

     deleteUser.addActionListener(this); 
     buttonsPanel.add(deleteUser); 

     return buttonsPanel; 
    } 

    public void titleUserCount() { 
     AllUser userCount = new AllUser(); 
     UserPage.this.setTitle("All User Information , Number Of user is : " + userCount.getRowCount()); 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     if (e.getSource() == deleteUser) { 
      int selectedrow = uTable.getSelectedRow(); 
      if (selectedrow >= 0) { 
       userModel.RemoveRow(selectedrow); 
       titleUserCount(); 
      } else { 
       JOptionPane.showMessageDialog(null, "No Row Selected"); 
      } 
     } 
    } 
} 

Моя модель класса: информация

public class AllUser extends AbstractTableModel { 

    UserInformation uiS = new UserInformation(); 
    String[] col = {"ID", "Fname", "Lname", "Gender", "Date"}; 
    ArrayList<UserInformation> Udata = new ArrayList<UserInformation>(); 

    public AllUser() { 
     BufferedReader br = null; 
     try { 
      FileReader fr = new FileReader("AllUserRecords.txt"); 
      br = new BufferedReader(fr); 
      String line; 
      while ((line = br.readLine()) != null) { 
       if (line.trim().length() == 0) { 
        continue; 
       } 
       Udata.add(initializeUserInfos(line)); 
      } 
     } catch (IOException e) { 
     } finally { 
      if (br != null) { 
       try { 
        br.close(); 
       } catch (IOException ioe) { 
       } 
      } 
     } 
    } 

    private UserInformation initializeUserInfos(String str) { 
     UserInformation Uinit = new UserInformation(); 
     String[] CellArray = str.split("  "); 
     Uinit.setID(CellArray[0]); 
     Uinit.setFname(CellArray[1]); 
     Uinit.setLname(CellArray[2]); 
     Uinit.setGender(CellArray[3]); 
     Uinit.setDate(CellArray[4]); 
     return Uinit; 
    } 

    public void RemoveRow(int rowIndex) { 
     if (RemoveUserFromFile(rowIndex)) { 
      Udata.remove(rowIndex); 
      fireTableRowsDeleted(rowIndex, rowIndex); 
     } else { 
      JOptionPane.showMessageDialog(null, "Unable to delete"); 
     } 
    } 

    public boolean RemoveUserFromFile(int index) { 
     File Mf = new File("AllUserRecords.txt"); 
     File Tf = new File("Uoutput.txt"); 
     try { 
      BufferedReader Ubr = new BufferedReader(new FileReader(Mf)); 
      PrintWriter Upw = new PrintWriter(new FileWriter(Tf)); 
      String line; 
      while ((line = Ubr.readLine()) != null) { 
       if (line.trim().length() == 0) { 
        continue; 
       } 
       if (!line.startsWith(String.valueOf(getValueAt(index, 0)))) { 
        Upw.println(line); 
       } 
      } 
      Upw.close(); 
      Ubr.close(); 
      Mf.delete(); 
      Tf.renameTo(Mf); 
      return true; 
     } catch (FileNotFoundException e1) { 
      return false; 
     } catch (IOException ioe) { 
      return false; 
     } 
    } 

    @Override 
    public String getColumnName(int colu) { 
     return col[colu]; 
    } 

    @Override 
    public int getRowCount() { 
     return Udata.size(); 
    } 

    @Override 
    public int getColumnCount() { 
     return col.length; 
    } 

    @Override 
    public Object getValueAt(int rowIndex, int columnIndex) { 
     UserInformation uinfoS = Udata.get(rowIndex); 
     Object value = null; 
     switch (columnIndex) { 
      case 0: 
       value = uinfoS.getID(); 
       break; 
      case 1: 
       value = uinfoS.getFname(); 
       break; 
      case 2: 
       value = uinfoS.getLname(); 
       break; 
      case 3: 
       value = uinfoS.getGender(); 
       break; 
      case 4: 
       value = uinfoS.getDate(); 
       break; 
      default: 
       value = "..."; 
     } 
     return value; 
    } 

    @Override 
    public void setValueAt(Object value, int rowIndex, int columnIndex) { 
     UserInformation userInfo = Udata.get(rowIndex); 

     switch (columnIndex) { 

      case 0: 
       userInfo.setID((String) value); 
       break; 
      case 1: 
       userInfo.setFname((String) value); 
       break; 
      case 2: 
       userInfo.setLname((String) value); 
       break; 
      case 3: 
       userInfo.setGender((String) value); 
       break; 
      case 4: 
       userInfo.setDate((String) value); 
       break; 
     } 
    } 
} 

пользователя Класс:

public class UserInformation { 

    private String Fname; 
    private String Lname; 
    private String ID; 
    private String Gender; 
    private String Date; 

    public String getFname() { 
     return Fname; 
    } 

    public void setFname(String fname) { 
     this.Fname = fname; 
    } 

    public String getLname() { 
     return Lname; 
    } 

    public void setLname(String lname) { 
     this.Lname = lname; 
    } 

    public String getID() { 
     return ID; 
    } 

    public void setID(String i_d) { 
     this.ID = i_d; 
    } 

    public String getGender() { 
     return Gender; 
    } 

    public void setGender(String gndr) { 
     this.Gender = gndr; 
    } 

    public String getDate() { 
     return Date; 
    } 

    public void setDate(String date) { 
     this.Date = date; 
    } 

    @Override 
    public String toString() { 
     return ID + "  " + Fname + "  " 
       + Lname + "  " + Gender + "  " + Date + "\n"; 
    } 
} 

Мой текст Файл:

85  lo  ii  Female  2013/03/08 
86  jkj  nmn  Female  2013/03/08 
52  tyr  fgfg  Female  2013/03/08 
7  dfdf  wew  Female  2013/03/08 
47  zczc  asa  Female  2013/03/08 
16  erw  www  Male  2013/03/08 
83  gfg  dsd  Male  2013/03/08 
+3

Пожалуйста, изучите соглашения о присвоении имен java и придерживайтесь их. – kleopatra

+0

Покажите свой полный код .. введите код для 'UserInformation'? –

+0

Не могли бы вы пояснить: «Иногда, когда я выбираю строку в моей таблице ... больше, что одна строка удалена»? Можете ли вы воспроизвести «иногда» событие? Являются ли несколько записей потерянными в вашем файле, или только JTable (т. Е. Ваш файл правильный и только ваше представление ошибочно или несколько записей удаляются в обоих)? – SeKa

ответ

4

Ну, так как я не имею свой весь код, поэтому я исхожу с фиктивной программой для удаления записи из JTable, а также соответствующий файл. Смотрите метод removeRow, определенный в классе MyTabeModel. Он также охватывает риск, если данные не могут быть записаны на file (records.temp) после удаления record с ArrayList.

import javax.swing.table.*; 
import java.awt.event.*; 
import java.awt.*; 
import javax.swing.*; 
import java.util.*; 
import java.io.*; 
public class TableFocus extends JFrame 
{ 
    MyTableModel model1; 
    JTable table1; 
    public void createAndShowGUI() 
    { 
     setTitle("JTables"); 
     Container c = getContentPane(); 
     model1 = new MyTableModel(); 
     table1 = new JTable(model1); 
     table1.setColumnSelectionAllowed(false); 
     table1.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 
     JScrollPane jsTable1 = new JScrollPane(table1); 
     c.add(jsTable1); 
     JButton button = new JButton("Delete"); 
     button.addActionListener(new ActionListener() 
     { 
      public void actionPerformed(ActionEvent evt) 
      { 
       if (model1.getRowCount() > 0 && table1.getSelectedRow() != -1) 
       { 
        model1.deleteRow(table1.getSelectedRow()); 
       } 
      } 
     }); 
     add(button,BorderLayout.SOUTH); 
     setSize(500,300); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setVisible(true); 
    } 
    private class MyTableModel extends AbstractTableModel 
    { 
     String columns[] ; 
     ArrayList<ArrayList<String>> data; 
     public MyTableModel() 
     { 
      columns = new String[] {"Roll No.","Name"}; 
      prepareData(); 
     } 
     private void prepareData() 
     { 
      data = new ArrayList<ArrayList<String>>(); 
      data.add(new ArrayList<String>(){{add("1");add("Michael");}}); 
      data.add(new ArrayList<String>(){{add("2");add("Derake");}}); 
      data.add(new ArrayList<String>(){{add("3");add("Archie");}}); 
     } 
     @Override 
     public String getColumnName(int columnIndex) 
     { 
      return columns[columnIndex]; 
     } 
     @Override 
     public int getRowCount() 
     { 
      return data.size(); 
     } 
     @Override 
     public int getColumnCount() 
     { 
      return columns.length; 
     } 
     @Override 
     public Object getValueAt(int row, int col) 
     { 
      return data.get(row).get(col); 
     } 
     @Override 
     public void setValueAt(Object aValue, int rowIndex, int colIndex) 
     { 
      data.get(rowIndex).set(colIndex,(String)aValue); 
      fireTableCellUpdated(rowIndex,colIndex); 
     } 
     @Override 
     public boolean isCellEditable(int row, int col) 
     { 
      return false; 
     } 
     public void deleteRow(int row) 
     { 
      ArrayList<String> temp = data.get(row);//backup of value in case of IOException while writing to file 
      BufferedWriter bfr = null; 
      try 
      { 
       data.remove(row); 
       //Write here the logic for repopulating file with new records. 
       bfr = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("records.temp"))); 
       StringBuffer sBuffer = new StringBuffer(); 
       for (ArrayList<String> list : data) 
       { 
        StringBuffer buf = new StringBuffer(); 
        for (String val : list) 
        { 
         buf.append(val+"\t"); 
        } 
        buf.replace(buf.length() - 1, buf.length(),"\n"); 
        sBuffer.append(buf.toString()); 
       } 
       bfr.write(sBuffer.toString()); 
       bfr.flush(); 
       bfr.close(); 
       fireTableRowsDeleted(row,row); 
      } 
      catch (Exception ex) 
      { 
       data.add(row,temp);//Rollback the delete from ArrayList 
       ex.printStackTrace(); 
      } 
      finally 
      { 
       if (bfr != null) 
       { 
        try 
        { 
         bfr.close(); 
        } 
        catch (Exception ex){} 
       } 
      } 

     } 
    } 
    public static void main(String[] args) 
    { 
     SwingUtilities.invokeLater(new Runnable() 
     { 
      @Override 
      public void run() 
      { 
       TableFocus ths = new TableFocus(); 
       ths.createAndShowGUI(); 
      } 
     }); 
    } 
} 

UPDATE

Иногда, когда я выбрать строку в моей таблице и нажмите кнопку, чтобы удалить более , что одна строка была удалена!

Ну, пройдя свой код, я узнал об этом случае, когда удалено более одной строки.Корпус:Если в вашем файле имеется более одной строки, начиная с той же user ID записи, которую вы хотите удалить.
Для примера предположит, что вы имеете такую ​​запись в файле:

85  lo  ii  Female  2013/03/08 
86  jkj  nmn  Female  2013/03/08 
52  tyr  fgfg  Female  2013/03/08 
86  jkj  pqr  Male  2013/03/08 
7  dfdf  wew  Female  2013/03/08 
47  zczc  asa  Female  2013/03/08 
16  erw  www  Male  2013/03/08 
83  gfg  dsd  Male  2013/03/08 

Здесь идентификатор пользователь 86 содержится в два ряде (row 2 и row 4) .Когда вы выбираете 4th строку в вашем JTable, чтобы удалить эту конкретную запись , Он удаляет 2nd, а также строку 4th из вашего Файла. Но в JTable строка 2nd будет отображаться, потому что она не обновляется с новыми File до сих пор. Как только вы обновите свой JTable новым файлом, он отобразит обе строки, удаленные оттуда.
Чтобы узнать, почему это происходит, посмотрите на свой RemoveUserFromFile(int index) метод while loop который выглядит следующим образом:

while ((line = Ubr.readLine()) != null) //Reads the file till the end. 
{ 
    if (line.trim().length() == 0) { 
    continue; 
    } 
    if (!line.startsWith(String.valueOf(getValueAt(index, 0)))) //If line starts with 86 don't write it to new `Uoutput.txt`. so all lines starting with 86 will be ignored. 
    { 
    Upw.println(line);//Lines starting with 86 is not written. 
    } 
} 

Я надеюсь, что теперь вы получили твердую причину, почему иногда удаление записи из JTable удаляет два или более чем две линии от вашего file.
Обходной к этой проблеме, чтобы изменить свои методы (RemoveRow и RemoveUserFromFile) следующим способ :(использовать этот Измененный код)

public void RemoveRow(int rowIndex) { 
    UserInformation temp = Udata.get(rowIndex);//Keep it as back up so that you could reconsolidate it to ArrayList in case RemoveUserFromFile return false 
    Udata.remove(rowIndex);//remove the element from Udata on temporary basis. 
    if (RemoveUserFromFile(rowIndex)) 
    { 
      fireTableRowsDeleted(rowIndex, rowIndex); 
    } 
    else 
    { 
     Udata.add(rowIndex,temp);//re-insert temp in ArrayList as the file updation is failed. 
     JOptionPane.showMessageDialog(null, "Unable to delete"); 
    } 
} 

public boolean RemoveUserFromFile(int index) 
{ 
    File Mf = new File("AllUserRecords.txt"); 
    File Tf = new File("Uoutput.txt"); 
    PrintWriter Upw = null; 
    try 
    { 
     Upw = new PrintWriter(new FileWriter(Tf)); 
     for (UserInformation uino : Udata) 
     { 
      Upw.print(uino.toString());//Don't use Upw.println because the toString() method of UserInformation class is already using \n in last. 
     } 
     Upw.close(); 
     Mf.delete(); 
     Tf.renameTo(Mf); 
     return true; 
    } catch (FileNotFoundException e1) { 
     return false; 
    } catch (IOException ioe) { 
     return false; 
    } 
    finally 
    { 
     if (Upw != null) 
     { 
      try 
      { 
       Upw.close(); 
      } 
      catch (Exception ex){} 
     } 
    } 
} 

Я надеюсь, что это устроился ваша проблема сейчас ...

ПРИМЕЧАНИЕ: В качестве примечания. Я хочу предложить вам придерживаться соглашения об именах java при написании ваших кодов. Например: Имя класса всегда начинается с заглавной буквы. Имя переменной всегда начинается с маленькой буквы. И константы (т. Е. Конечные переменные) имеют все буквы в капитале. Есть много других. Посмотрите на official site оракула.

+0

@ Sajjad- Посмотрите обновленный ответ .. –

+0

О да. Очень хорошо объясняют и понимают. – Sajad

+0

Как мне сказали @SeKa, еще одна проблема заключается в том, что когда я пишу: – Sajad

5

Несколько вещей, я хотел бы изменить здесь:

  • в вашем RemoveRow, только Udata.remove(rowIndex); fireTableRowsDeleted(rowIndex, rowIndex);
  • заменить RemoveUserFromFile метод с методом saveToFile(File file), который бы просто итерацию над Udata и записать его в данной file

Боковые ноты:

  • следуют соглашениям об именах Java (переменные и методы начинаются с буквы нижнего регистра!). Из-за этого ваш код намного сложнее читать.
  • В своем titleUserCount() вы каждый раз воссоздаете новый TableModel, только для подсчета записей в таблице. Вы могли бы просто использовать userModel.getRowCount()
  • Там нет необходимости exend JFrame
+0

+1, как предложение 'saveToFile()'. Поскольку метод setValueAt (...) был реализован, вы думаете, что в любом случае требуется функция сохранения. – camickr

+0

@ Гийом Полет я не могу понять! Можете ли вы объяснить больше? – Sajad

+0

@camickr Вы больше не можете объяснить? – Sajad

3

Этот тест:

if (!line.startsWith(String.valueOf(getValueAt(index, 0)))) { 

в методе removeUserFromFile() является ОЧЕНЬ ОПАСЕН, потому что это испытание строки таким образом, что идентификатор как 3 будет соответствовать 30, 31, 35, 301 и т.д. (почти ничего начиная с 3).

Чтобы исправить этот конкретный тест, вы, вероятно, захотите сравнить идентификаторы как целые числа. Во-первых, тянуть номер из линии, что-то вроде:

Integer.parseInt(line.split("\\s")[0]); 

Затем сравните это число в ваш getValueAt из таблицы.

Следует отметить, что другие ответы имеют лучшие общие конструкции; это просто предназначено для решения конкретной проблемы.

+0

О, да! Очень полезно. – Sajad

+0

Есть ли другие проблемы в моем коде? – Sajad

+0

Что значит «\\ s»? – Sajad