CSV dosyasındaki virgüllerle ilgilenme


472

Oluşturulan, daha sonra müşterilerimiz tarafından yüklenen ve bir şirket adı gibi bir değerde virgül olabilen bir csv dosyasının nasıl işleneceğine dair öneriler arıyorum.

İncelediğimiz bazı fikirler şunlardır: alıntılanmış Tanımlayıcılar (değer "," değerler "," vb.) Veya bir | virgül yerine. En büyük sorun, bunu kolaylaştırmamız gerektiğidir, yoksa müşteri bunu yapmaz.


Müşteri yazıyor ve yüklüyor
Bob The Janitor

1
İşte csv dosyasında commos içinde yönetmek için çözüm. ziyaretin stackoverflow.com/questions/9889225/...
Hasan Abrar


3
Bu KG'nin eski olduğunu unutmayın. Günümüzde csv, RFC 4180 anlamına geliyor ve işte bu.
Fattie

Virgülle ayrılmış bir csv dosyasında bir sütun toplam çalışırken aynı sorunu var. Bir awk komutuyla sorun değil. Maalesef bazı hücreler virgül içerebilir (örneğin bir adreste), diğer hücreler içermez. Linux uyumlu bir çözüm mü arıyorsunuz ancak nereden başlayacağınızdan emin değilsiniz.
Greenage

Yanıtlar:


223

Diğerlerinin söylediği gibi, tırnak içeren değerlerden kaçmanız gerekir. Burada, gömülü tırnak işaretleri ve satır başları dahil, alıntılanmış değerleri destekleyen küçük bir CSV okuyucu var.

Bu arada, bu birim test edilmiş kod. Şimdi gönderiyorum çünkü bu soru çok ortaya çıkıyor gibi görünüyor ve diğerleri basit CSV desteği yapacağında tüm kütüphaneyi istemeyebilir.

Aşağıdaki gibi kullanabilirsiniz:

using System;
public class test
{
    public static void Main()
    {
        using ( CsvReader reader = new CsvReader( "data.csv" ) )
        {
            foreach( string[] values in reader.RowEnumerator )
            {
                Console.WriteLine( "Row {0} has {1} values.", reader.RowIndex, values.Length );
            }
        }
        Console.ReadLine();
    }
}

İşte sınıflar. Bu Csv.Escapeişlevi geçerli CSV yazmak için de kullanabileceğinizi unutmayın .

using System.IO;
using System.Text.RegularExpressions;

public sealed class CsvReader : System.IDisposable
{
    public CsvReader( string fileName ) : this( new FileStream( fileName, FileMode.Open, FileAccess.Read ) )
    {
    }

    public CsvReader( Stream stream )
    {
        __reader = new StreamReader( stream );
    }

    public System.Collections.IEnumerable RowEnumerator
    {
        get {
            if ( null == __reader )
                throw new System.ApplicationException( "I can't start reading without CSV input." );

            __rowno = 0;
            string sLine;
            string sNextLine;

            while ( null != ( sLine = __reader.ReadLine() ) )
            {
                while ( rexRunOnLine.IsMatch( sLine ) && null != ( sNextLine = __reader.ReadLine() ) )
                    sLine += "\n" + sNextLine;

                __rowno++;
                string[] values = rexCsvSplitter.Split( sLine );

                for ( int i = 0; i < values.Length; i++ )
                    values[i] = Csv.Unescape( values[i] );

                yield return values;
            }

            __reader.Close();
        }
    }

    public long RowIndex { get { return __rowno; } }

    public void Dispose()
    {
        if ( null != __reader ) __reader.Dispose();
    }

    //============================================


    private long __rowno = 0;
    private TextReader __reader;
    private static Regex rexCsvSplitter = new Regex( @",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))" );
    private static Regex rexRunOnLine = new Regex( @"^[^""]*(?:""[^""]*""[^""]*)*""[^""]*$" );
}

public static class Csv
{
    public static string Escape( string s )
    {
        if ( s.Contains( QUOTE ) )
            s = s.Replace( QUOTE, ESCAPED_QUOTE );

        if ( s.IndexOfAny( CHARACTERS_THAT_MUST_BE_QUOTED ) > -1 )
            s = QUOTE + s + QUOTE;

        return s;
    }

    public static string Unescape( string s )
    {
        if ( s.StartsWith( QUOTE ) && s.EndsWith( QUOTE ) )
        {
            s = s.Substring( 1, s.Length - 2 );

            if ( s.Contains( ESCAPED_QUOTE ) )
                s = s.Replace( ESCAPED_QUOTE, QUOTE );
        }

        return s;
    }


