# Performanceproblem beim Einlesen aus Datei mittels Threads



## spacegaier (6. Sep 2007)

Hallo zusammen,

ich mahe folgendes:

Ich habe eine Datei mit mehr als einer Million float-Einträgen (bis hin zu 5 Mio. Einträgen). Diese Werte sollen nun in einen Vektor eingelesen werden. Während dessen wird mittels eines zweiten Threads ein Ladebalken, sowie die Anzahl der bereits eingelesenen floats angezeigt. Das Problem ist nur: Das ganze ist total langsam.  :cry:  
Für 100 geladene Einträge braucht das Programm 10 Sekunden -> für eine Million Einträge sind das ca. 27 Stunden (wenn ich mich net verrechnet hab  ???:L ) !!!  :? 

Ich hoffe ihrt findet die Performancebremse!!!

PS: Ich poste jetzt den ganzen Code zur Übersicht. Das Problem liegt aber vermutlich entweder beim Einlesen selber (ist hier BufferedStream die beste Lösung?) oder bei den Threads von denen ich bislang kaum Ahnuing habe; dieser Teil ist von dem Tut von Beni abgekupfert).

class app (startet nur das Programm):


```
public class App 
{
	public App()
	{
		AppWnd frame = new AppWnd();
		frame.setResizable(false);
		frame.setVisible(true);
	}
	
	public static void main(String[] args)
	{
		new App();
	}
}
```

class AppWnd (ist für das Programmfenster verantwortlich):


