# CSV auslesen und Inhalt vergleichen



## Damn (22. Jan 2012)

Hallo, 
ich versuche gerade:

- zwei csv Dateien einzulesen ( A hat 2 Spalten und 1 Mio Zeilen und B 2 Spalte und 1000 Zeilen)
z.b: Nr., Artikel                                                 B) Nr., Artikel
        01,Spiel|Konsole|playstation                           01, Spiel
        02,SpielKonsole|wii                                         02,playstation                    

- die Artikelname in A mit den Artikelnamen in B zu vergleichen
- Für jede Zeile (A) aufzuzählen, wieviel Wörter in Zeilen B vorkommen

zb.: 

  01,Spiel|Konsole|playstation              2 Wörter 
  02,SpielKonsole|wii                             1 Wort 


- Das Ergebnis als CSV zu speichern


Ich habe ein Standardprogramm geschrieben, aber habe mehrere Problem:


```
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
 
public class Test 
{
	//static int zeileAnzahl= 0;
    public static void main(String[] args) throws IOException 
    {
    	BufferedReader reader = new BufferedReader(new FileReader(new File("E:/Persönlich/A.csv")));
    	//BufferedReader reader = new BufferedReader(new FileReader(new File("E:/Persönlich/B.csv")));
        String line;
        String[] temp;
        ArrayList<String[]> strings = new ArrayList<String[]>();
        while((line = reader.readLine()) != null)
        {
            strings.add(line.split(","));
           // System.out.println(strings);
            
           
        }
        

        for(int i = 0; i < strings.size(); i++) 
        {
            String[] arr = (String[]) strings.get(i);
         
            //get array of one line
            for(int j = 0; j < arr.length; j++)
            {
                
                System.out.println(arr[j]);
                //zeileAnzahl++;
            }  
        }
       // System.out.println(zeileAnzahl);
    }
}
```


Die großere Datei wird nicht vom Anfang  eingelesen! Ich habe  mit der kleineren Datei (B) versucht und die wird komplett eingelesen.

Kann jemand mir helfen


----------



## Gast2 (22. Jan 2012)

Musst du die Datei selbst parsen oder kannst du nen fertigen CSV Parser nutzen? Dann hätte ich ne schöne kompakte Lösung auf Lager.

Falls du das selbst parsen musst dann solltest du so vorgehen:
Zuerst Datei B komplett einlesen in eine Liste.
Danach Zeile für Zeile Datei A auslesen und für jeden Eintrag zählen wieoft der String in Liste B vorkommt. Das Ergebnis schreibst du direkt nach Datei C.


----------



## Damn (22. Jan 2012)

Ich darf auch einen fertigen CSV Parser nutzen.
Welche Lösung meinst du ?

Ich hatte OstermillerUtils Java Utilities - CSVParser.java Source Code zuvor versucht, aber ich könnte die CSV datei nicht lesen.


----------



## Fab1 (22. Jan 2012)

schau mal in die Signatur von EikeB denke, dass er das damit gemeint hat


----------



## Damn (22. Jan 2012)

```
Reader reader = new FileReader("A.csv"); 
    	CSVReader<String[]> csvPersonReader = CSVReaderBuilder.newDefaultReader(reader);
    	List<String[]> persons = csvPersonReader.readAll();
```

Ich bekomme Fehler:

CSVReaderBuilder  cannot be resolved.


----------



## Gast2 (22. Jan 2012)

Hi,
ich habe gestern schon das Wiki für die neue Version angepasst, da hat sich nen bisschen was getan. Lad dir bitte mal die Version 1.1.0 runter. Die findest du jetzt im Downloadbereich.

In der Zwischenzeit baue ich dir mal nen kleines Beispiel fertig


----------



## Gast2 (22. Jan 2012)

Hab dir mal nen kleines Beispiel gebastelt. Bin mir aber nicht so sicher ob ich das Zählen der Artikel richtig verstanden habe, ich glaube du meinst da was anderes  Aber schaus dir mal an (es sieht komplizierter aus als es ist ^^), wenn du noch Fragen/Probleme damit hast, dann sag bescheid.


