我正在java中创建一个没有数据库的库系统程序。(直接使用文件)。
我在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
答案 0 :(得分:5)
我会在这里改变一些事情:
RemoveRow
中,只有Udata.remove(rowIndex); fireTableRowsDeleted(rowIndex, rowIndex);
RemoveUserFromFile
方法替换您的saveToFile(File file)
方法,该方法只会迭代Udata
并将其写入给定的file
附注:
titleUserCount()
中,您每次都在重新创建一个新的TableModel,只计算表中的条目。您只需使用userModel.getRowCount()
JFrame
答案 1 :(得分:4)
好吧,因为我没有你的所有代码,所以我正在进行一个虚拟程序,用于从JTable
删除记录以及相应的文件。观看removeRow
课程中定义的MyTabeModel
方法。它还涵盖了从file
删除record
后无法在ArrayList
(records.temp)上写入数据的风险。
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();
}
});
}
}
<强>更新强>
有时当我在表格中选择一行并点击删除按钮时, 更多的一行已被删除!
通过你的代码后,我知道你删除了多行的情况。 案例是: 如果您的文件中有多行,则从您要删除的同一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
此处,userID 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命名约定。例如:类名始终以大写字母开头。变量名称始终以小写字母开头。常数(即最终变量)的所有字母都是大写的。还有很多其他的。看看oracle的official site。
答案 2 :(得分:3)
这个测试:
if (!line.startsWith(String.valueOf(getValueAt(index, 0)))) {
您的removeUserFromFile()
方法中的非常危险,因为它是一个字符串测试,因此像3这样的ID将匹配30,31,35,301等。(几乎任何东西都以3)。
要修复此特定测试,您可能希望将ID作为整数进行比较。首先,从行中提取数字,例如:
Integer.parseInt(line.split("\\s")[0]);
然后将该数字与表格中的getValueAt
进行比较。
值得注意的是,其他答案的整体设计更好;这只是针对特定问题。