```
package app;

import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.lang.reflect.InvocationTargetException;

import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

public class AppWnd extends JFrame implements Runnable
{
	private javax.swing.JButton buttonCancel;
	private javax.swing.JButton buttonChoose;
	private javax.swing.JButton buttonQuit;
	private javax.swing.JLabel labelBonusCount;
	private javax.swing.JLabel labelPercentage;
	private javax.swing.JLabel labelPricesCount;
	private javax.swing.JProgressBar progressBarCompute;
	private javax.swing.JProgressBar progressBarLoad;

	private Reader reader = new Reader();

	public AppWnd()
	{
		super("Title");
		initComponents();

		this.centerWnd();
	}

	private void initComponents() 
	{
		buttonChoose = new javax.swing.JButton();
		labelPercentage = new javax.swing.JLabel();
		labelBonusCount = new javax.swing.JLabel();
		labelPricesCount = new javax.swing.JLabel();
		buttonCancel = new javax.swing.JButton();
		progressBarLoad = new javax.swing.JProgressBar();
		progressBarCompute = new javax.swing.JProgressBar();
		buttonQuit = new javax.swing.JButton();

		setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
		buttonChoose.setText("Datei auswählen");
		buttonChoose.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent evt)
			{
				start();
			}
		});

		labelPercentage.setText("n \\ a");

		labelBonusCount.setText("Prämienanzahl: 0");

		labelPricesCount.setText("Eingelesene Preise: 0");

		buttonCancel.setText("Abbrechen");
		buttonCancel.setEnabled(false);
		buttonCancel.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent evt)
			{
				stop();
			}
		});

		buttonQuit.setText("Beenden");
		buttonQuit.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent evt)
			{
				System.exit(0);
			}
		});

		javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
		getContentPane().setLayout(layout);
		layout.setHorizontalGroup(
				layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
				.addGroup(layout.createSequentialGroup()
						.addContainerGap()
						.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
								.addComponent(buttonChoose, javax.swing.GroupLayout.DEFAULT_SIZE, 500, Short.MAX_VALUE)
								.addComponent(progressBarLoad, javax.swing.GroupLayout.DEFAULT_SIZE, 500, Short.MAX_VALUE)
								.addComponent(labelPricesCount, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 270, Short.MAX_VALUE)
								.addComponent(progressBarCompute, javax.swing.GroupLayout.DEFAULT_SIZE, 500, Short.MAX_VALUE)
								.addComponent(labelBonusCount, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 270, Short.MAX_VALUE)
								.addComponent(labelPercentage, javax.swing.GroupLayout.DEFAULT_SIZE, 500, Short.MAX_VALUE)
								.addComponent(buttonCancel, javax.swing.GroupLayout.DEFAULT_SIZE, 500, Short.MAX_VALUE)
								.addComponent(buttonQuit, javax.swing.GroupLayout.DEFAULT_SIZE, 500, Short.MAX_VALUE))
								.addContainerGap())
		);
		layout.setVerticalGroup(
				layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
				.addGroup(layout.createSequentialGroup()
						.addContainerGap()
						.addComponent(buttonChoose)
						.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
						.addComponent(progressBarLoad, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
						.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
						.addComponent(labelPricesCount)
						.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
						.addComponent(progressBarCompute, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
						.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
						.addComponent(labelBonusCount)
						.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
						.addComponent(labelPercentage)
						.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
						.addComponent(buttonCancel)
						.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
						.addComponent(buttonQuit)
						.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
		);
		pack();
	}

	private File recieveFile()
	{
		JFileChooser fc = new JFileChooser();
		fc.setAcceptAllFileFilterUsed(false);
		fc.setDialogTitle("Datei auswählen");

		fc.setFileFilter(new javax.swing.filechooser.FileFilter() 
		{
			public boolean accept(File f) 
			{ 
				return f.isDirectory() || f.getName().toLowerCase().endsWith(""); 
			} 

			public String getDescription() 
			{ 
				return "Datei"; 
			} 
		});	

		int state = fc.showSaveDialog(null);

		if(state == JFileChooser.APPROVE_OPTION)
		{
			return new File(fc.getCurrentDirectory().getPath()+ "\\" + fc.getSelectedFile().getName());
		}

		return null;
	}

	protected void start()
	{ 	
		new Thread(this).start(); 
		
		buttonChoose.setEnabled(false); 
		buttonCancel.setEnabled(true);
		buttonQuit.setEnabled(false);
	} 

	protected void stop()
	{ 
		buttonCancel.setEnabled(false);
		buttonChoose.setEnabled(true);
		buttonQuit.setEnabled(true);
		reader.setInterrupted(true); 
	} 

	public void run()
	{ 
		reader.setInterrupted(false); 

		reader.run(progressBarLoad, recieveFile(), labelPricesCount); 

		if(reader.isInterrupted())
		{ 
			SwingUtilities.invokeLater(new Runnable()
			{ 
				public void run()
				{ 
					progressBarLoad.setMinimum(0); 
					progressBarLoad.setMaximum(1); 
					progressBarLoad.setValue(0); 
					buttonChoose.setEnabled(true); 
				} 
			}); 
		} 
		else
		{ 
			try 
			{ 
				SwingUtilities.invokeAndWait(new Runnable()
				{ 
					public void run()
					{ 
						JOptionPane.showMessageDialog(null, "Algorithmus erfolgreich beendet.", "Beendet", JOptionPane.INFORMATION_MESSAGE); 
					} 
				}); 
			}
			catch(InterruptedException e)
			{ 
				e.printStackTrace(); 
			} 
			catch(InvocationTargetException e) 
			{ 
				e.printStackTrace(); 
			} 
		} 
	} 
	
	public void centerWnd()
	{
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		Dimension frameSize = this.getSize();
		if(frameSize.height > screenSize.height) 
		{
			frameSize.height = screenSize.height;
		}
		if(frameSize.width > screenSize.width)
		{
			frameSize.width = screenSize.width;
		}
		this.setLocation((screenSize.width  - frameSize.width)  / 2, (screenSize.height - frameSize.height) / 2);
	}
}
```

class Reader (ist für das Einlesen der Datei zuständig):