    private const string QUOTE = "\"";
    private const string ESCAPED_QUOTE = "\"\"";
    private static char[] CHARACTERS_THAT_MUST_BE_QUOTED = { ',', '"', '\n' };
}

2
Ayrıca, uygulamanıza bağlı olarak Windows uyumluluğu için \ r \ n çevirmeniz gerekebilir.
Mandrake

3
@NadaNaeem, özen göstermeye özen gösteriyor musunuz?
harpo

bir csv dosya satırındaki öğeleri doğru saymıyor, alanlardaki virgüllerle iyi ilgilenmiyor ve dönüş ve cesaret döndürüyor
Nada N. Hantouli

-1 OP dosyayı oluşturan bir dil belirtmiyor. Başka bir programcı C # dışında herhangi bir dilde bir çözüm aramaya gelirse, bu cevapta kullanabilecekleri bir çözüm bulamazlar.
Ben Leggiero

8
@ BenC.R. Laggiero, o zaman standart da cevapsız olduğu için, soruyu da aşağı indirmeniz gerektiğini varsayalım. Olduğu gibi, kod basit bir spesifikasyonun resmi bir uygulamasına karşılık gelir ve yaygın olarak kullanılan herhangi bir dile kolayca çevrilebilir.
harpo

395

2017 için csv tam olarak belirtildi - RFC 4180.

Çok yaygın bir özelliktir ve tamamen birçok kütüphane tarafından kapsanmaktadır ( örnek ).

Kolayca erişilebilen herhangi bir csv kütüphanesini kullanın - yani RFC 4180.


Aslında CSV formatı ve virgüllerle nasıl başa çıkılacağı konusunda bir spesifikasyon var:

Satır sonu (CRLF), çift tırnak ve virgül içeren alanlar çift tırnak içine alınmalıdır.

http://tools.ietf.org/html/rfc4180

Yani, değerlere sahip olmak foo ve bar,bazbunu yapmak:

foo,"bar,baz"

Dikkate alınması gereken bir başka önemli gereklilik (spesifikasyondan da):

Alanları çift tırnak içine almak için kullanılırsa, bir alanın içinde görünen çift tırnaktan önce başka bir çift tırnak işareti konarak kaçılmalıdır. Örneğin:

"aaa","b""bb","ccc"

120
"Satır sonu (CRLF), çift tırnak ve virgül içeren alanlar çift tırnak içine alınmalıdır."
Eli

42
"Alanları çift tırnak içine almak için kullanılırsa, bir alanın içinde görünen çift tırnaktan önce başka bir çift tırnak işareti geçerek kaçmak gerekir."
C.Ejderha 76

11
Gerçekten bir spec değil, ama yine de muhtemelen kullanışlı. Diyor ki ... "Var olan, CSV dosyalarının çok çeşitli yorumlanmasına izin veren resmi bir şartname yoktur. Bu bölüm, çoğu uygulamanın izlediği görünen formatı belgelemektedir."
Justin Clarke

5
Ayrıca, adına rağmen, satırdaki CSV değerlerinin yalnızca virgülle değil, en azından Windows platformlarında ayrılabileceğini unutmayın. O (intl.cpl komut satırında "Gelişmiş ayarlar") güncel bölgesel ayarlara özellikle, liste ayırıcı içinde, bağlıdır: System.Globalization.CultureInfo.CurrentCulture.TextInfo.ListSeparator.
lxa

4
Lütfen bağlantıya ek olarak A'ya yukarıdaki bilgileri de ekleyin. veri, C) Link Rot önlemek.
user66001

76

CSV biçimi değerleri ayırmak için virgül kullanır, satır başı, satır beslemeleri, virgül veya çift tırnak işareti içeren değerler çift tırnak içine alınır. Çift tırnak içeren değerler tırnak içine alınır ve her değişmez alıntı hemen bir önceki tırnaktan çıkar: Örneğin, 3 değer:

test
list, of, items
"go" he said

şu şekilde kodlanır:

