Ο κώδικας σου έχει αρκετά προβλήματα και δεν έχουν να κάνουν με τα ελληνικά.
- Η αποθήκευση σε txt μέσω OLEDB είναι το λιγότερο περίεργη. Αν δεν έχεις φροντίσει σε αυτό το σημείο να ορίσεις ότι τα πεδία κειμένου είναι τύπου Unicode, θα αποθηκευθούν σε ASCII. Για να ορίσεις το encoding και το format του αρχείου πρέπει να δημιουργήσεις ένα αρχείο Schema.ini στον φάκελο στον οποίο αποθηκεύονται τα αρχεία. Η μορφή του schema.ini περιγράφεται εδώ.
Ο OLEDB driver δεν χρησιμοποιείται για τη δημιουργία text αρχείων, εκτός και αν θέλεις να δουλέψεις με CSV αρχεία. Ακόμα και εκεί όμως χρησιμοποιείται συνήθως για ανάγνωση, όχι για δημιουργία. - Tο default encoding στο .NET όταν δουλεύεις με αρχεία είναι το UTF8 οπότε δεν υπάρχει λόγος να το προσθέσεις. Αν έχεις πρόβλημα είναι επειδή το αρχείο σου έχει ήδη χαλάσει.
- Ο κώδικας σου διαβάζει γραμμές από το "χαλασμένο" αρχείο και τις αποθηκεύει ΩΣ ΕΧΟΥΝ σε ένα νέο. Προφανώς, αν διαβάσει κινέζικα, θα γράψει και κινέζικα.
- H File.WriteAllLines δέχεται άνετα και IEnumerable<string> οπότε δεν υπάρχει λόγος να αντιγράφεις τη λίστα των string σε array, απλά πέρνα τη λίστα. Προφανώς αυτό δεν θα δουλέψει με ένα StringCollection, αλλά δεν υπάρχει κανένας απολύτως λόγος να χρησιμοποιείς StringCollection. Ένα List(Of String) αρκεί. Το StringCollection είναι απομεινάρι του .NET 1.1 και χρησιμοποιείται μόνο για λόγους συμβατότητας με παλιά API.
- Η Instr είναι απομεινάρι της VB6 και υπάρχει μόνο για λόγους συμβατότητας. Αντί γι αυτή χρησιμοποιήσε την String.Contains. To .ΝΕΤ έχει πολύ περισσότερες, ισχυρότερες, ευκολότερες και γρηγορότερες συναρτήσεις για string manipulation (ή οτιδήποτε άλλο) από την αρχαία VB6.
- Η χρήση της InStr ή ακόμα και της String.Contains μπορεί να οδηγήσει σε λανθασμένα αποτελέσματα καθώς θα σου επιστρέψει και γραμμές που περιέχουν το string που αναζητάς σε άσχετες τιμές, π.χ. η αναζήτηση του 12 θα επιστρέψει και το 123. Καλύτερα να χρησιμοποιήσεις κάποιο RegEx που θα αναγνωρίσει και θα επιστρέψει μόνο τις τιμές που θέλεις.
- Διαβάζεις ξανά και ξανά το ίδιο αρχείο για να ψάξεις κάθε γραμμή μήπως περιέχει τις τιμές που θέλεις. Κάνε το αντίθετο, μάζεψε σε μία λίστα τις τιμές που θέλεις και μετά ψάξε το αρχείο μία και καλή
- Η ανάγνωση όλων των γραμμών στη μνήμη πριν τις επεξεργαστείς σπαταλάει μνήμη χωρίς λόγο. Αν τα αρχεία σου είναι μεγάλα αυτό θα έχει επίπτωση στην απόδοση της εφαρμογής. Θα μπορούσες να χρησιμοποιήσεις την StreamReader.ReadLine για να διαβάσεις μία-μία τις γραμμές και να τις ελέγξεις, χωρίς να φορτώσεις τα πάντα στη μήνη, όπως παρακάτω:
Dim keys = {"1", "2", "5"}
Using reader As StreamReader = New StreamReader("somefile.txt")
Dim line = reader.ReadLine()
If keys.Any(Function(key) line.Contains(key)) Then
....
End If
End Using
Εδώ βλέπεις και μερικά ακόμα κόλπα του .NET όπως την Using η οποία φροντίζει να κλείσει ένα reader, connection, stream κλπ ακόμα και αν υπάρξει exception και την
Any, ένα από τα functions του LINQ, που εκτελεί ένα function (εδώ το line.Contains(key) ) επάνω σε κάθε αντικείμενο μίας λίστας ή query και επιστρέφει TRUE μόλις βρει έστω και μία τιμή.
Επιπλέον, αντί να διαβάζεις όλες τις γραμμές και να ψάχνεις κάποια συγκεκριμένη τιμή στο loop, μπορείς είτε να χρησιμοποιήσεις τον OLEDB driver για να ανακτήσεις με τη μία όλες τις γραμμές που θέλεις, ή να χρησιμοποιήσεις LINQ όπως παρακάτω (φορτώνει όλες τις γραμμές, αλλά είναι πολύ πιο καθαρό):
Dim keys = From row As DataGridViewRow In DG.SelectedRows
Select row.Cells("ID").Value
Dim lines = File.ReadAllLines("somefile.txt")
Dim selectedLines = From line In lines
Where keys.Any(Function(key) line.Contains(key))
Select line
File.WriteAllLines("somefile.txt", selectedLines)
Μπορείς δηλαδή να κάνεις αναζητήσεις σε μορφή SQL και να έχεις πολύ πιο καθαρό και ευανάγνωστο κώδικα. Το LINQ query δείχνει αμέσως τί θέλεις να κάνεις ενώ ο αρχικός κώδικας ήθελε αρκετό διάβασμα για να καταλάβεις τί γίνεται
Καλό θα ήταν (μάλλον απαραίτητο) να εγκαταλείψεις εντελώς τις κακές συνήθεις της VB6 και να εξοικειωθείς με τον τρόπο που δουλεύει το .NET καθώς ο κώδικας σου θα γίνει πολύ ευκολότερος και γρηγορότερος. Η διαφορά μεταξύ VB6 και VB.NET είναι σχεδόν τόσο μεγάλη όσο και μεταξύ VB6 και C#. Η ομοιότητα στη σύνταξη είναι παγίδα καθώς διευκολύνει τη χρήση παλιών κακών συνηθειών στον κώδικα.
Παναγιώτης Καναβός, Freelancer
Twitter: http://www.twitter.com/pkanavos