```
package app;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.util.Vector;

import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;

public class Reader 
{
	// Membervariablen
	//----------------
	int lineCount;

	private Vector<Float> vectorPrices = new Vector<Float>();
	
	private JProgressBar status;
	private boolean interrupted = false; 

	// Getter / Setter
	//----------------
	public int getLineCount(){return this.lineCount;}

	public Vector<Float> getPricesVector(){return this.vectorPrices;}

	public boolean isInterrupted() 
	{ 
		return interrupted; 
	} 

	public void setInterrupted(boolean interrupt) 
	{ 
		interrupted = interrupt; 
	} 

	// Memberfunktionen
	//-----------------

	public void run(JProgressBar progress, File file, JLabel labelPrices) 
	{ 
		int current = 0;

		status = progress; 
		status.setStringPainted(true);

		establishLineCount(file);
		setMinMax(0, lineCount); 

		BufferedReader br = null;
		
		try
		{
			try 
			{
				br = new BufferedReader(new FileReader(file));
			}
			catch(FileNotFoundException e) 
			{
				e.printStackTrace();
			}

			while(current < lineCount && !isInterrupted())
			{ 
				try
				{ 
					Thread.sleep(100); 
				} 
				catch(InterruptedException e)
				{ 
				} 
				current++;
				try 
				{
					vectorPrices.add(Float.parseFloat(br.readLine()));
					labelPrices.setText("Eingelesene Preise: " + current);
				}
				catch(NumberFormatException e)
				{
					e.printStackTrace();
				} 
				catch(IOException e) 
				{
					e.printStackTrace();
				}
				setValue(current); 
			}	
		}
		finally
		{
			if(br != null)try{br.close();}catch(IOException e){e.printStackTrace();}
		}

		status = null; 
	} 

	private void setMinMax( final int min, final int max ) 
	{ 
		try{ 
			SwingUtilities.invokeAndWait(new Runnable()
			{ 
				public void run()
				{ 
					status.setMinimum(min); 
					status.setValue(min); 
					status.setMaximum(max); 
				} 
			}); 
		} 
		catch(Exception e)
		{ 
		} 
	} 

	private void setValue(final int value) 
	{ 
		SwingUtilities.invokeLater(new Runnable()
		{ 
			public void run()
			{ 
				try
				{ 
					status.setValue(value+1); 
				} 
				catch(NullPointerException ex)
				{ 
				} 
			} 
		}); 
	} 

	public void establishLineCount(File file)
	{
		System.out.println("Reader - establishLineCount()");
		
		LineNumberReader line = null;
		System.out.println("Start");

		try
		{
			try 
			{
				line = new LineNumberReader(new FileReader(file));
			}
			catch(FileNotFoundException e) 
			{
				e.printStackTrace();
			} 

			try 
			{
				while(line.readLine()!=null)
				{ 
					lineCount = line.getLineNumber(); 
				}
			} 
			catch(IOException e) 
			{
				e.printStackTrace();
			}
		}
		finally
		{
			try{line.close();}catch(IOException e){e.printStackTrace();}
		}

		System.out.println("Ende");
	}

}
```

Nochmal sorry für den vielen Code. Hoffe mir kann jemand helfen.


----------



## Wildcard (6. Sep 2007)

1. Die GUI interessiert für dieses Problem doch wirklich niemand, warum postest du das?
2. Nicht dein ernst, oder? Du machst ein sleep(100) und wunderst dich das es lange dauert?
3. Was bitte soll der 2. Reader?
4. Der Rest ist auch alles andere als optimal, aber vielleicht reicht es dir schon wenn du 2) und 3) abstellst


----------



## spacegaier (6. Sep 2007)

1. Das mit GUI stimmt   
2. Das war die Hauptbremse in der Tat (hab nicht nachgeacht und des einfach vom Tutorial so drinn gelassen [Schwachsinn!!!])  
3. Welchen 2. Reader???
4. Könntest du mir bitte noch weitere Tipps geben, was nicht optimal ist. Ich bin noch nicht lange mit Java unterwegs (erst ca. 4 Wochen) und deshalb über jeden Hinweis froh!

Ansonsten schon mal danke soweit!!!


----------



## Wildcard (6. Sep 2007)

Ich meine den LineReader. Empfindest du es als sinnvoll eine große Datei zwei mal zu lesen?
vectorPrices.add(Float.parseFloat(br.readLine())); 
Was glaubst du wie entsetzlich oft (bei ein paar Millionen Einträgen) das interne Array umkopiert werden muss.