```
public class Main {
	public static void main(String[] args) throws IOException {
		List<Article> articles = readArticleList("/B.csv");

		// read list A and write qun
		CSVReader<Article> articleReader = buildCSVReader("/A.csv");
		CSVWriter<ArticleQuantity> articleQuantityWriter = buildCSVWriter("/C.csv");

		for (Article article : articleReader) {
			ArticleQuantity articleQuantity = countArticle(articles, article);
			articleQuantityWriter.write(articleQuantity);
			articleQuantityWriter.flush();
		}

		articleQuantityWriter.close();
		articleReader.close();
	}

	private static ArticleQuantity countArticle(List<Article> articles, Article art) {
		int count = 0;
		for (Article article : articles) {
			if (article.equals(art)) {
				count++;
			}
		}

		return new ArticleQuantity(art, count);
	}

	private static CSVWriter<ArticleQuantity> buildCSVWriter(String file) throws IOException {
		String userHome = System.getProperty("user.home");
		Writer out = new FileWriter(userHome + file);
		CSVWriter<ArticleQuantity> csvWriter = new CSVWriterBuilder<ArticleQuantity>(out)
				.strategy(CSVStrategy.UK_DEFAULT).entryConverter(new ArticleQuantityEntryConverter()).build();
		return csvWriter;
	}

	private static CSVReader<Article> buildCSVReader(String file) {
		Reader csvFile = new InputStreamReader(Main.class.getResourceAsStream(file));
		CSVReader<Article> csvArticleReader = new CSVReaderBuilder<Article>(csvFile).strategy(CSVStrategy.UK_DEFAULT)
				.entryParser(new ArticleEntryParser()).build();
		return csvArticleReader;
	}

	private static List<Article> readArticleList(String file) throws IOException {
		CSVReader<Article> csvArticleReader = buildCSVReader(file);
		List<Article> articles = csvArticleReader.readAll();
		csvArticleReader.close();

		return articles;
	}

	private static class ArticleEntryParser implements CSVEntryParser<Article> {
		@Override
		public Article parseEntry(String... data) {
			if (data.length != 2) {
				throw new IllegalArgumentException("data is not a valid article");
			}
			return new Article(data[1]);
		}
	}

	private static class ArticleQuantityEntryConverter implements CSVEntryConverter<ArticleQuantity> {
		@Override
		public String[] convertEntry(ArticleQuantity e) {
			return new String[] { e.getArticle().getName(), String.valueOf(e.getQuantity()) };
		}
	}
}
```


----------



## Damn (22. Jan 2012)

Ich habe das Projekt von EikeB benutzt und angepasst.
Leider habe ich immer noch Problem:

Exception in thread "main" java.lang.NullPointerException
	at java.io.Reader.<init>(Unknown Source)
	at java.io.InputStreamReader.<init>(Unknown Source)
	at de.eikeb.jcsv.demo.Main.readCategories(Main.java:70)
	at de.eikeb.jcsv.demo.Main.main(Main.java:23)




CSVEntryConverter cannot be resolved to a type	line 105	Java Problem
CSVEntryParser cannot be resolved to a type	line 80	Java Problem
CSVEntryParser cannot be resolved to a type	line 93	Java Problem

Kann jemand mit dabei helfen?