test
"list, of, items"
"""go"" he said"

Herhangi bir alan tırnak içine alınabilir, ancak yalnızca virgül, CR / NL veya tırnak içeren alanlar tırnak içine alınmalıdır .

CSV biçimi için gerçek bir standart yoktur , ancak neredeyse tüm uygulamalar burada belgelenen sözleşmelere uyar . Başka bir yerde bahsedilen RFC, CSV için bir standart değildir, MIME içinde CSV kullanımı için bir RFC'dir ve MIME dışında işe yaramaz hale getiren bazı alışılmadık ve gereksiz sınırlamalar içerir.

Görmediğim birçok CSV modülünün birden fazla satırın tek bir alanda kodlanabilmesi, her satırın ayrı bir kayıt olduğunu varsayamayacağınız, ya da veri veya bunu ele almaya hazır olun.


40

Dizelerin etrafına çift tırnak işareti koyun. Genelde Excel bunu yapar .

Ala Eli,

iki çift tırnak gibi bir çift tırnak kaçmak. Örneğin, "test1", "foo" "bar", "test2"


alıntı yapılan tanımlayıcılarla aynı kavram
Bob The Janitor

1
iki çift tırnak gibi bir çift tırnak kaçmak. Örneğin, "test1", "foo" "bar", "test2"
Eli

Bir "hemen arkasından virgül
geldikten

9

Alanların etrafına çift tırnak işareti koyabilirsiniz. Başka bir özel karakter (çift tırnak) eklediğinden, bu yaklaşımı sevmiyorum. Sadece bir kaçış karakteri tanımlayın (genellikle ters eğik çizgi) ve bir şeyden kaçmak için ihtiyacınız olan her yerde kullanın:

veri, daha fazla veri, daha fazla veri \, hatta daha fazlası

Alıntıları eşleştirmeye çalışmak zorunda değilsiniz ve ayrıştırmak için daha az istisnanız var. Bu, kodunuzu da basitleştirir.


3
Hızlı ve kirli ama aslında "\" içeren bir girişiniz varsa çalışmaz
Sarp Kaya

1
Sarp, bu yüzden bir çift \\ kaçan ters eğik çizgi, çünkü şimdi başka bir özel karakter haline geliyor.
Grungondola

1
Bu çalışıyor, ancak CSV değil. Bu bir DSV .
TRiG

8

Nuget aracılığıyla hemen hemen iyi biçimlendirilmiş herhangi bir CSV (.net) ile uğraşmak için bir kütüphane var - CsvHelper

Bir sınıfa eşleme örneği:

var csv = new CsvReader( textReader );
var records = csv.GetRecords<MyClass>();

Tek tek alanları okumak için örnek:

var csv = new CsvReader( textReader );
while( csv.Read() )
{
    var intField = csv.GetField<int>( 0 );
    var stringField = csv.GetField<string>( 1 );
    var boolField = csv.GetField<bool>( "HeaderName" );
}

İstemcinin dosya biçimini kullanmasına izin vermek:
, standart alan sınırlayıcıdır, "sınırlayıcı, tırnak işareti veya satır sonu içeren alanlardan kaçmak için kullanılan standart değerdir.

#Alanlar ve çıkış 'için (örneğin) kullanmak üzere:

var csv = new CsvReader( textReader );
csv.Configuration.Delimiter = "#";
csv.Configuration.Quote = ''';
// read the file however meets your needs

Daha Fazla Dokümantasyon


3
CsvHelperOP'nin problemini çözmek için kütüphanenin nasıl kullanılacağına dair bir örnek eklerseniz tercih edilir .
George Stocker

Neden .Net'teki neredeyse her şey bir "Yardımcı" olmak zorunda ... kelime anlamsız yakın ... "Yönetici" gibi.
bytedev

5

Harpo'nun cevabına yaptığım yorumda belirtildiği gibi, çözümü iyi ve çoğu durumda işe yarıyor, ancak bazı senaryolarda doğrudan birbirine bitişik olarak virgüllerin virgüllere bölünememesi.

Bunun nedeni, bir vertabim dizesi olarak beklenmedik biçimde davranan Regex dizgesidir. Bunun doğru davranmasını sağlamak için, regex dizesindeki tüm "karakterlerin vertabim escape kullanılmadan manuel olarak kaçmaları gerekir.

Yani. Normal ifade manuel kaçışlar kullanarak şu olmalıdır:

",(?=(?:[^\"\"]*\"\"[^\"\"]*\"\")*(?![^\"\"]*\"\"))"

dönüştüren ",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))"

Bir vertabim dizesi kullanırken, normal ifadede hata ayıklayıp @",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))"ayıklamadığınızı görebileceğiniz gibi aşağıdaki gibi davranır:

",(?=(?:[^"]*"[^"]*")*(?![^"]*"))"

Yani özet olarak, harpo'nun çözümünü öneriyorum, ama bu küçük gotcha'ya dikkat edin!

Ben CsvReader içine bu hata oluşursa (önceden bilinen sayıda sütun varsa) size bildirmek için biraz isteğe bağlı bir failsafe dahil ettik:

if (_expectedDataLength > 0 && values.Length != _expectedDataLength) 
throw new DataLengthException(string.Format("Expected {0} columns when splitting csv, got {1}", _expectedDataLength, values.Length));

Bu, yapıcı yoluyla enjekte edilebilir:

public CsvReader(string fileName, int expectedDataLength = 0) : this(new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
    _expectedDataLength = expectedDataLength;
}

Başlık satırını nasıl ele alırsınız? Ben csv tüm türleri C # nesneleri
eşlemeye

İle [^""]aynı değil [^"]mi? Bir karakterin karakter sınıfı belirtimi içinde çoğaltılması gereksizdir, değil mi?
Minh Tran

4

Microsoft.VisualBasic'e bir başvuru ekleyin (evet, VisualBasic diyor ama C # ile de çalışıyor - sonunda hepsi sadece IL).

Microsoft.VisualBasic.FileIO.TextFieldParserCSV dosyasını ayrıştırmak için sınıfı kullanın İşte örnek kod:

 Dim parser As TextFieldParser = New TextFieldParser("C:\mar0112.csv")
 parser.TextFieldType = FieldType.Delimited
 parser.SetDelimiters(",")      

   While Not parser.EndOfData         
      'Processing row             
      Dim fields() As String = parser.ReadFields         
      For Each field As String In fields             
         'TODO: Process field                   

      Next      
      parser.Close()
   End While 

Evet, bu biraz talihsiz bir isim alanında çok yararlı bir sınıf ;-). Bununla birlikte, orijinal soruyu çözmek için ayar yapmalısınız parser.HasFieldsEnclosedInQuotes = true;ve giriş dosyasının CSV spesifikasyonuna göre virgül içeren alanları tırnak içine alması gerekir - excel zaten bunu yapar.
Christopher King


4

Bir * nix sistemindeyseniz , CSV'nizin yalnızca belirli bir alanına erişebileceğiniz sedve bir veya daha fazla istenmeyen virgül olabiliyorsa, bunları RFC4180 Bölümü" olarak dahil etmek için aşağıdaki tek astarı kullanabilirsiniz. 2 teklif:

sed -r 's/([^,]*,[^,]*,[^,]*,)(.*)(,.*,.*)/\1"\2"\3/' inputfile

İstenilen virgül (ler) in hangi alanda olabileceğine bağlı olarak, normal ifadenin (ve ikame) yakalama gruplarını değiştirmeniz / genişletmeniz gerekir.
Yukarıdaki örnek dördüncü alanı (altıdan) tırnak içine alacaktır.

resim açıklamasını buraya girin

-Option ile birlikte--in-place bu değişiklikleri doğrudan dosyaya uygulayabilirsiniz.

Doğru normal ifadeyi "oluşturmak" için izlenmesi gereken basit bir ilke vardır:

  1. CSV'nizde istenmeyen virgül (ler) ile alandan önce gelen her alan için bir tane yazar [^,]*,ve hepsini bir yakalama grubuna koyarsınız.
  2. Yazdığınız istenmeyen virgül (ler) i içeren alan için (.*).
  3. İstenmeyen virgül (ler) ile alandan sonraki her alan için bir tane yazar ,.* ve hepsini bir yakalama grubuna koyarsınız.

Burada, alana bağlı olarak farklı olası normal ifadeler / ikamelere kısa bir genel bakış verilmiştir. Verilmezse, oyuncu değişikliği yapılır \1"\2"\3.

([^,]*)(,.*)                     #first field, regex
"\1"\2                           #first field, substitution

(.*,)([^,]*)                     #last field, regex
\1"\2"                           #last field, substitution


([^,]*,)(.*)(,.*,.*,.*)          #second field (out of five fields)
([^,]*,[^,]*,)(.*)(,.*)          #third field (out of four fields)
([^,]*,[^,]*,[^,]*,)(.*)(,.*,.*) #fourth field (out of six fields)

İstenmeyen virgül (leri) sedtırnak işareti içine almak yerine kaldırmak istiyorsanız bu cevaba bakınız. .


3

Tekerleği yeniden icat etmek istiyorsanız, aşağıdakiler sizin için işe yarayabilir:

public static IEnumerable<string> SplitCSV(string line)
{
    var s = new StringBuilder();
    bool escaped = false, inQuotes = false;
    foreach (char c in line)
    {
        if (c == ',' && !inQuotes)
        {
            yield return s.ToString();
            s.Clear();
        }
        else if (c == '\\' && !escaped)
        {
            escaped = true;
        }
        else if (c == '"' && !escaped)
        {
            inQuotes = !inQuotes;
        }
        else
        {
            escaped = false;
            s.Append(c);
        }
    }
    yield return s.ToString();
}

3

Avrupa'da bu sorunun bu sorudan önce olması gerekir. Avrupa'da ondalık nokta için virgül kullanıyoruz. Aşağıdaki numaralara bakın:

| American      | Europe        |
| ------------- | ------------- |
| 0.5           | 0,5           |
| 3.14159265359 | 3,14159265359 |
| 17.54         | 17,54         |
| 175,186.15    | 175.186,15    |

Bu nedenle, CSV dosyaları için virgül ayırıcıyı kullanmak mümkün değildir. Bu nedenle Avrupa'daki CSV dosyaları noktalı virgülle ( ) ayrılır.; .

Microsoft Excel gibi programlar noktalı virgülle dosyaları okuyabilir ve ayırıcıdan geçiş yapmak mümkündür. \tAyırıcı olarak bir sekme ( ) bile kullanabilirsiniz . Supper User'ın bu cevabına bakın .


2

Dosyaların genel olarak nasıl ayrıştırılacağı konusunda daha eğitici bir çalışma ile ilgileniyorsanız (örnek olarak CSV kullanarak), bu makaleye göz atabilirsiniz. Julian Bucknall'ın . Makaleyi seviyorum çünkü işleri daha az çözülemeyen daha küçük sorunlara ayırıyor. Önce bir dilbilgisi oluşturursunuz ve iyi bir dilbilgisine sahip olduğunuzda, dilbilgisini koda dönüştürmek nispeten kolay ve yöntemsel bir işlemdir.

Makale C # kullanır ve kodu indirmek için altta bir bağlantı vardır.


1

İşte düzgün küçük bir çözüm:

Bunun yerine bir Yunan Alt Sayı İşareti kullanabilirsiniz (U + 0375)

Öyle görünüyor ͵

Bu yöntemi kullanmak size çok fazla kaynak tasarrufu sağlar ...


1

NuGet üzerinde SoftCircuits.CsvParser kullanmanız yeterli . Tüm bu ayrıntıları sizin için halledecek ve çok büyük dosyaları verimli bir şekilde işleyecektir. Ve gerekirse sütunları nesne özelliklerine eşleyerek nesneleri içe / dışa aktarabilir. Buna ek olarak, testlerim, popüler CsvHelper'den ortalama 4 kat daha hızlı olduğunu gösterdi.


0

Bu genel uygulamalar ile ilgili olduğundan, baş parmak kurallarından başlayalım:

  1. CSV kullanmayın, xml dosyasını okumak ve yazmak için XML'yi bir kitaplıkla kullanın.

  2. CSV kullanmanız gerekiyorsa. Düzgün yapın ve CSV dosyalarını ayrıştırmak ve depolamak için ücretsiz bir kitaplık kullanın.

1) gerekçelendirmek için, çoğu CSV ayrıştırıcısı farkında kodlamıyor, bu yüzden US-ASCII ile uğraşmıyorsanız sorunlarınız var. Örneğin excel 2002, CSV'yi kodlama hakkında herhangi bir not olmadan yerel kodlamada saklamaktadır. CSV standardı yaygın olarak benimsenmemiştir :(. Öte yandan xml standardı iyi kabul edilmiştir ve kodlamaları oldukça iyi işler.

2), Hemen hemen tüm dil için tonlarca csv ayrıştırıcı var, bu yüzden çözümler oldukça basit görünse bile tekerleği yeniden icat etmeye gerek yok.

Birkaç isim vermek için:

  • python kullanımı için csv modülünde inşa

  • perl kontrol CPAN ve Metin için :: CSV

  • php kullanım fgetcsv / fputcsv fonksiyonlarında kurmak için

  • java için SuperCVS kütüphanesini kontrol edin

Gerçekten, gömülü aygıtta ayrıştırmayacaksanız bunu elle uygulamaya gerek yoktur.


12
XML her zaman cevap değildir. CSV, çok yoğun, tablo şeklinde verileriniz (yani bir e-tablo) olduğunda iş için doğru biçimdir. Bu etiketler çok fazla ek yük getirir ve her satırın özdeş bir biçimi varsa, her bir değerin neyi temsil ettiği konusunda açık olmaya gerek yoktur. XML, karmaşık hiyerarşik verileriniz veya isteğe bağlı alanlara sahip kayıtlarınız olduğunda harikadır. Bu her zaman böyle değildir.
Adam Jaskiewicz

Teorik olarak "etiketler" biraz genel gider tanıtmak ama bir sorun olmaya başlar herhangi bir gerçek yaşam uygulaması düşünemiyorum. Pratik örnekleriniz var mı? Veriler üzerinde çalışmak için csv yerine bir veritabanı kullanılmalıdır. veri serileştirme (yedeklemeler, veri değişimi) hakkında konuşursak, ayrıştırmanın 5 gün yerine bir hafta sürmesi önemli midir?
Piotr Czapla

2
Temel olarak, en iyi bir tablo ile temsil edilen verilere sahip olduğunuz herhangi bir durum. Diyelim ki sık sık örneklediğiniz bir düzine farklı sensörden verileriniz var ve o anda sensörlerin her birinin zaman damgasını ve değerini kaydediyorsunuz. Her kayıt aynıdır: zaman damgası, sensör0, sensör1, ... sensör11. XML, karmaşık ve düzensiz verileri temsil etmek için mükemmeldir, ancak her duruma uymayan oldukça ağır bir biçimdir. KISS
Adam Jaskiewicz

10
Bazı insanlar bir sorun görür ve "Biliyorum, XML kullanacağım!" Diyorlar. Şimdi onların iki problemi var.
Adam Jaskiewicz

Tamamen katılıyorum xml her şey için bir cevap değildir. Özellikle veritabanı değiştirme veya yapılandırma dosyaları için uygun değildir. Ancak burada soru, XML için tasarlanan veri alışverişi ile ilgiliydi.
Piotr Czapla

0

Csv dosyasını böyle okuyabilirsiniz.

bu bölünmeleri kullanır ve boşluklarla ilgilenir.

ArrayList List = new ArrayList();
static ServerSocket Server;
static Socket socket;
static ArrayList<Object> list = new ArrayList<Object>();


public static void ReadFromXcel() throws FileNotFoundException
{   
    File f = new File("Book.csv");
    Scanner in = new Scanner(f);
    int count  =0;
    String[] date;
    String[] name;
    String[] Temp = new String[10];
    String[] Temp2 = new String[10];
    String[] numbers;
    ArrayList<String[]> List = new ArrayList<String[]>();
    HashMap m = new HashMap();

         in.nextLine();
         date = in.nextLine().split(",");
         name = in.nextLine().split(",");
         numbers = in.nextLine().split(",");
         while(in.hasNext())
         {
             String[] one = in.nextLine().split(",");
             List.add(one);
         }
         int xount = 0;
         //Making sure the lines don't start with a blank
         for(int y = 0; y<= date.length-1; y++)
         {
             if(!date[y].equals(""))
             {   
                 Temp[xount] = date[y];
                 Temp2[xount] = name[y];
                 xount++;
             }
         }

         date = Temp;
         name =Temp2;
         int counter = 0;
         while(counter < List.size())
         {
             String[] list = List.get(counter);
             String sNo = list[0];
             String Surname = list[1];
             String Name = list[2];
             for(int x = 3; x < list.length; x++)
             {           
                 m.put(numbers[x], list[x]);
             }
            Object newOne = new newOne(sNo, Name, Surname, m, false);
             StudentList.add(s);
             System.out.println(s.sNo);
             counter++;
         }

0

İlk olarak kendimize, "Neden CSV dosyaları için virgülle farklı şekilde ilgilenme ihtiyacını hissediyoruz?"

Benim için, "Verileri bir CSV dosyasına aktardığımda, bir alandaki virgüller kaybolur ve alanım virgüllerin orijinal verilerde göründüğü birden çok alana ayrılır." (Virgül CSV alan ayırıcı karakter olduğu için.)

Durumunuza bağlı olarak, noktalı virgül CSV alan ayırıcıları olarak da kullanılabilir.

Gereksinimlerim göz önüne alındığında, virgül gibi görünen bir karakter, örneğin tek düşük 9 tırnak işareti kullanabilirim.

Go'da bunu nasıl yapabileceğiniz aşağıda açıklanmıştır:

// Replace special CSV characters with single low-9 quotation mark
func Scrub(a interface{}) string {
    s := fmt.Sprint(a)
    s = strings.Replace(s, ",", "‚", -1)
    s = strings.Replace(s, ";", "‚", -1)
    return s
}

Değiştir işlevindeki ikinci virgül görünümlü karakter ondalık 8218'dir.

Yalnızca ascii metin okuyucuları olan istemcileriniz varsa, bu decima 8218 karakterinin virgül gibi görünmeyeceğini unutmayın. Bu durumda, alanı RFC 4128 başına çift tırnak işareti ile virgülle (veya noktalı virgülle) çevrelemenizi öneririm: https://tools.ietf.org/html/rfc4180


0

Genelde virgül veya özel karakter içeren alanları URL olarak kodlarım. Ve daha sonra herhangi bir görsel ortamda kullanıldığında / görüntülendiğinde kodunu çözün.

(virgül% 2C olur)

Her dilin dizeleri URL kodlamak ve kodunu çözmek için yöntemleri olmalıdır.

örneğin, java

URLEncoder.encode(myString,"UTF-8"); //to encode
URLDecoder.decode(myEncodedstring, "UTF-8"); //to decode

Bunun çok genel bir çözüm olduğunu biliyorum ve kullanıcının csv dosyasının içeriğini manuel olarak görüntülemek istediği durum için ideal olmayabilir.


0

Bunu genellikle CSV dosyalarımda ayrıştırma rutinleri içinde yapıyorum. 'Line' değişkeninin bir CSV dosyası içindeki bir satır olduğunu ve tüm sütunların değerlerinin çift tırnak içine alındığını varsayın. Aşağıdaki iki satır yürütüldükten sonra, 'değerler' koleksiyonunda CSV sütunları alırsınız.

// The below two lines will split the columns as well as trim the DBOULE QUOTES around values but NOT within them
    string trimmedLine = line.Trim(new char[] { '\"' });
    List<string> values = trimmedLine.Split(new string[] { "\",\"" }, StringSplitOptions.None).ToList();

1
Kodum neden StackOverflow'da asla birden fazla renkte görüntülenmiyor? Dört boşluk girintiliyim.
user1451111


0

Bulduğum en basit çözüm LibreOffice'in kullandığı çözüm:

  1. Tüm edebi değiştirin "biriminin by
  2. Dizenizin etrafına çift tırnak işareti koyun

Excel'in kullandığı yöntemi de kullanabilirsiniz:

  1. Tüm edebi değiştirin "biriminin by""
  2. Dizenizin etrafına çift tırnak işareti koyun

Diğer kişilerin yalnızca yukarıdaki 2. adımı gerçekleştirmelerini önerdiğine dikkat edin, ancak CSV'nin okuyacağı gibi, dizeyle tek bir sütun olmasını istediğiniz bir CSV'de olduğu gibi, a'nın a'nın "takip ettiği satırlarla çalışmaz :,hello",world

"hello",world"

İki sütunlu bir satır olarak yorumlanır: helloveworld"


1
Standart kurallara göre, bölünmüş karakter veya tırnak işareti içeren herhangi bir alan tırnak işaretleri içine alınır ve içindeki tırnak iki katına çıkar, bu yüzden sorun olmaz. Alanınızın hello",worldyalnızca "hello"",world"% 100 doğru şekilde ayrıştırılabilecek şekilde kaydedilmesi gerekir .
Nyerguds

0
    public static IEnumerable<string> LineSplitter(this string line, char 
         separator, char skip = '"')
    {
        var fieldStart = 0;
        for (var i = 0; i < line.Length; i++)
        {
            if (line[i] == separator)
            {
                yield return line.Substring(fieldStart, i - fieldStart);
                fieldStart = i + 1;
            }
            else if (i == line.Length - 1)
            {
                yield return line.Substring(fieldStart, i - fieldStart + 1);
                fieldStart = i + 1;
            }

            if (line[i] == '"')
                for (i++; i < line.Length && line[i] != skip; i++) { }
        }

        if (line[line.Length - 1] == separator)
        {
            yield return string.Empty;
        }
    }

0

Csvreader kitaplığı kullandım ama bunu kullanarak sütun değeri virgül (,) patlayarak veri var.

Bu nedenle, sütun değerlerinin çoğuna virgül (,) içeren CSV dosyası verileri eklemek isterseniz, aşağıdaki işlevi kullanabilirsiniz. Yazar bağlantısı => https://gist.github.com/jaywilliams/385876

function csv_to_array($filename='', $delimiter=',')
{
    if(!file_exists($filename) || !is_readable($filename))
        return FALSE;

    $header = NULL;
    $data = array();
    if (($handle = fopen($filename, 'r')) !== FALSE)
    {
        while (($row = fgetcsv($handle, 1000, $delimiter)) !== FALSE)
        {
            if(!$header)
                $header = $row;
            else
                $data[] = array_combine($header, $row);
        }
        fclose($handle);
    }
    return $data;
}

0

CSV dosyasının ayrıştırılması ve anahtar / değer çiftlerinin (anahtar / başlık / CSV dosya değerinin ilk satırı) olması için papaParse kütüphanesini kullandım.

İşte kullandığım örnek:

https://codesandbox.io/embed/llqmrp96pm

CSV ayrıştırma demosu için dummy.csv dosyası var.

Herhangi bir dilde yazılmış uygulamada çoğaltmak kolay ve basit olsa da tepki içinde kullandım.


0

Bir örnek virgüllerin bir .csv dosyasında nasıl görüntülenebileceğini göstermeye yardımcı olabilir. Aşağıdaki gibi basit bir metin dosyası oluşturun:

Bu metin dosyasını ".csv" sonekine sahip bir metin dosyası olarak kaydedin ve Windows 10'dan Excel 2000 ile açın.

aa, bb, cc, d; d "Elektronik tablo sunumunda, aşağıdaki satır yukarıdaki gibi görünmelidir, ancak aşağıdakiler d'ler arasında noktalı virgül yerine görüntülenen virgül gösterir." aa, bb, cc, "d, d", Excel'de bile çalışır

aa, bb, cc, "d, d", Bu Excel 2000'de bile çalışır aa, bb, cc, "d, d", Bu Excel 2000'de bile çalışır aa, bb, cc, "d, d", Bu çalışır Excel 2000'de bile

aa, bb, cc, "d, d", Bu alan 2000 alıntı belore nedeniyle Excel 2000'de başarısız aa, bb, cc, "d, d", Bu alan 1. alıntı belore nedeniyle Excel 2000'de başarısız aa, bb, cc, "d, d", Bu alanın 1. alıntıdan dolayı alan nedeniyle Excel 2000'de başarısız oluyor

aa, bb, cc, "d, d", Bu Excel 2000'de bile 2. tekliften önce ve sonra boşluklarla bile çalışır. aa, bb, cc, "d, d", Bu Excel 2000'de bile 2. tekliften önce ve sonra boşluklarla bile çalışır. aa, bb, cc, "d, d", Bu Excel 2000'de bile 2. tekliften önce ve sonra boşluklarla bile çalışır.

Kural: Bir .csv dosyasının bir hücresinde (alanında) virgül görüntülemek istiyorsanız: "Alanı çift tırnak işareti ile başlatın ve bitirin, ancak 1. tırnaktan önce boşluk bırakmayın"


-1

Bu sorunun en kolay çözüm müşteri excel csv açmak ve daha sonra tüm virgül istediğiniz herhangi bir tanımlayıcı ile değiştirmek için ctrl + r olduğunu düşünüyorum. Bu, müşteri için çok kolaydır ve seçtiğiniz sınırlayıcıyı okumak için kodunuzda yalnızca bir değişiklik gerektirir.


Kim demiş Excel var? Aslında kim yükleme bile yapan bir insan olduğunu söylüyor? ...
bytedev

-3

Alanları ayırmak için bir sekme karakteri (\ t) kullanın.


4
-1 Birisi kendi değerinde bir sekme kullanana kadar harika, o zaman soruyu soran kişinin sorununa geri dönün. Sorunu çözecek bir sınırlayıcı karakterini başka bir karakterle değiştirmek.
bytedev

Saçmalık. Kullanıcılar veri girişlerine sekme giremez. Çoğu formda bu, veri giriş noktasını bir sonraki alana taşır.
Pierre

6
"İnsanlar veri girişlerine sekme giremez" .... ciddi misin ?? A) Tabii ki bir kişi girdi alanına bir sekme koyabilir B) verilerin geldiği GUI olduğunu kim söyleyebilir? C) Verilere giren bir insanın bile kim olduğunu söyler?
bytedev
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.