Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια
σε

 

Αρχική σελίδα Ιστολόγια Συζητήσεις Εκθέσεις Φωτογραφιών Αρχειοθήκες

Προβλημα με ελληνικά σε txt αρχείο

Îåêßíçóå áðü ôï ìÝëïò neoklis. Τελευταία δημοσίευση από το μέλος Παναγιώτης Καναβός στις 05-10-2011, 18:08. Υπάρχουν 7 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  30-09-2011, 08:54 67582

    Προβλημα με ελληνικά σε txt αρχείο

    Καλημέρα,

     

    Σε ένα windows form έχω μερικά textboxes και ένα datagridview. Τα textboxes με το πάτημα ενός button αποθηκεύονται σε txt αρχείο μέσω ενός insert into statement χρησιμοποιώντας Jet.OLEDB.4 provider και στην συνέχεια το txt φορτώνεται στο datagridview. Το πρόβλημα με τα ελληνικά εμφανίζεται όταν πάω να σβήσω ένα row από το datagridview. Επειδή ο provider που χρησιμοποιώ δεν υποστηρίζει (δεν ξέρω αν μπορώ να χρησιμοποιήσω κάποιον άλλον, αλλά από ότι έψαξα μάλλον όχι) update και delete statements για να σβήσω μία γραμμή από το txt, πρέπει να πρώτα  να διαβάσω όλο το datagridview να το μεταφέρω σε ένα array εξαιρώντας το row προς διαγραφή και στην συνέχεια να γράψω το array στο txt αρχείο. Και εδώ έρχεται το πρόβλημα καθώς στην

    επανεγγραφή του txt ότι ελληνικό υπάρχει το μετατρέπει σε κινέζικα.

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
    Private Sub DG_KeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles DG.KeyDown
    
            If e.KeyValue = 46 Then
    
                Me.Cursor = Cursors.WaitCursor
    
                For Each selectedrow As DataGridViewRow In DG.SelectedRows
                    If DG.SelectedRows.Count > 0 Then
    
                        Dim i As Integer
                        i = selectedrow.Index
                        Dim arrlines() As String = File.ReadAllLines("c:\Hlc\nonet.txt")
                        Dim DataLines As New System.Collections.Specialized.StringCollection
                        Dim CurrentLine As String
    
                        For Each CurrentLine In arrlines
                            If InStr(CurrentLine, DG.Rows(i).Cells("ID").Value) <= 0 Then
                                DataLines.Add(CurrentLine)
                            End If
                        Next
    
                        Dim WriteArray(DataLines.Count - 1) As String
                        DataLines.CopyTo(WriteArray, 0)
                        File.WriteAllLines("c:\Hlc\nonet.txt", WriteArray, Encoding.UTF8)
                    End If
    
                    DG.Rows.Remove(selectedrow)
                Next
    
                Me.Cursor = Cursors.Default
    
            End If
        End Sub

    Αν και στην γραμμή 24 στο File.WriteAllLines χρησιμοποιώ utf8 δεν εμφανίζεται το επιθυμητό αποτέλεσμα.

     

    Ευχαριστώ

     


    Dionisis
  •  30-09-2011, 10:29 67584 σε απάντηση της 67582

    Απ: Προβλημα με ελληνικά σε txt αρχείο

    Ο κώδικας σου έχει αρκετά προβλήματα και δεν έχουν να κάνουν με τα ελληνικά. 
    1.  Η αποθήκευση σε txt μέσω OLEDB είναι το λιγότερο περίεργη. Αν δεν έχεις φροντίσει σε αυτό το σημείο να ορίσεις ότι τα πεδία κειμένου είναι τύπου Unicode, θα αποθηκευθούν σε ASCII.  Για να ορίσεις το encoding και το format του αρχείου πρέπει να δημιουργήσεις ένα αρχείο Schema.ini στον φάκελο στον οποίο αποθηκεύονται τα αρχεία. Η μορφή του schema.ini περιγράφεται εδώ.
      Ο OLEDB driver δεν χρησιμοποιείται για τη δημιουργία text αρχείων, εκτός και αν θέλεις να δουλέψεις με CSV αρχεία. Ακόμα και εκεί όμως χρησιμοποιείται συνήθως για ανάγνωση, όχι για δημιουργία.
    2. Tο default encoding στο .NET όταν δουλεύεις με αρχεία είναι το UTF8 οπότε δεν υπάρχει λόγος να το προσθέσεις. Αν έχεις πρόβλημα είναι επειδή το αρχείο σου έχει ήδη χαλάσει.
    3. Ο κώδικας σου διαβάζει γραμμές από το "χαλασμένο" αρχείο και τις αποθηκεύει ΩΣ ΕΧΟΥΝ σε ένα νέο. Προφανώς, αν διαβάσει κινέζικα, θα γράψει και κινέζικα.
    4. H File.WriteAllLines δέχεται άνετα και IEnumerable<string> οπότε δεν υπάρχει λόγος να αντιγράφεις τη λίστα των string σε array, απλά πέρνα τη λίστα. Προφανώς αυτό δεν θα δουλέψει με ένα StringCollection, αλλά δεν υπάρχει κανένας απολύτως λόγος να χρησιμοποιείς StringCollection. Ένα List(Of String) αρκεί. Το StringCollection είναι απομεινάρι του .NET 1.1 και χρησιμοποιείται μόνο για  λόγους συμβατότητας με παλιά API.
    5. Η Instr είναι απομεινάρι της VB6 και υπάρχει μόνο για λόγους συμβατότητας. Αντί γι αυτή χρησιμοποιήσε την String.Contains. To .ΝΕΤ έχει πολύ περισσότερες, ισχυρότερες, ευκολότερες και γρηγορότερες συναρτήσεις για string manipulation (ή οτιδήποτε άλλο) από την αρχαία VB6. 
    6. Η χρήση της InStr ή ακόμα και της String.Contains μπορεί να οδηγήσει σε λανθασμένα αποτελέσματα καθώς θα σου επιστρέψει και γραμμές που περιέχουν το string που αναζητάς σε άσχετες τιμές, π.χ. η αναζήτηση του 12 θα επιστρέψει και το 123. Καλύτερα να χρησιμοποιήσεις κάποιο RegEx που θα αναγνωρίσει και θα επιστρέψει μόνο τις τιμές που θέλεις. 
    7. Διαβάζεις ξανά και ξανά το ίδιο αρχείο για να ψάξεις κάθε γραμμή μήπως περιέχει τις τιμές που θέλεις. Κάνε το αντίθετο, μάζεψε σε μία λίστα τις τιμές που θέλεις και μετά ψάξε το αρχείο μία και καλή
    8. Η ανάγνωση όλων των γραμμών στη μνήμη πριν τις επεξεργαστείς σπαταλάει μνήμη χωρίς λόγο. Αν τα αρχεία σου είναι μεγάλα αυτό θα έχει επίπτωση στην απόδοση της εφαρμογής. Θα μπορούσες να χρησιμοποιήσεις την 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
  •  30-09-2011, 11:37 67591 σε απάντηση της 67584

    Απ: Προβλημα με ελληνικά σε txt αρχείο

    Παναγιώτη πολύ ενδιαφέροντα όλα αυτά και σε ευχαριστώ για το κόπο που έκανες για να μου τα εξηγήσεις. Θέλησα να πειραματιστώ με Linq και αντέγραψα το τελευταίο κομμάτι κώδικα έτσι ώστε να δω πως δουλεύει. Έκανα import το namespace system.linq και μου εμφανίζει το εξης error στην γραμμή 2..

    Error 13 Expression of type 'Object' is not queryable. Make sure you are not missing an assembly reference and/or namespace import for the LINQ provider. 
    C:\Users\werer\Desktop\Zygoi 2010\Zygoi\Form1.vb 1024 42 Zygoi


    1
    2
    3
    4
     
    Dim lines = File.ReadAllLines("c:\Hlc\nonet.txt")
            Dim selectedLines = From line In lines
                    Where keys.Any(Function(key) line.Contains(key))
                    Select line


    Dionisis
  •  30-09-2011, 12:11 67592 σε απάντηση της 67591

    Απ: Προβλημα με ελληνικά σε txt αρχείο

    Ο κώδικας κάνει compile και σε .NET 3.5 (VS 2008) και σε .NET 4.0 (VS 2010) ενώ σκάει σε 3.0 (VS 2005). To LINQ είναι feature του .NET 3.5 και άνω. Ποιά έκδοση χρησιμοποιείς?
    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  30-09-2011, 12:25 67593 σε απάντηση της 67592

    Απ: Προβλημα με ελληνικά σε txt αρχείο

    Όταν δημιούργησα την συγκεκριμένη ενότητα χρησιμοποιούσα framework 2.0, στην συνέχεια διάβασα ότι για Linq θα πρέπει όπως αναφέρεις να χρησμοποιήσω 3.5 και πάνω. Πήγα στο Advanced Complie Options και το άλλαξα από 2 σε 4. Πρέπει να αλλάξω και τίποτα άλλο...;


    Dionisis
  •  30-09-2011, 13:16 67595 σε απάντηση της 67593

    Απ: Προβλημα με ελληνικά σε txt αρχείο

    Να προσθέσω ότι έχω VS2010
    Dionisis
  •  05-10-2011, 14:49 67634 σε απάντηση της 67595

    Απ: Προβλημα με ελληνικά σε txt αρχείο

    Έχω δοκιμάσει 2 διαφορετικούς τρόπους εισαγωγής εγγραφών στο txt αρχείο.

     

    1.       Μέσω oledb  όπου τα ελληνικά εμφανίζονται σωστά στο txt αρχείο, σωστά στο datagridview, σωστά με console.writeline και λάθος όταν διαβάζω το αρχείο με List(of string).

     

    2.       Με την Streamwriter οπου τα ελληνικά δεν εμφανίζονται σωστά στο txt, δεν εμφανίζονται σωστά στο datagridview, το ίδιο και το αυτό με console.writeline  και εμφανίζονται σωστά μόνο στο List(of string).

     

    Να σημειώσω ότι για τις εισαγωγές με OLEDB χρησιμοποιώ ήδη schema.

     

     

    Confused


    Dionisis
  •  05-10-2011, 18:08 67636 σε απάντηση της 67634

    Απ: Προβλημα με ελληνικά σε txt αρχείο

    Και ? Τί codepage έχεις ορίσει στο schema? Το ότι εμφανίζονται σωστά στο console ΔΕΝ ΣΗΜΑΙΝΕΙ ΟΤΙ ΕΙΝΑΙ UNICODE. Επιπλέον το List(string) ΔΕΝ ΕΙΝΑΙ ΤΡΟΠΟΣ ΑΝΑΓΝΩΣΗΣ. Είναι το που τα αποθηκεύεις ΑΦΟΥ τα διαβάσεις. Πως τα διαβάζεις λοιπόν? Αν τα strings που βλέπεις είναι λάθος σημαίνει ότι το αρχείο ΔΕΝ ΕΙΝΑΙ UNICODE. Το .ΝΕΤ χρησιμοποιεί παντού unicode. Η κλάση string είναι Unicode. Πρέπει να κάνεις μετατροπή με κώδικα για να πάρεις κείμενο σε άλλο codepage. 

    Αλήθεια, ΠΩΣ γράφεις στο αρχείο? Αν το αρχείο ΔΕΝ είναι unicode, λογικό είναι ότι δεν θα μπορέσεις να το διαβάσεις σωστά ως unicode. Θα πρέπει να ορίσεις το codepage του αρχείου στον constructor της StreamReader

    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems