2010-03-02 19 views
44

satırların bir seq içine bir dosya okuyun:Bu C# versiyonudur Ya F #

public static IEnumerable<string> ReadLinesEnumerable(string path) { 
    using (var reader = new StreamReader(path)) { 
    var line = reader.ReadLine(); 
    while (line != null) { 
     yield return line; 
     line = reader.ReadLine(); 
    } 
    } 
} 

Ama doğrudan tercüme ihtiyaçlarını kesilebilir bir değişken.

cevap

62
let readLines (filePath:string) = seq { 
    use sr = new StreamReader (filePath) 
    while not sr.EndOfStream do 
     yield sr.ReadLine() 
} 
+0

Teşekkür! Btw, bunun için bir kütüphane işlevi var mı? –

+0

@David - Kesinlikle olmalı. .NET kitaplıklarının yavaş yavaş daha IEnumerable arabirimlere doğru ilerlediğine inanıyorum. – ChaosPandion

+1

Başka bir işlem tarafından önceden açılmış bir dosyayı okumam gerekiyordu, bu yüzden aşağıdaki gibi değiştirdim: fs = new FileStream (filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); sr = new StreamReader (fs) 'işlevini kullanın – User

71

.NET 4.0 kullanıyorsanız, yalnızca File.ReadLines'u kullanabilirsiniz.

> let readLines filePath = System.IO.File.ReadLines(filePath);; 

val readLines : string -> seq<string> 
+0

Bu, tüm dosyanın bir kerede bellekte tutulmasını gerektirir mi yoksa satır satır mı işleyebilir? –

+12

"ReadLines ve ReadAllLines yöntemleri, aşağıdaki gibi farklılık gösterir: ReadLines kullandığınızda, tüm koleksiyonun döndürülmesinden önce dizelerin toplanması numaralandırmaya başlayabilirsiniz; ReadAllLines kullandığınızda, tüm dizileri dizisi için kullanabilmeniz için önce beklemeniz gerekir. Bu nedenle, çok büyük dosyalar ile çalışırken, ReadLines daha verimli olabilir. " –

17

bu modeli kaplamak için bir kütüphane işlevi olup olmadığını soruya cevap vermek için - bir işlev bunun için tam olarak yoktur, ancak bazı devlet Seq.unfold denilen sizi diziyi oluşturmak için olanak sağlayan bir işlevi yoktur . Böyle yukarıda işlevleri gerçekleştirmek için kullanabilir:

new StreamReader(filePath) |> Seq.unfold (fun sr -> 
    match sr.ReadLine() with 
    | null -> sr.Dispose(); None 
    | str -> Some(str, sr)) 

sr değer akışı okuyucusu temsil eder ve durumuna geçirilir. Boş olmayan değerler sağladığınız sürece, oluşturulacak bir öğe ve durum (istediğiniz takdirde değişebilir) içeren Some'u döndürebilirsiniz. null okunduğunda, diziyi sonlandırmak için None'u iade ederiz. Bu bir doğrudan eşdeğer değildir, çünkü bir istisna atıldığında StreamReader düzgün şekilde atmaz.

Bu durumda, kesinlikle sıralama ifadesini (çoğu durumda daha zarif ve okunabilir) kullanırdım, ancak daha yüksek sıralı bir işlev kullanılarak yazılabileceğini bilmek de yararlı olur. .NET 2/3 günü

+0

bunu kullanarak şu özel durumla karşılaşıyorum: {"Kapalı bir TextReader'dan okunamıyor."} "Sr.ReadLine() eşleştirmesi" satırında. herhangi bir yardım neden olduğu gibi lütfen? – AruniRC

+0

@AruniRC @ChaosPandion tarafından çözümün, 'açılmamış' kelimesini kullanandan çok daha iyi olduğunu düşünüyorum, bu yüzden bu :-) ile devam ediyorum :-) –

+0

@AruniRC, Seq tembel - daha sonra kodu değerlendirdiğinizde , okuyucu zaten kapalı olabilir, dolayısıyla kapalı bir TextReader'dan okunamıyor olabilir. Sıralamanın değerlendirmesini hemen zorlamak zorunda kalacaksınız, örneğin "Seq.toList" ile listeye dönüştürerek veya başka bir numara. –

3

Yapabileceğiniz:

let readLines filePath = File.ReadAllLines(filePath) |> Seq.cast<string> 

ve .NET 4:

let readLines filePath = File.ReadLines(filePath);; 
+0

Bunlardan birincisi tembel değil ('ReadAllLines' tüm satırları hevesle bir diziye okur). –

8
let lines = File.ReadLines(path)     

    // To check 
    lines |> Seq.iter(fun x -> printfn "%s" x)