# Strings aus externen Dateien Einlesen (Sudoku)



## VIDEN (21. Nov 2006)

Hi,

ich habe ein Sudoku Spiel Programmiert.
Da ich unter Zeitdruck stehe, habe ich im Moment keine Zeit einen richtig funktionierenden Generator zu coden, der verschiedene Schwierigkeitsgrade unterstützt.
Ich will also eine spielbare Version mit 3 Sudoku "DatenBanken" haben. (easy, medium, hard).
Bis jetzt sieht das so aus:


```
import java.util.ArrayList;
import java.util.Random;
/**
 *
 * @author eberldav
 */
public class Generator {
    
    ArrayList easyPuzzles= new ArrayList();
    ArrayList mediumPuzzles= new ArrayList();
    ArrayList hardPuzzles= new ArrayList();
    
    /** Creates a new instance of Generator */
    public Generator() {
       int[][] test0={//easy
            {3, 0, 0, 0, 0, 0, 0, 2, 0},
            {0, 7, 5, 4, 2, 1, 6, 0, 9},
            {6, 2, 0, 3, 5, 9, 8, 7, 4},
            {0, 3, 0, 5, 8, 0, 0, 0, 7},
            {0, 8, 7, 0, 0, 4, 0, 5, 0},
            {0, 9, 0, 1, 6, 7, 2, 0, 0},
            {0, 5, 0, 2, 1, 0, 0, 4, 0},
            {4, 6, 8, 7, 0, 0, 0, 0, 2},
            {7, 0, 0, 8, 4, 3, 9, 6, 5}};
       int[][] test1={//hard
            {4, 0, 0, 0, 1, 6, 0, 0, 5},
            {0, 0, 1, 0, 9, 2, 3, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 9, 3, 0, 7, 0, 0, 5, 0},
            {2, 0, 4, 0, 0, 0, 1, 0, 7},
            {0, 6, 0, 0, 8, 0, 9, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 5, 1, 2, 0, 4, 0, 0},
            {9, 0, 0, 7, 4, 0, 6, 0, 3}};
        
        int[][] test2={
            {0, 9, 0, 3, 7, 0, 0, 0, 5},
            {3, 0, 0, 0, 0, 4, 0, 9, 1},
            {0, 4, 0, 1, 0, 0, 0, 6, 0},
            {0, 0, 0, 0, 0, 9, 0, 0, 0},
            {4, 0, 0, 6, 0, 5, 0, 0, 2},
            {0, 0, 0, 8, 0, 0, 0, 0, 0},
            {0, 2, 0, 0, 0, 7, 0, 3, 0},
            {1, 8, 0, 4, 0, 0, 0, 0, 7},
            {7, 0, 0, 0, 8, 3, 0, 1, 0}};
        
        int[][] test3={
            {0, 7, 0, 6, 0, 0, 0, 0, 0},
            {0, 3, 1, 2, 0, 0, 5, 0, 0},
            {0, 0, 0, 5, 0, 0, 0, 0, 0},
            {0, 4, 0, 0, 3, 0, 6, 0, 0},
            {0, 0, 0, 0, 0, 5, 0, 0, 2},
            {0, 0, 7, 0, 0, 0, 0, 9, 1},
            {6, 0, 9, 0, 0, 0, 4, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 3},
            {0, 0, 0, 1, 7, 6, 2, 0, 0}};
       
        this.addBoard(test0, 0);
        this.addBoard(test1, 2);
        this.addBoard(test2, 1);
        this.addBoard(test3, 1);
    }
    
    /**add a new Board to the data base*/
    public boolean addBoard(Board boardToAdd, int difficulty){
        switch(difficulty){
            case 0:
                easyPuzzles.add(boardToAdd);
                return true;
            case 1:
                mediumPuzzles.add(boardToAdd);
                return true;
            case 2:
                hardPuzzles.add(boardToAdd);
                return true;
            default: return false;
        }
    }
    
        /**add a new Board to the data base using int array*/
    public boolean addBoard(int[][] cellValues, int difficulty){
        Board boardToAdd= new Board(cellValues);
        Solver solver= new Solver(boardToAdd);
        solver.run();
        
        switch(difficulty){
            case 0:
                easyPuzzles.add(boardToAdd);
                return true;
            case 1:
                mediumPuzzles.add(boardToAdd);
                return true;
            case 2:
                hardPuzzles.add(boardToAdd);
                return true;
            default: return false;
        }
    }
    
    /**return a Puzzle according to its difficulty*/
    public Board getNewPuzzle(int difficulty){
        Random randomNum= new Random();
        Board board=new Board();
        Board tmpBoard;
        switch(difficulty){
            case 0:
                tmpBoard=(Board)easyPuzzles.get(randomNum.nextInt(easyPuzzles.size()));
                board=tmpBoard.copyInto(board);
                return board;
            case 1:
                tmpBoard=(Board)mediumPuzzles.get(randomNum.nextInt(mediumPuzzles.size()));
                board=tmpBoard.copyInto(board);
                return board;
            case 2:
                tmpBoard=(Board)hardPuzzles.get(randomNum.nextInt(hardPuzzles.size()));
                board=tmpBoard.copyInto(board);
                return board;
            default: return board=null;
        }
    }
}
```