Wenn du wissen willst wie's richtig geht, benutz java.nio, aber dafür solltest du erst ein Tutorial oder Ähnliches lesen.


----------



## spacegaier (7. Sep 2007)

Den LineNumberReader brauche ich doch um die Anzahl der Einträge zu ermitteln, damit ich der ProgressBar den max-Wert geben kann. Oder geht das auch anders, oder habe ich dich missverstanden?

Soll ich dan den Vector durch einen buffer aus java.nio ersetzen? (Oder wo soll das java.nio angewendet werden?)


----------



## NTB (7. Sep 2007)

Also lieber ein bisschen zuviel Code gepostet, als viel zu wenig, finde ich. Es hätte ja auch sein können, dass Dein Zeitproblem mit der GUI irgendwie zusammenhängt. Dass Du da nun ein Sleep drin hattest.... äh 

Du kannst direkt von Anfang an den LineNumberReader benutzen. Der erbt sowieso vom BufferedReader. Also in Zeile 61 machst Du aussen einfach noch den LineNumberReader drumrum.

Ein Vector ist intern durch ein Array aufgebaut, dass initial eine größe von 10 hat. Wenn Du ein Element hinzufügst und in dem Array  nicht mehr genügend Platz ist, dann wird ein neues größeres Array erzeugt und das alte hineinkopiert. Das ist natürlich sehr zeitaufwändig. Daher kannst Du dem Vector auch eine initiale Kapazität mitgeben, die in Deinem Fall entsprechend hoch sein sollte. Davon abgesehen bietet sich glaube ich hier auch eine andere List (ArrayList?) besser an, als der Vector.


----------



## Saxony (7. Sep 2007)

Hiho,

hmm um die Anzahl der Datensätze zu bekommen, geht auch schonender.

Größe der Datei in Bytes / 4 = Anzahl der enthaltenen floats.
Geht natürlich nur wenn nur Floats drinne sind, bei mehreren Mio. Einträgen ist es aber dann egal ob die Progressbar bis 1834815 oder 1834975 geht. 

Oder man macht keine Datenabhängige Progressbar, sondern  eine die nur hin und herläuft (analog zu Lauflicht bei K.I.T.T von Knight Rider ) bis der Einleseprozess zu ende ist.

bye Saxony


----------



## spacegaier (7. Sep 2007)

@NTB: Um den BufferedReader noch den LineNumberReader drum oder meinst du ich soll den BufferedReader ersetzen? Was würde es denn bringen da noch einen LineNumberReader drum zu machen?

Wäre das Problem mit dem Vektor dann beseitigt, wenn ich erst die Zeilenanzahl ermittle und dann einen Vektor mit dieser Größe erstelle, denn dann müsste ja nix mehr intern umkopiert werden, oder?

Warum meinst, du dass eine ArrayList hier besser wäre? Wo liegt der Vorteil / Nachteil?

@Saxony: Ich möchte keine hin und her wandernde ProgressBar, denn der Nutzer soll einen Anhaltspunkt haben wie lange es noch geht (er kennt die Anzahl der Einträge in der Datei nicht zwingend).

Die Methode lenght() / 4 klapp net. Bei meinen vier Testfiles kommen immer falsche Werte raus:

Richtig / deine Methode
50 / 87
1 Mio. / 1,5 Mio.
2 Mio. / 2,5 Mio.
5 Mio. / 7,5 Mio.

Bei den letzten drei ist es immer die Hälfte mehr als drinn ist.

Der Aufbau der Datei ist so:

10.23
20.32
-5.23
10.32
-0.12

[Da wo jetzt ein '-' ist, ist in der Datei ein WhiteSpace!]

Spielen bei deiner Metzhode diese WhiteSpaces oder die Zeilenumbrüche eine Rolle?


----------



## sparrow (7. Sep 2007)

Na, ich zähle 6 Bytes je Zeile.
Ziffer,Ziffer,Punkt,Ziffer,Ziffer,Zeilenumbruch

