2016-03-19 10 views
1

für das Leben von mir Ich kann nicht herausfinden, was ist los mit diesen Codes .. die speichern, um sich selbst zu überschreiben und die Last von lädt nicht die bereits vorhandenen Daten. . ich habe für diesen Code gesucht, aber es scheint, wie Menschen verschiedene Codes verwenden .. bitte helfen Sie mirspeichern und laden von nicht funktioniert in Java

// Write to file 
static void writeToFile(Customer c[], int number_of_customers) throws IOException { 
    // set up file for output 
    // pw used to write to file 
    File outputFile = new File("Customers.dat"); 
    FileOutputStream fos = new FileOutputStream(outputFile); 
    PrintWriter pw = new PrintWriter(new OutputStreamWriter(fos)); 

    int i = 0; 
    do { 
     pw.println(c[i].getName()); 
     pw.println(c[i].getNumber()); 
     i++; 
    } while (i < number_of_customers); 
    pw.println(0); 
    pw.println(0); 
    pw.close(); 
} 

// Read from file 
public static int readFromFile(Customer c[]) throws IOException { 
    // set up file for reading 
    // br used to read from file 
    File inputFile = new File("Customers.dat"); 
    FileInputStream fis = new FileInputStream(inputFile); 
    BufferedReader br = new BufferedReader(new InputStreamReader(fis)); 

    String cus; 
    int l = -1; 
    // Subtract AND assignment operator, It subtracts right operand from the 
    // left operand and assign the result to left operand 
    int all_customers = 0; 
    do { 
     l++; 
     c[l] = new Customer(); 
     c[l].cus_name = br.readLine(); 
     cus = br.readLine(); 
     c[l].cus_no = Integer.parseInt(cus); 
     all_customers++; 

    } while (c[l].cus_no != 0); // end while 

    br.close(); // end ReadFile class 
    return all_customers - 1; 
} 
+1

Was genau ist falsch? Ihre Beschreibung des Problems ist ziemlich vage – dovetalk

+0

der erste Code überschreiben die Daten existieren in, dh: wenn die Datei einen Namen0 und Nummer0 gespeichert hat .. dann geben Sie name2 und number2 die ersten Werte werden gelöscht und die zweiten Werte werden nehmen Sie es an Stelle ... wie für den zweiten Code liest es nicht die Werte, die bereits gespeichert haben, wenn Sie es nicht überschreiben .. ich hoffe, dass es Ihnen klar ist – jill

+0

So wollen Sie 'writeToFile', um das zu verschmelzen Dateiinhalt mit den übergebenen Datensätzen? – dovetalk

Antwort

1

Sie haben eine Reihe von Problemen mit Ihrem Code meine Kopfschmerzen zu beenden.

Betrachtet man zunächst Ihre readFromFile Methode:

  • Sie sind in einem Array übergeben, die Ihre Methode füllt sich mit allen Aufzeichnungen es findet. Was passiert, wenn mehr Kunden in der Datei sind, als im Array Platz ist? (Hinweis: ArrayIndexOutOfBoundsException ist eine Sache)
  • Sie analysieren eine Ganzzahl, die als Zeichenfolge aus der Datei gelesen wird. Was passiert, wenn die Datei beschädigt ist und die gelesene Zeile keine Ganzzahl ist?
  • Der Name der Datei, aus der gelesen werden soll, ist fest codiert. Dies sollte eine konstante oder Konfigurationsoption sein. Um Methoden zu schreiben, ist es am besten, sie zu einem Parameter zu machen.
  • Sie öffnen die Datei und lesen daraus in der Methode. Für Unit-Tests sollten Sie diese in separate Methoden aufteilen.
  • Im Allgemeinen sollten Sie eine Collections Klasse anstelle eines Arrays verwenden, um eine Liste von Objekten zu speichern.
  • Sie greifen auf die Customer Attribute direkt in der readFromFile Methode zu. Sie sollten eine Zugriffsmethode verwenden.

Collections -basierte Ansatz

Hier ist mein Vorschlag Rewrite basiert auf der Verwendung Collections APIs:

public static List<Customer> readFromFile(String filename) throws IOException { 
    // set up file for reading 
    // br used to read from file 
    File inputFile = new File(filename); 
    FileInputStream fis = new FileInputStream(inputFile); 
    BufferedReader br = new BufferedReader(new InputStreamReader(fis)); 

    List<Customer> customers = readFromStream(br); 

    br.close(); // end ReadFile class 

    return customers; 
} 

Diese verwendet diese Methode, um tatsächlich den Inhalt zu lesen:

public static List<Customer> readFromStream(BufferedReader br) throws IOException { 

    List<Customer> customerList = new LinkedList<>(); 

    // Subtract AND assignment operator, It subtracts right operand from the 
    // left operand and assign the result to left operand 
    boolean moreCustomers = true; 
    while (moreCustomers) { 
     try { 
      Customer customer = new Customer(); 
      customer.setName(br.readLine()); 
      String sCustNo = br.readLine(); 
      customer.setNumber(Integer.parseInt(sCustNo)); 
      if (customer.getNumber() == 0) { 
       moreCustomers = false; 
      } 
      else { 
       customerList.add(customer); 
      } 
     } 
     catch (NumberFormatException x) { 
      // happens if the line is not a number. 
      // handle this somehow, e.g. by ignoring, logging, or stopping execution 
      // for now, we just stop reading 
      moreCustomers = false; 
     } 
    } 

    return customerList; 
} 

eine Verwendung ähnlicher Ansatz für writeToFile, erhalten wir:

static void writeToFile(Collection<Customer> customers, String filename) throws IOException { 
    // set up file for output 
    // pw used to write to file 
    File outputFile = new File(filename); 
    FileOutputStream fos = new FileOutputStream(outputFile); 
    PrintWriter pw = new PrintWriter(new OutputStreamWriter(fos)); 

    writeToStream(customers, pw); 

    pw.flush(); 
    pw.close(); 
} 

static void writeToStream(Collection<Customer> customers, PrintWriter pw) throws IOException { 

    for (Customer customer: customers) { 
     pw.println(customer.getName()); 
     pw.println(customer.getNumber()); 
    } 
    pw.println(0); 
    pw.println(0); 

} 

Wir haben jedoch immer noch nicht Ihre Hauptsorge angesprochen. Anscheinend möchten Sie den Dateiinhalt mit den Kunden im Speicher zusammenführen, wenn Sie writeToFile aufrufen. Ich schlage vor, dass Sie stattdessen eine neue Methode für diesen Zweck einführen. Dies hält die bestehenden Methoden einfacher:

static void syncToFile(Collection<Customer> customers, String filename) throws IOException { 

    // get a list of existing customers 
    List<Customer> customersInFile = readFromFile(filename); 

    // use a set to merge 
    Set<Customer> customersToWrite = new HashSet<>(); 

    // first add current in-memory cutomers 
    customersToWrite.addAll(customers); 

    // then add the ones from the file. Duplicates will be ignored 
    customersToWrite.addAll(customersInFile); 

    // then save the merged set 
    writeToFile(customersToWrite, filename); 
} 

Oh ... ich fast vergessen: Die Magie eines Set der Verwendung der Datei und im Speicher zu fusionieren Liste stützt sich auf Sie die equals() Methode in der Klasse Customer zu implementieren. Wenn Sie equals() überschreiben, sollten Sie auch hashCode() überschreiben. Zum Beispiel:

public class Customer { 
    @Override 
    public boolean equals(Object obj) { 
     return (obj != null) && (obj instanceof Customer) && (getNumber() == ((Customer)obj).getNumber()); 
    } 

    @Override 
    public int hashCode() { 
     return getNumber()+31; 
    } 
}; 

CustomerList -basierte Ansatz

Wenn Sie Collections APIs nicht verwenden können, die zweitbeste wäre eine eigene Kollektion Art zu schreiben, die die gleichen Operationen unterstützt, wird aber von einem Array gesichert (oder verknüpfte Liste, wenn Sie das gelernt haben).In Ihrem Fall wäre es eine Liste von Kunden. Ich rufe den Typ CustomerList:

Analysieren unseres vorhandenen Codes, benötigen wir eine Klasse, die eine add Methode und eine Möglichkeit zum Durchlaufen der Liste implementiert. Ignorieren Iterators, erreichen wir das letztere mit einem getLength und einem getCustomer (per Index). Für die Synchronisation, müssen wir auch eine Möglichkeit zu überprüfen, ob ein Kunde in der Liste enthalten ist, so dass wir eine contains Methode hinzufügen:

public class CustomerList { 

    private static final int INITIAL_SIZE = 100; 
    private static final int SIZE_INCREMENT = 100; 

    // list of customers. We're keeping it packed, so there 
    // should be no holes! 
    private Customer[] customers = new Customer[INITIAL_SIZE]; 
    private int numberOfCustomers = 0; 

    /** 
    * Adds a new customer at end. Allows duplicates. 
    * 
    * @param newCustomer the new customer to add 
    * @return the updated number of customers in the list 
    */ 
    public int add(Customer newCustomer) { 

     if (numberOfCustomers == customers.length) { 
      // the current array is full, make a new one with more headroom 
      Customer[] newCustomerList = new Customer[customers.length+SIZE_INCREMENT]; 
      for (int i = 0; i < customers.length; i++) { 
       newCustomerList[i] = customers[i]; 
      } 
      // we will add the new customer at end! 
      newCustomerList[numberOfCustomers] = newCustomer; 

      // replace the customer list with the new one 
      customers = newCustomerList; 
     } 
     else { 
      customers[numberOfCustomers] = newCustomer; 
     } 

     // we've added a new customer! 
     numberOfCustomers++; 

     return numberOfCustomers; 
    } 

    /** 
    * @return the number of customers in this list 
    */ 
    public int getLength() { 
     return numberOfCustomers; 
    } 

    /** 
    * @param i the index of the customer to retrieve 
    * @return Customer at index <code>i</code> of this list (zero-based). 
    */ 
    public Customer getCustomer(int i) { 
     //TODO: Add boundary check of i (0 <= i < numberOfCustomers) 
     return customers[i]; 
    } 

    /** 
    * Check if a customer with the same number as the one given exists in this list 
    * @param customer the customer to check for (will use customer.getNumber() to check against list) 
    * @return <code>true</code> if the customer is found. <code>false</code> otherwise. 
    */ 
    public boolean contains(Customer customer) { 
     for (int i = 0; i < numberOfCustomers; i++) { 
      if (customers[i].getNumber() == customer.getNumber()) { 
       return true; 
      } 
     } 
     // if we got here, it means we didn't find the customer 
     return false; 
    } 

} 

Damit implementiert, die Neufassung der writeToFile Methode ist genau das gleiche, außer wir verwenden CustomerList statt List<Customer>:

static void writeToFile(CustomerList customers, String filename) throws IOException { 
    // set up file for output 
    // pw used to write to file 
    File outputFile = new File(filename); 
    FileOutputStream fos = new FileOutputStream(outputFile); 
    PrintWriter pw = new PrintWriter(new OutputStreamWriter(fos)); 

    writeToStream(customers, pw); 

    pw.flush(); 
    pw.close(); 
} 

die writeToStream ist auch sehr ähnlich, mit der Ausnahme, da wir keine Iterator verwenden, haben wir die Liste manuell zu durchqueren:

static void writeToStream(CustomerList customers, PrintWriter pw) throws IOException { 

    for (int i = 0; i < customers.getLength(); i++) { 
     pw.println(customers.getCustomer(i).getName()); 
     pw.println(customers.getCustomer(i).getNumber()); 
    } 
    pw.println(0); 
    pw.println(0); 

} 

Ähnliche für readFromFile - so ziemlich das gleiche mit Ausnahme des Listentyp:

public static CustomerList readFromFile(String filename) throws IOException { 
    // set up file for reading 
    // br used to read from file 
    File inputFile = new File(filename); 
    FileInputStream fis = new FileInputStream(inputFile); 
    BufferedReader br = new BufferedReader(new InputStreamReader(fis)); 

    CustomerList customers = readFromStream(br); 

    br.close(); // end ReadFile class 

    return customers; 
} 