Nur die ganzen Datenbanken jedes mal im Konstrukter so zu laden halte ich für nicht sehr sinnvoll, da dieser bei ca 50 Sudokus pro Schwierigkeitsgrad einfach total überladen ist.
Daher würde ich die Sudokus gerne aus einer externen Datei einfach irgendwie einlesen.
Schreibform für die Puzzles wäre dann diese:
"000306500800500000010000040900080020000000000040060001050000010000009002006108000"

nur ich hab absolut keine Ahnung wie ich das hinbekommen soll, ich habe garkeine Erfahrung wie man auf Java-externe Dateien zugreifen kann bzw ob das überhaupt geht und ob es das Ganze wirklich einfacher macht.
Daher würde ich mich über jede Hilfe freuen!

Grüsse David


----------



## The_S (21. Nov 2006)

Entweder missverstehe ich dein Vorhaben jetzt, oder dir hilft der BufferedWriter bzw. BufferedReader weiter  ???:L


----------



## Leroy42a (21. Nov 2006)

Hobbit_Im_Blutrausch hat gesagt.:
			
		

> Entweder missverstehe ich dein Vorhaben jetzt, oder dir hilft der BufferedWriter bzw. BufferedReader weiter  ???:L



Du verstehst schon richtig, allerdings ist da noch wesentlich
mehr nötig als ein BufferedReader

- zeilenweise die Sudoku-Rohdaten einlesen
- umwandeln der characters in Zahlen
- befüllen der arrays

und angesichts der Einschränkung


			
				VIDEN hat gesagt.:
			
		

> nur ich hab absolut keine Ahnung wie ich das hinbekommen soll, ich habe garkeine Erfahrung wie man auf nicht Java-externe Dateien zugreifen kann


habe ich mich mal zurückgehalten.


----------



## meez (21. Nov 2006)

VIDEN  hat gesagt.:
			
		

> ich habe garkeine Erfahrung wie man auf nicht Java-externe Dateien zugreifen kann




D.h. du weisst nicht wie man auf Java-interne Dateien zugreift...Was wiederum heisst, du weisst wie man auf externe Dateien zugreift... ???:L 

Ich mag nicht keine Doppel-Verneinungen... :wink:


----------



## The_S (21. Nov 2006)