```
package de.eikeb.jcsv.demo;

import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.Writer;
import java.util.Arrays;
import java.util.List;

import de.eikeb.jcsv.CSVStrategy;
import de.eikeb.jcsv.reader.CSVEntryParser;
import de.eikeb.jcsv.reader.CSVReader;
import de.eikeb.jcsv.reader.internal.CSVReaderBuilder;
import de.eikeb.jcsv.writer.CSVEntryConverter;
import de.eikeb.jcsv.writer.CSVWriter;
import de.eikeb.jcsv.writer.internal.CSVWriterBuilder;

public class Main {
	private static CSVStrategy strategy = new CSVStrategy(';', '"', '#', true, true);

	public static void main(String[] args) throws IOException {
		List<Category> categories = readCategories("/B.csv");

		// read list A and write quantities
		CSVReader<CategoryList> categoryListReader = buildCategoryListReader("/A.csv");
		CSVWriter<CategoryQuantity> categoryQuantityWriter = buildCSVWriter("/C.csv");

		for (CategoryList cl : categoryListReader) {
			CategoryQuantity categoryQuantity = countCategories(categories, cl);
			categoryQuantityWriter.write(categoryQuantity);
			categoryQuantityWriter.flush();

		}

		categoryQuantityWriter.close();
		categoryListReader.close();
	}

	private static CategoryQuantity countCategories(List<Category> categories, CategoryList cl) {
		int count = 0;
		for (String category : cl.getCategories()) {
			for (Category cat : categories)  {
				if (cat.getName().equalsIgnoreCase(category)) {
					count++;
					break;
				}
			}
		}

		return new CategoryQuantity(cl.getId(), count);
	}

	private static CSVWriter<CategoryQuantity> buildCSVWriter(String file) throws IOException {
		String userHome = System.getProperty("user.home");
		Writer out = new FileWriter(userHome + file);
		CSVWriter<CategoryQuantity> csvWriter = new CSVWriterBuilder<CategoryQuantity>(out).strategy(strategy)
				.entryConverter(new CategoryQuantityEntryConverter()).build();
		return csvWriter;
	}

	private static CSVReader<CategoryList> buildCategoryListReader(String file) {
		Reader csvFile = new InputStreamReader(Main.class.getResourceAsStream(file));
		CSVReader<CategoryList> csvReader = new CSVReaderBuilder<CategoryList>(csvFile).strategy(strategy)
				.entryParser(new CategoryListEntryParser()).build();
		return csvReader;
	}

	private static List<Category> readCategories(String file) throws IOException {
		Reader csvFile = new InputStreamReader(Main.class.getResourceAsStream(file));
		CSVReader<Category> csvReader = new CSVReaderBuilder<Category>(csvFile).strategy(strategy)
				.entryParser(new CategoryEntryParser()).build();

		List<Category> articles = csvReader.readAll();
		csvReader.close();

		return articles;
	}

	private static class CategoryEntryParser implements CSVEntryParser<Category> {
		@Override
		public Category parseEntry(String... data) {
			if (data.length != 2) {
				throw new IllegalArgumentException("data is not a valid article");
			}
			int id = Integer.parseInt(data[0]);
			String name = data[1];

			return new Category(id, name);
		}
	}

	private static class CategoryListEntryParser implements CSVEntryParser<CategoryList> {
		@Override
		public CategoryList parseEntry(String... data) {
			if (data.length != 2) {
				throw new IllegalArgumentException("data is not a valid article");
			}
			int id = Integer.parseInt(data[0]);
			List<String> categories = Arrays.asList(data[1].split("\\||\\s/\\s"));
			return new CategoryList(id, categories);
		}
	}

	private static class CategoryQuantityEntryConverter implements CSVEntryConverter<CategoryQuantity> {
		@Override
		public String[] convertEntry(CategoryQuantity e) {
			return new String[] { String.valueOf(e.getId()), String.valueOf(e.getQuantity()) };
		}
	}
}
```


----------



## Gast2 (22. Jan 2012)

Wie gesagt:



> Exception in thread "main" java.lang.NullPointerException
> at java.io.Reader.<init>(Unknown Source)
> at java.io.InputStreamReader.<init>(Unknown Source)
> at de.eikeb.jcsv.demo.Main.readCategories(Main.java:70)
> at de.eikeb.jcsv.demo.Main.main(Main.java:23)


In meinem Beispiel lade ich die Dateien (der einfachheit halber) als Ressource, wenn du das auch so machen willst, dann musst du deine Dateien in nen source ordner legen. Wenn du die Dateien von deiner Festplatte laden willst dann mach das so:

```
Reader reader = new FileReader(derPfadZuDeinerDatei);
```


```
CSVEntryConverter cannot be resolved to a type line 105 Java Problem
CSVEntryParser cannot be resolved to a type line 80 Java Problem
CSVEntryParser cannot be resolved to a type line 93 Java Problem
```
Da hast du die Library falsch eingebunden, der Fehler tritt bei mir nicht auf.


----------



## Damn (22. Jan 2012)

Hi EikeB,

tausend Dank.

Jetzt läuft es. Ich werde jetzt das Programm erweitern.


----------



## Damn (23. Jan 2012)

Hi zusammen,


mit meinem Programm kann ich jetzt die Wörter in der A.CSV-Datei mit dem Wörtern in der B.CSV-Datei vergleichen, die aufzählen und die gleichen Wörter (als Liste)  ausgeben.

z.B:Baby,|Kids| & |Teens| Spielwaren | & | Schulbedarf | Kinderfahrzeuge |Spielzeug |Autos futscher | Autos	                            3 [Schulbedarf, Kinderfahrzeuge, Autos]

Bis jetzt vergleiche ich die Kategorien wie:



```
private static CategoryQuantity countCategories(List<Category> categories, CategoryList cl) {
		int count = 0;
		List<String> cat1 = new ArrayList<String>();
		for (String category : cl.getCategories()) {
			for (Category cat : categories)  {
				if (cat.getName().equalsIgnoreCase(category)) {
					cat1.add(cat.getName());
					count++;
					break;
				}
			}
		}
```


Das Problem ist, dass ich nur die identischen Wärter vergleiche.
Ich möchte gern auch Teilwörter vergleichen.

Z.b:  Baby (in A.csv) soll auch gelich Babyliegen (in B.csv) sein.

Also, ich möchte auch Teilwörter vergleichen.

Kann einer mir helfen?


----------



## Gast2 (23. Jan 2012)

Da würd ich dir mal die API ans Herz legen wollen:
String (Java Platform SE 7 )

equalsIgnoreCase prüft ob die Wörter gleich sind (Groß-/Kleinschreibung wird ignoriert). Wenn du prüfen ob es sich um nen Teilwort handelt kannst du contains nutzen.


----------



## Damn (24. Jan 2012)

@EikeB, danke dir für deine Empfehlung in Bezug auf contains.


Ich habe meinen code erweitert, aber ich komme immer noch nicht auf das gewünschte Ergebnis. 
Als Ergebnis möchte ich bekommen:

id,Kategorie,gefundene Kategorie, Anzahl
01,Textil|Sport|Sporttextilien|Kinder|Teile|Kindersportbekleidung|neutral,Textil|Sport|Sporttextilien,3|8,2


Ich habe 2 Problem.

1. ich speiche das gefundene Wort in eine Liste, aber ich will das gefundene Wort nur einmal angezeigt wird.
Gezeigt wird:
[Textil, Sport, Sport, Sport, Sport, Sport, Sport, Sport, Sport, Sporttextilien,Sporttextilien]

2. Ich möchte die Anzahl der gefundenen Wörter darstellen wie o.g.
Zurzeit zähle ich falsch, in dem ich immer addiere und in die Liste speichern.

Hat jemand eine Idee, wie ich die Probleme lösen kann?



```
private static CategoryQuantity countCategories(List<Category> categories, CategoryList cl) {
			List<Integer> count = new ArrayList<Integer>();
			
			List<String> name = new ArrayList<String>();
				for (String category : cl.getCategories()) {
					int number= 0;
					for (Category cat : categories) {
						if (cat.getName().contains(category)) {
							name.add(category.toString());
							number++;
							count.add(number);



						}
					}
				}
```


----------



## Damn (26. Jan 2012)

Hi zusammen, 

jetzt benutze ich ein MAP statt die beiden Liste (zuvor). Außerdem benutze ich noch ein Set zum kontrollieren.

Aber jetzt wie vergleiche ich sinnvoll die beiden Kategorien?




```
private static CategoryQuantity countCategories(List<Category> categories, CategoryList cl) {        
        Map<String,Integer> result = new TreeMap<String,Integer>();        
        Set<String> control = new HashSet<String>();      
        List<String> categories1 = cl.getCategories();      
            
        for (String category : categories1) {      
                            
            if(control.contains(category))    
                continue;      
                  
            control.add(category);      
            if(categories1.contains(category))
            		{  
                result.put(category, Collections.frequency(categories1, category));     
            }            
        }        
        return new CategoryQuantity(cl.getId(), cl.getCategories(), result);  

    }
```


----------



## Damn (26. Jan 2012)

Ich habe eine neue for schleife, aber das Programm läuf und läuft, nach 50 Min. habe ich abgebrochen und die vorläufigen Ergebnise angeguckt und gesehen, dass das prrogramm nicht funktioniert.

Idee ?


```
private static CategoryQuantity countCategories(List<Category> categories, CategoryList cl) {          
        Map<String,Integer> result = new TreeMap<String,Integer>();          
        Set<String> control = new HashSet<String>();        
        List<String> categories1 = cl.getCategories();        
          
          
      for (Category cat : categories) {       
        for (String category : categories1) {        
            if(cat.getName().contains(category))  
            if(control.contains(category))      
                continue;        
                    
            control.add(category);        
            if(categories1.contains(category))  
                    {    
                result.put(category, Collections.frequency(categories1, category));       
            }              
        }    
      }  
          
        return new CategoryQuantity(cl.getId(), cl.getCategories(), result);    
  
    }
```


----------

