Quero ler um arquivo de texto linha por linha. Eu queria saber se estou fazendo isso da maneira mais eficiente possível no escopo do .NET C #.
Isto é o que estou tentando até agora:
var filestream = new System.IO.FileStream(textFilePath,
System.IO.FileMode.Open,
System.IO.FileAccess.Read,
System.IO.FileShare.ReadWrite);
var file = new System.IO.StreamReader(filestream, System.Text.Encoding.UTF8, true, 128);
while ((lineOfText = file.ReadLine()) != null)
{
//Do something with the lineOfText
}
c#
.net
performance
file-io
text-files
Loren C Fortner
fonte
fonte
Fastest
que você quer dizer a partir de desempenho ou de desenvolvimento perspectivas?filestream = new FileStream
emusing()
declaração para evitar possíveis problemas irritantes com bloqueado identificador de arquivoRespostas:
Para encontrar a maneira mais rápida de ler um arquivo linha por linha, você precisará fazer alguns testes comparativos. Fiz alguns pequenos testes no meu computador, mas você não pode esperar que meus resultados se apliquem ao seu ambiente.
Usando StreamReader.ReadLine
Este é basicamente o seu método. Por algum motivo, você define o tamanho do buffer para o menor valor possível (128). Aumentar isso geralmente aumentará o desempenho. O tamanho padrão é 1.024 e outras boas opções são 512 (o tamanho do setor no Windows) ou 4.096 (o tamanho do cluster no NTFS). Você precisará executar uma referência para determinar o tamanho ideal do buffer. Um buffer maior é - se não mais rápido - pelo menos não mais lento que um buffer menor.
O
FileStream
construtor permite especificar FileOptions . Por exemplo, se você estiver lendo um arquivo grande sequencialmente do começo ao fim, poderá se beneficiarFileOptions.SequentialScan
. Novamente, o benchmarking é a melhor coisa que você pode fazer.Usando File.ReadLines
Isso é muito parecido com sua própria solução, exceto que ela é implementada usando um
StreamReader
tamanho de buffer fixo de 1.024. No meu computador, isso resulta em um desempenho um pouco melhor comparado ao seu código com o tamanho do buffer de 128. No entanto, você pode obter o mesmo aumento de desempenho usando um tamanho de buffer maior. Este método é implementado usando um bloco iterador e não consome memória para todas as linhas.Usando File.ReadAllLines
Isso é muito parecido com o método anterior, exceto que esse método aumenta uma lista de cadeias usadas para criar a matriz de linhas retornada, para que os requisitos de memória sejam maiores. No entanto, ele retorna
String[]
e nãoIEnumerable<String>
permite que você acesse as linhas aleatoriamente.Usando String.Split
Esse método é consideravelmente mais lento, pelo menos em arquivos grandes (testados em um arquivo de 511 KB), provavelmente devido à maneira como
String.Split
é implementado. Ele também aloca uma matriz para todas as linhas, aumentando a memória necessária em comparação com a sua solução.Minha sugestão é usar
File.ReadLines
porque é limpo e eficiente. Se você precisar de opções especiais de compartilhamento (por exemplo, useFileShare.ReadWrite
), poderá usar seu próprio código, mas deverá aumentar o tamanho do buffer.fonte
Se você estiver usando o .NET 4, basta usar o
File.ReadLines
que faz tudo por você. Eu suspeito que é muito o mesmo que o seu, a não ser que também pode usarFileOptions.SequentialScan
e um buffer maior (128 parece muito pequena).fonte
ReadLines()
é que é preguiçoso, portanto funciona bem com o LINQ.Embora
File.ReadAllLines()
seja uma das maneiras mais simples de ler um arquivo, também é uma das mais lentas.Se você deseja apenas ler linhas em um arquivo sem fazer muito, de acordo com esses benchmarks , a maneira mais rápida de ler um arquivo é o antigo método de:
No entanto, se você precisar fazer muito com cada linha, este artigo conclui que a melhor maneira é a seguinte (e é mais rápido pré-alocar uma string [] se você souber quantas linhas vai ler):
fonte
Use o seguinte código:
Essa foi uma enorme diferença no desempenho da leitura.
Ele custa o consumo de memória, mas vale a pena!
fonte
File.ReadAllLines
Há um bom tópico sobre isso na pergunta Stack Overflow. O retorno do rendimento é mais lento que o retorno da "velha escola"? .
Diz:
fonte
Se o tamanho do arquivo não for grande, será mais rápido ler o arquivo inteiro e dividi-lo depois
fonte
File.ReadAllLines()
File.ReadAllLines
tenha um tamanho de buffer fixo, pois o tamanho do arquivo é conhecido.File.ReadAllLines
cria uma lista e é adicionada a essa lista em um loop usandoStreamReader.ReadLine
(com realocação potencial da matriz subjacente). Este método usa um tamanho de buffer padrão 1024.StreamReader.ReadToEnd
Evita a parte de análise de linha e o tamanho do buffer pode ser definido no construtor, se desejado.Se você tiver memória suficiente, encontrei alguns ganhos de desempenho lendo o arquivo inteiro em um fluxo de memória e abrindo um leitor de fluxo para ler as linhas. Contanto que você realmente planeje ler o arquivo inteiro de qualquer maneira, isso poderá gerar algumas melhorias.
fonte
File.ReadAllLines
parece ser uma escolha melhor então.Você não pode ficar mais rápido se quiser usar uma API existente para ler as linhas. Mas ler pedaços maiores e encontrar manualmente cada nova linha no buffer de leitura provavelmente seria mais rápido.
fonte