【问题标题】:Java BufferedFileReader skips first lineJava BufferedFileReader 跳过第一行
【发布时间】:2018-12-15 14:50:59
【问题描述】:

我正在尝试使用 BufferedFileReader 读取包含已保存信息的文档。它工作得很好,但它总是跳过代码的第一行。是因为我在 for 循环中调用 readLine() 吗?如果是这样,我怎么能改变它?

private void createViewUser() {

    String[] stringFirstName = new String[10];
    String[] stringName = new String[10];
    String[] stringAge= new String[10];

    try {
        FileReader fr = new FileReader(file);
        BufferedReader br = new BufferedReader(fr);

        for (int i = 0; br.readLine() != null; i++) {

            stringFirstName[i] = br.readLine();
            stringName[i] = br.readLine();
            stringAge[i] = br.readLine();

            firstname[i] = new JTextField();
            firstname[i].setBounds(100, 100 + 50 * i, 100, 30);
            view.add(firstname[i]);

            name[i] = new JTextField();
            name[i].setBounds(200, 100 + 50 * i, 100, 30);
            view.add(name[i]);

            age[i] = new JTextField();
            age[i].setBounds(300, 100 + 50 * i, 100, 30);
            view.add(age[i]);

            firstname[i].setText(stringFirstName[i]);
            name[i].setText(stringName[i]);
            age[i].setText(stringAge[i]);

        }
        fr.close();
        br.close();



    } catch (IOException ex) {
        ex.printStackTrace();
    }


}

【问题讨论】:

  • 与您的问题无关,但您的组件定位、使用空布局和setBounds 是一件非常糟糕的事情,因为这样做会创建一个僵化、难以调试或增强的程序,一个这在具有不同分辨率的计算机上看起来很糟糕,并且与您正在使用的 GUI 库作斗争。如果这是我的程序,并且我正试图像您一样显示表格数据,为什么不更简单地在 JTable 中创建和显示这些信息?
  • 另外,您正在使用并行数组,这是一个糟糕的设计选择,应该考虑创建一个类来在单个对象中保存名字和姓氏以及年龄。然后创建这些对象的 ArrayList。
  • 是的,你是对的,但这只是我的第一个想法,我想完成它,然后可能会改变它。无论如何,谢谢,我会尽快尝试。而且我才刚刚开始,从未使用过 ArrayLists,所以我尽量避免使用它们

标签: java swing io text-files


【解决方案1】:

没错,每次进入 for 循环之前,您的程序都会读取一行并检查它是否不为空。 由于这种情况,您还将跳过一行。 (不确定是否需要) 你自己也有答案;)

【讨论】:

  • 好的,我可以用什么代替?
【解决方案2】:

您正在阅读 for 循环中的第一行:

for (int i = 0; br.readLine() /* HERE*/ != null; i++) {

你可以这样做:

String line = br.readLine();
for(int i = 0; line != null ; i++){
       stringFirstName[i] = line;
       line = br.readLine();
}

【讨论】:

    【解决方案3】:

    您好,您可以初始化 String var 来修复它:

    String line = br.readLine();
    
    for (int i = 0; line != null; i++) {
        stringFirstName[i] = line;
        stringName[i] = br.readLine();
        stringAge[i] = br.readLine();
    

    它不起作用,因为它在循环验证 for (int i = 0; br.readLine() != null; i++) {987654322@ 上加载了第一行

    祝你好运。

    【讨论】:

      【解决方案4】:

      您的问题涉及几个步骤,但对您而言最重要的问题是当数据以三行一组的形式呈现时,如何有效安全地读取文本文件中保存的数据,例如:

      first_name_1
      last_name_1
      age_1
      first_name_2
      last_name_2
      age_2
      first_name_3
      last_name_3
      age_3
      first_name_4
      last_name_4
      age_4
      

      当然是用真实姓名代替名字,还有年龄?替换为实数。

      如果您要走 BufferedReader 路线,我认为最安全的做法是在 while 循环的布尔条件内的每个分组中获取 所有三个字符串,例如:

      BufferedReader reader = new BufferedReader(....);
      
      // declare empty Strings first
      String firstName = "";
      String lastName = "";
      String ageString = ""; // need to get age *first* as a String
      
      while ((firstName = reader.readLine()) != null         // get all 3 Strings here
              && (lastName = reader.readLine()) != null
              && (ageString = reader.readLine()) != null) {  // boolean condition ends here
          int age = Integer.parseInt(ageString.trim());    // NumberFormatException risk here
      
          // ....
      
      }
      

      这样,如果文本文件中缺少任何一个Strings,整个while循环结束,不会得到坏数据。

      其他建议,创建一个普通的 Java 对象来保存您的 Person 数据、姓名和年龄,一个具有 3 个字段的类,其中 2 个字段是名称的字符串,以及一个用于年龄的 int 字段。给它一个像样的构造函数,getter 方法……例如:

      public class Person {
          private String firstName;
          private String lastName;
          private int age;
      
          public Person(String firstName, String lastName, int age) {
              this.firstName = firstName;
              this.lastName = lastName;
              this.age = age;
          }
      
          public String getFirstName() {
              return firstName;
          }
      
          public String getLastName() {
              return lastName;
          }
      
          public int getAge() {
              return age;
          }
      
          @Override
          public String toString() {
              return "Person [firstName=" + firstName + ", lastName=" + lastName + ", age=" + age + "]";
          }
      
      }
      

      这样,上面的 while 循环可以用来简单地创建 Person 对象:

      List<Person> persons = new ArrayList<>();  // an ArrayList of Person to hold the data
      
      while ((firstName = reader.readLine()) != null              // get all 3 Strings here
              && (lastName = reader.readLine()) != null
              && (ageString = reader.readLine()) != null) {       // the while loop ends here
          int age = Integer.parseInt(ageString.trim());
      
          Person person = new Person(firstName, lastName, age);   // create a new Person object 
          persons.add(person);                                    // put it into the arraylist
      }
      

      好的,如何将这些信息显示到 JTable 中——这很简单。

      使用正确的列名创建一个 DefaultTableModel:

      private static final String[] COL_NAMES = { "First Name", "Last Name", "Age" };
      private DefaultTableModel model = new DefaultTableModel(COL_NAMES, 0);
      

      然后用这个模型创建一个 JTable:

      private JTable table = new JTable(model);
      

      然后遍历ArrayList&lt;Person&gt;并用数据填充我们的模型:

      for (Person person : personList) {
          Vector<Object> rowData = new Vector<>();
          rowData.add(person.getFirstName());
          rowData.add(person.getLastName());
          rowData.add(person.getAge());
          model.addRow(rowData);
      }
      

      然后 JTable 就这样被创建并填充了数据。

      好的,假设一个名为 PersonData.txt 的数据文件与我们的类文件位于同一目录中,如下所示:

      假设这个文件像这样保存我们的数据:

      John
      Smith
      21
      Fred
      Flinstone
      53
      Barny
      Rubble
      52
      Mary
      Contrary
      22
      Bo
      Peep
      12
      Donald
      Trump
      75
      Donald
      Duck
      40
      Mickey
      Mouse
      45
      Minnie
      Mouse
      41
      Ebenezer
      Scrooge
      80
      Bob
      Cratchit
      33
      Ralph
      Kramden
      55
      Alice
      Kramden
      48
      Ed
      Norton
      54
      

      然后使用我们的 Person.java 类,我们可以创建一个 GUI 来保存和显示我们的数据,如下所示:

      import java.awt.BorderLayout;
      import java.io.BufferedReader;
      import java.io.IOException;
      import java.io.InputStream;
      import java.io.InputStreamReader;
      import java.util.ArrayList;
      import java.util.List;
      import java.util.Vector;
      
      import javax.swing.*;
      import javax.swing.table.DefaultTableModel;
      
      @SuppressWarnings("serial")
      public class PersonDisplay extends JPanel {
          private static final String[] COL_NAMES = { "First Name", "Last Name", "Age" };
          private static final String PERSON_DATA_PATH = "PersonData.txt";
          private DefaultTableModel model = new DefaultTableModel(COL_NAMES, 0);
          private JTable table = new JTable(model);
      
          public PersonDisplay(List<Person> personList) {
              for (Person person : personList) {
                  Vector<Object> rowData = new Vector<>();
                  rowData.add(person.getFirstName());
                  rowData.add(person.getLastName());
                  rowData.add(person.getAge());
                  model.addRow(rowData);
              }
      
              setLayout(new BorderLayout());
              add(new JScrollPane(table));
          }
      
          private static void createAndShowGui(List<Person> personList) {
              PersonDisplay mainPanel = new PersonDisplay(personList);
      
              JFrame frame = new JFrame("Person Display");
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              frame.getContentPane().add(mainPanel);
              frame.pack();
              frame.setLocationRelativeTo(null);
              frame.setVisible(true);
          }
      
          public static List<Person> readInPersons(InputStream is) throws IOException {
              List<Person> persons = new ArrayList<>();
              BufferedReader reader = new BufferedReader(new InputStreamReader(is));
              String firstName = "";
              String lastName = "";
              String ageString = "";
      
              while ((firstName = reader.readLine()) != null 
                      && (lastName = reader.readLine()) != null
                      && (ageString = reader.readLine()) != null) {
                  int age = Integer.parseInt(ageString.trim());
                  Person person = new Person(firstName, lastName, age);
                  persons.add(person);
              }
      
              return persons;
          }
      
          public static void main(String[] args) {
              try {
                  InputStream inputStream = PersonDisplay.class.getResourceAsStream(PERSON_DATA_PATH);
                  List<Person> personList = readInPersons(inputStream);
                  SwingUtilities.invokeLater(() -> createAndShowGui(personList));
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      }
      

      当显示时,它看起来像:

      【讨论】:

        猜你喜欢
        • 2014-06-07
        • 2013-08-17
        • 2013-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-09-29
        • 2018-02-02
        相关资源
        最近更新 更多