Die readFromStream auch das gleiche ist ziemlich viel, außer für den Typen (die auf CustomerList verwendeten Methoden hat die gleiche Signatur wie die, die verwendeten List<Customer>:

public static CustomerList readFromStream(BufferedReader br) throws IOException { 

    CustomerList customerList = new CustomerList(); 

    // Subtract AND assignment operator, It subtracts right operand from the 
    // left operand and assign the result to left operand 
    boolean moreCustomers = true; 
    while (moreCustomers) { 
     try { 
      Customer customer = new Customer(); 
      customer.setName(br.readLine()); 
      String sCustNo = br.readLine(); 
      customer.setNumber(Integer.parseInt(sCustNo)); 
      if (customer.getNumber() == 0) { 
       moreCustomers = false; 
      } 
      else { 
       customerList.add(customer); 
      } 
     } 
     catch (NumberFormatException x) { 
      // happens if the line is not a number. 
      // handle this somehow, e.g. by ignoring, logging, or stopping execution 
      // for now, we just stop reading 
      moreCustomers = false; 
     } 
    } 

    return customerList; 
} 

die andere Methode der syncToFile ist, wie wir die Set Typ nicht haben, die keine Duplikate garantiert, haben wir manuell zu überprüfen jedes Mal versuchen wir einen Kunden aus der Datei einfügen:

static void syncToFile(CustomerList customers, String filename) throws IOException { 

    // get a list of existing customers 
    CustomerList customersInFile = readFromFile(filename); 

    // use a set to merge 
    CustomerList customersToWrite = new CustomerList(); 

    // first add current in-memory customers 
    for (int i = 0; i < customers.getLength(); i++) { 
     customersToWrite.add(customers.getCustomer(i)); 
    } 

    // then add the ones from the file. But skip duplicates 
    for (int i = 0; i < customersInFile.getLength(); i++) { 
     if (!customersToWrite.contains(customersInFile.getCustomer(i))) { 
      customersToWrite.add(customersInFile.getCustomer(i)); 
     } 
    } 

    // then save the merged set 
    writeToFile(customersToWrite, filename); 
} 

Etwas zu beachten ist hier, dass wir, indem er einen zusätzlichen Konstruktor für CustomerList, die die neue Kapazität nahm die add Operationen optimiert haben könnte, aber ich werde verlassen mindestens etwas für Sie herauszufinden;)

+0

vielen dank viel für deinen Input .. es zeigt wahres Verständnis für Java, wo du es verstehen und mir helfen kannst, es besser zu verstehen ...Das Problem mit set ist, dass ich es nicht verwenden kann, da wir es in meinem Kurs nicht behandelt haben .. wie für die Liste hatte ich den folgenden Code, um die Liste zu zeigen \t public static void list_of_customers (Kunde c [], int number_of_customers) löst IOException \t { \t int m = 0; \t do \t { \t c [m] .output(); \t m ++; \t} while (m jill

+0

Sie hatten also ein großes Array, das garantiert genug Platz für alle Kunden hatte? Gibt es einen Grund, warum Sie keinen CustomerList-Typ zum Einkapseln der Array-Verwaltung erstellt haben? – dovetalk

+0

Ich habe meine Antwort erweitert und gezeigt, wie Sie dasselbe tun können, ohne die 'Collections' API zu verwenden. – dovetalk

1

Eine alternative Möglichkeit, Ihre Schreibmethode zu beheben, wäre die Verwendung eines FileOutputStream-Konstruktors, mit dem Sie die Daten am Ende der Datei anhängen können.

Dies setzt voraus, dass Sie auch unter Fehlerbedingungen immer einen vollständigen Endsatz mit einem Zeilenende schreiben. Sie müssen sich mit dieser Art von Situation immer noch mit der anderen Lösung (Lesen und Zusammenführen) auseinandersetzen, aber damit kann der nachfolgende Lauf bei Bedarf erkennen und sich damit befassen. Also ist die Append-Lösung, die ich beschreibe, nicht so robust.

+0

Dies ist ein Ansatz. Es ignoriert jedoch die Tatsache, dass wir einen speziellen EOF "Customer" -Marker verwenden (mit dem Namen und der Nummer auf "0" gesetzt). Natürlich könnten wir den ursprünglichen Ansatz ändern, diesen Marker nicht zu verwenden und stattdessen mit dem integrierte Java-Datei-I/O-APIs ... – dovetalk

Verwandte Themen