Unter Windows noch eins mehr, aber das glaub ich nicht.

Du musst also nicht durch 4 sondern durch 6 teilen.


Da wärst aber auch selber mit einem einfachen 3-Satz drauf gekommen.


----------



## Saxony (7. Sep 2007)

Hiho,

yep wenn die floats nicht im Binärformat vorliegen, klappts auch nicht mit den 4 Byte. Das ist jo wohl klar 

Wo kommen die Files denne her ? Wenn du selber für die Erzeugung jener verantwortlich bist, dann speicher die bitte binär und net als Textdateien.

-> weniger Speicherplatz
-> nun kann man durch 4 teilen
-> man kann mit nem byte[4] die Datei auslesen
-> man spart sich Parsen über die Float Wrapper Klasse
-> gibts bestimmt noch ein zwei Vorteile mehr



bye Saxony

[edit]
Ähm was isn bei dir length() bei der Rechnung length() / 4 ?
Doch nicht etwa die Vector#length() ?

Ich hoffe das ist File#length(). 

Damit kann ich ohne einmal über die Einträge iteriert zu haben die Anzahl der Einträge ausgeben.
[/edit]


----------



## Guest (7. Sep 2007)

> Warum meinst, du dass eine ArrayList hier besser wäre? Wo liegt der Vorteil / Nachteil?



Also eine ArrayList bringt imo nichts, da sie intern ebenfalls Arrays nutzt, ich denke eine LinkedList könnte hilfreich sein, da neue Elemente einfach ans Ende angehangen werden und nichts umkopiert werden muß.


----------



## Murray (7. Sep 2007)

Anonymous hat gesagt.:
			
		

> > Warum meinst, du dass eine ArrayList hier besser wäre? Wo liegt der Vorteil / Nachteil?
> 
> 
> 
> Also eine ArrayList bringt imo nichts, da sie intern ebenfalls Arrays nutzt, ich denke eine LinkedList könnte hilfreich sein, da neue Elemente einfach ans Ende angehangen werden und nichts umkopiert werden muß.


Vector hat intern synchronisierte Zugriffsmethoden, ArrayList nicht. Wenn man nicht von mehreren Threads aus auf die gleiche Liste zugreift, braucht man diese Synchronisierung nicht und kann so etwas Zeit sparen.

Wichtiger war der Hinweis, dass ein Vector (und auch eine ArrayList) eine bestimmte initiale Kapazität hat und immer dann, wenn diese Kapazität überschritten wird, das interne Array neu anlegen und umkopieren muss. Aus diesen Grund sollte man dort, wo man die engültige Länge zumindest grob abschätzen kann, die initiale Kapazität auf diesen erwarteten Wert setzen. Das dürfte in deinem Fall eine Menge bringen.


----------



## spacegaier (7. Sep 2007)

Also, die Dateien sind nicht von mir -> bleiben halt so.

Mit den großen Dateien (mehr als eine Mio Einträge die ich nicht verändert habe, da funktioniert das System mit dem durch sechs teilen).

Ich habe mir aber eine von diesen großen Dateien genommen und auf 35 runtergekürzt und mit der klappt es nicht. Er kommt 40 aus.

Ich hänge die Datei mal an: Hier

Die Größe ist 245, warum? Sollte doch eigentlich 210 sein (6 Byte * 35 Zeilen).


----------



## sparrow (7. Sep 2007)

Das liegt am Zeilenumbruch.

Die Datei wie du sie hier beschreibst hat 6 Byte je Zeile und stammt nicht von einem Windows-System. (Zeilenumbruch ein Byte.)
Die angehängte Datei stammt von einem Windows-System (Zeilenumbruch ein Byte, Carriage Return ein Byte). Das sind dann 7 Byte pro Zeile.


Um sicher zu sein könntest du die erste Zeile darauf prüfen wie viele Steuerzeichen am Ende stehen.



Gruß
Sparrow


----------



## spacegaier (7. Sep 2007)

Das Prüfen klappt nicht  .

Mein Code:


```
String tmp = null;
			try 
			{
				tmp = br.readLine();
			} 
			catch(IOException e1) 
			{
				e1.printStackTrace();
			}
			
						
			if(tmp.endsWith("\r\n"))
			{
				System.out.println("Win");
				lineCount = (int)file.length() / 7;
			}
			else
			{
				System.out.println("Other OS");
				lineCount = (int)file.length() / 6;
			}
```

Wo ist mein (Denk-)Fehler?


----------



## Ariol (7. Sep 2007)

Vielleicht andersrum?

"\n\r"


----------



## spacegaier (7. Sep 2007)

Nö, die Reihenfolge steht ja auch so im Wikipedia-Eintrag.


----------



## sparrow (8. Sep 2007)

Versuch mal


```
String tmp = null;
         try
         {
            tmp = br.readLine();
         }
         catch(IOException e1)
         {
            e1.printStackTrace();
         }
         
                  
         if(tmp.endsWith("\r"))
         {
            System.out.println("Win");
            lineCount = (int)file.length() / 7;
         }
         else
         {
            System.out.println("Other OS");
            lineCount = (int)file.length() / 6;
         }
```

Ich bin mir gerade nicht sicher was wirklich das letzte Zeichen ist wenn man readLine() nimmt. Also ob die so gelesene Zeichenkette wirklich mit \n endet oder ob er die Zeichen zum Zeilenumbruch automatisch abschneidet.


Alternativ nimmst du dein Prüfung und liest zum Test die ersten 20 Zeichen der Datei ein.


----------



## spacegaier (9. Sep 2007)

Nein, dein Code geht leider auch nicht. 

readLine schneidet übrings alle LineSeparator ab, sowohl \r als auch \n.

Deinen letzten Punkt verstehe ich nicht. Könntest du das noch mal genauer erläutern.

Noch mal für alle: Ich muss wissen, wieviele Bytes eine Linie in meiner Datei hat. Problem ist, das Dateien von verschiedenen OS andere LineSeparator haben. Nun muss ich irgendwie herausfinden, welche LineSeparator meine Datei enthält.


----------



## sparrow (9. Sep 2007)

Du liest, unabhängig vom übernehmen der Lines in dein Programm, die erste 20 Bytes aus der Datei ein. Das sind, egal ob Windows oder *nix-Format der Datei, mindestens 2 Zeilen aus dem Programm.
Diese 20 Bytes prüfst du dann auf das Vorhandensein der Folge "\r\n"

Gruß
Sparrow


----------



## Saxony (9. Sep 2007)

sparrow hat gesagt.:
			
		

> Ich bin mir gerade nicht sicher was wirklich das letzte Zeichen ist wenn man readLine() nimmt. Also ob die so gelesene Zeichenkette wirklich mit \n endet oder ob er die Zeichen zum Zeilenumbruch automatisch abschneidet.



Hiho,

damit hast du recht.
readLine() liest bis zu einem Zeileendezeichen liefert aber als Ergebnis den Teil ohne diese Zeichen.

bye Saxony


----------



## spacegaier (9. Sep 2007)

Jetzt findet er raus, ob die Datei von einem WindowsSystem ist oder nicht, aber die Zeileenanzahl bei den Daten des WindowSystems ist immer eins zu niedrig, warum?


```
char tmp[] = new char[bytesReadForLinecount];
			try 
			{
				br.read(tmp, 0, bytesReadForLinecount-1);
			} 
			catch(IOException e1) 
			{
				e1.printStackTrace();
			}
			
			String tmp_2 = new String(tmp); 	
			if(tmp_2.contains("\r\n"))
			{
				System.out.println("Win");
				lineCount = (int)file.length() / 7;
			}
			else
			{
				System.out.println("Other OS");
				lineCount = (int)file.length() / 6;
			}
```


----------



## Saxony (10. Sep 2007)

Hiho,

weil die letzte Zeile in der Datei vielleicht kein "\r\n" enthält.

bye Saxony


----------



## spacegaier (12. Sep 2007)

Okay, daran könnt es liegen. Danke!


----------