zeilenweise = bufferedreader.readLine();
zahlen = Zeichenweiße durch das eingelesene durchgehen (z. B. charAt() und parsen
befüllen der arrays = array[0][0] = geparsteZahl


----------



## VIDEN (21. Nov 2006)

Danke für die schnellen Antworten!
Also für:

- umwandeln der characters in Zahlen 
- befüllen der arrays

habe ich bereits eine Funktion, die ich auch so schon benutze.
 aber eben bei: 
- zeilenweise die Sudoku-Rohdaten 

einlesen liegt mein Problem. 

ist der von mir gedachte Lösungsweg denn Sinvoll oder gibt es was besseres?

Grüsse David

EDIT:



			
				meez hat gesagt.:
			
		

> VIDEN  hat gesagt.:
> 
> 
> 
> ...



Das war keine doppelte Verneinung, das war einfach schlecht geschrieben. 
Wollte damit sagen, dass ich nicht weis, wie man auf externe Dateien die keine *.java Files sind zugreift.

David


----------



## Leroy42a (21. Nov 2006)

VIDEN hat gesagt.:
			
		

> ist der von mir gedachte Lösungsweg denn Sinvoll oder gibt es was besseres?



Der ist absolut sinnvoll:


```
BufferedReader br = new BufferedReader(new FileReader("meinSudoku.txt"));
String line;

while ((line = br.readLine()) !) null)
  // Umwandeln des Strings in ein int[][]
br.close();
```


----------



## VIDEN (21. Nov 2006)

Vielen dank, ich versuch das gleich mal umzusetzen!

Grüsse David


----------



## Leroy42a (21. Nov 2006)

VIDEN hat gesagt.:
			
		

> Wollte damit sagen, dass ich nicht weis, wie man auf externe Dateien die keine *.java Files sind zugreift.



Das heißt also im Umkehrschluß, daß du weist, wie man 
_auf externe Dateien die *.java-Files sind_, zugreifen kann.

Keine Angst! Auf externe nicht-Java-Dateien kannst du genauso
wie auf externe Java-Dateien zugreifen!  :meld: 

( :bae:   )


----------



## VIDEN (21. Nov 2006)

Leroy42a hat gesagt.:
			
		

> VIDEN hat gesagt.:
> 
> 
> 
> ...



damit meine ich, dass ich weis wie ich beispielweise von Generator.java auf die Methode run() von Solver.java zugreifen kann aber nicht wie von Generator.java auf die erste Zeile von Puzzles.txt
- Aber dank dir kann ich das ja jetzt doch  
...nur 

```
while(line = br.readLine()) !) null)
```
da stimmt was mit den Klammern nicht

David


----------



## Leroy42a (21. Nov 2006)

Sorry, mein Fehler:   

```
while ((line = br.readLine()) != null)
```


----------



## VIDEN (21. Nov 2006)

Hab alles implementiert:


```
try {
            BufferedReader in = new BufferedReader(new FileReader("EasyPuzzles.txt"));
            String line;
            while( null != (line = in.readLine()) ) {
                Board board= new Board(StringToIntArr(line));
                this.addBoard(board, 0);
            }
            in.close();
        } catch( Exception ex ) {
            System.out.println( ex );
        }
```

Dann habe ich eine File _EasyPuzzles.txt_ im gleichen Ordner wie die src-files erstellt und dort ein paar Sudokus reingeschrieben.
wenn ich das Programm ausführe bekomme ich aber folgende exception:

*java.io.FileNotFoundException: EasyPuzzles.txt (The system cannot find the file specified)*

was mache ich falsch?

Grüsse David


----------



## The_S (21. Nov 2006)

Du musst das File ja auch in den selben Ordner wie die class-Files legen :roll:


----------



## VIDEN (21. Nov 2006)

Ist sie ja! werden da automatisch mit reinkopiert...

Arbeite mit netbeans und die file ist in:
netbeansproject\Sudkou\src

sowie:
netbeansproject\Sudkou\build\classes

hab sie auch testhalber mal ins 
netbeansproject\Sudkou\dist
und
netbeansproject\Sudkou\dist\lib
kopiert, hilft alles nichts

David


----------



## The_S (21. Nov 2006)

In welchem Verzeichnis wird dein Programm denn ausgeführt? Versuchs mal mit der absoluten Pfadangabe


----------



## VIDEN (21. Nov 2006)

Also die *. jar file liegt in 
netbeansproject\Sudkou\dist

die *.class files in 
netbeansproject\Sudkou\build\classes

wo es ausgeführt wird kann ich nicht sagen, ich versuchs mal mit dem absoluten pfad, aber das kann ja keine endgültige Lösung sein...

David

EDIT:

okay mit dem absoluten Pfad geht es aber wie bekomme ich das anders hin? Ich kann ja nicht von jedem der das Spiel benutzt erwarten, dass ers in das gleiche Verzeichnis kopiert wie ich es habe...


Grüsse David


----------



## The_S (21. Nov 2006)

Du musst garantieren, dass das Programm auch aus dem Verzeichnis aufgerufen wird, in dem es sich befindet. Das wirste du aber kaum können.


----------



## VIDEN (21. Nov 2006)

Also, wenn ich das Programm über "Run Main Project" bei netbeans starten will, bringt er mir einen Fehler, weil er die Dateien nicht findet. (*.txt file im Ordner der *.jar)

Starte ich die *.jar direkt aus dem Ordner in der sie gespeichert ist, kann ohne Probleme auf die beiliegenden Textfiles zugegriffen werden. Lösche ich diese geht es logischerweise nicht mehr...

Also wie ich das sehe wird mir wohl nichts anderes übrig bleiben als während der entwicklung mit den absoluten Pfaden zu arbeiten und dann bei der "Veröffentlichung" auf die beiliegenden Dateien zu referieren.

Grüsse David


----------



## The_S (21. Nov 2006)

Ähm, wenn der User später z. B. eine Verknüpfung auf den Desktop zu deinem Jar anlegt und dabei nicht angiebt, wo die Datei ausgeführt werden soll, wird sie auf dem Desktop ausgeführt und findet deine Textdatei auch nicht. Da diese sowieso statisch ist, wäre es evtl. von Vorteil sie gleich mit ins Jar zu packen oder?


----------



## VIDEN (21. Nov 2006)

wenn du mir sagst wie man das macht??

Greets David

btw. wenn ich die *.jar per Verknüpfung vom Desktop aus starte gehts auch, weil bei Windoof Verknüpfungen standardmässig im Zielpfad ausgeführt werden. Nichts desto trotz würde ich es bevorzugen die files in der Jar zu haben!

David


----------



## Leroy42a (21. Nov 2006)

Wie das in NetBeans geht weiß ich auch nicht,
aber im Allgemeinen so:

jar cvfm Anwendung.jar Manifest *.class _resource1 resource2 ..._


----------



## VIDEN (21. Nov 2006)

hmm ich bekomm das grad noch nicht hin, hab jetzt aber Feierabend und geh erstma nach Hause. 
Ich hock mich morgen nochmal dran!

Danke David


----------



## The_S (21. Nov 2006)

Schau mal in die FAQ, da gibts nen guten Beitrag zum Thema jar. Du musst die Datei dann aber über ClassLoader.getRessource laden.


----------



## VIDEN (22. Nov 2006)

Ich habe hersaugefunden, dass Netbeans mir alle Files aus 
...\netbeansproject\Sudkou\build\classes
in die Jar packt. 

Das Problem ist, durch den Absoluten Pfad versucht er nach wie vor auf den angegeben pfad zuzugreifen und sobald die Files da nicht mehr liegen gibts Probleme...

Grüsse David


----------



## The_S (22. Nov 2006)

wie gesagt, du musst die Dateien über den ClassLoader aus dem JAR laden und nicht wie bisher aus dem Dateisystem deiner Festplatte.


----------



## VIDEN (22. Nov 2006)

k thx sry hab ich wohl überlesen, schein jetzt zu gehen!

Danke David


----------

