Eu tenho um arquivo .\input.txt
como este:
aaa
bbb
ccc
Se eu o ler TStrings.LoadFromFile
e escrevê-lo novamente (mesmo sem aplicar nenhuma alteração) TStrings.SaveToFile
, ele criará uma linha vazia no final do arquivo de saída.
var
Lines : TStrings;
begin
Lines := TStringList.Create;
try
Lines.LoadFromFile('.\input.txt');
//...
Lines.SaveToFile('.\output.txt');
finally
Lines.Free;
end;
end;
O mesmo comportamento pode ser observado usando a TStrings.Text
propriedade que retornará uma string contendo uma linha vazia no final.
delphi
tstringlist
Fabrizio
fonte
fonte
\n
caractere e a função adiciona o\n
ao arquivo? Ou a função literalmente adiciona um\n
logo após um existente\n
no final do arquivo? O POSIX exige que os arquivos de texto tenham todas as suas linhas terminadas com a\n
, apenas fyi. Lotes de software foi escrito para seguir algumas normas de modo que é por isso que muitos editores irá adicionar a terminação ausente\n
quando você salvar arquivos por padrão (por exemplovim
, IDEs etc todos por padrão tornar seus arquivos compatível com POSIX.)Respostas:
Para o Delphi 10.1 e mais recente, existe uma propriedade que
TrailingLineBreak
controla esse comportamento.fonte
TrailingLineBreak
propriedade assim que atualizar o IDE. +1 e aceitoPara Delphi 10.1 (Berlin) ou mais recente, a melhor solução é descrita na resposta de Uwe.
Para versões mais antigas do Delphi, encontrei uma solução criando uma classe filho
TStringList
e substituindo aTStrings.GetTextStr
função virtual, mas ficarei feliz em saber se existe uma solução melhor ou se alguém encontrou algo errado na minha solução.Interface:
Implementação:
Exemplo:
fonte
SetLength(Result, -2)
.GetTextStr
, seLength(Result)
é0
, então você fazSetLength(Result, -2)
, o que é ruim. Pode ser que o efeito seja o mesmoSetLength(Result, 0)
, mas não conheço nenhuma garantia sobre isso. A documentação oficial, pelo menos, não contém essa garantia. (Portanto, em teoria, coisas ruins podem acontecer.)Length(Result) = 1
, então você fazSetLength(Result, -1)
, o que é igualmente ruim! Além disso, pode ser queResult
não termine com uma quebra de linha; nesse caso, você removerá os dois últimos caracteres da última linha. Isso também é um bug. (E isso pode acontecer, por exemplo, se você usarTrailingLineBreak
, eu suspeito. Mesmo se não, pode haver outras instâncias.) Você realmente deve testar se a sequência realmente termina com uma quebra de linha, comoif not IncludeLastLineBreakInText and Result.EndsWith(LineBreak) then
.Pos(LineBreak, Result) = Length(Result) - Length(LineBreak) + 1
.Pos
Fornece o índice da primeira correspondência. Se a string contém 6 quebras de linha, ela dará a posição da primeira, mas você claramente espera a última um ...