Ao criar um aplicativo de console do Windows em C #, é possível gravar no console sem precisar estender uma linha atual ou ir para uma nova linha? Por exemplo, se eu quiser mostrar uma porcentagem representando a proximidade de um processo, gostaria de atualizar o valor na mesma linha que o cursor, e não precisar colocar cada porcentagem em uma nova linha.
Isso pode ser feito com um aplicativo de console C # "padrão"?
Respostas:
Se você imprimir apenas
"\r"
no console, o cursor retornará ao início da linha atual e poderá reescrevê-lo. Isso deve fazer o truque:Observe os poucos espaços após o número para garantir que o que estava lá antes seja apagado.
Observe também o uso de em
Write()
vez de,WriteLine()
pois você não deseja adicionar um "\ n" no final da linha.fonte
PadRight
(salvar a sequência ou o comprimento sem preenchimento, é claro).Você pode usar
Console.SetCursorPosition
para definir a posição do cursor e, em seguida, escrever na posição atual.Aqui está um exemplo mostrando um simples "botão giratório":
Observe que você precisará substituir qualquer saída existente por uma nova saída ou espaços em branco.
Atualização: Como foi criticado que o exemplo move o cursor apenas de volta em um caractere, acrescentarei isso para esclarecimentos:
SetCursorPosition
Você pode definir o cursor para qualquer posição na janela do console.irá definir o cursor para o início da linha atual (ou você pode usar
Console.CursorLeft = 0
diretamente).fonte
SetCursorPosition
(ouCursorLeft
) permite mais flexibilidade, por exemplo, não escrever no início da linha, subir na janela, etc. barras de progresso personalizadas ou gráfico ASCII.Até agora, temos três alternativas concorrentes para fazer isso:
Eu sempre usei
Console.CursorLeft = 0
uma variação na terceira opção, então decidi fazer alguns testes. Aqui está o código que eu usei:Na minha máquina, obtenho os seguintes resultados:
Além disso,
SetCursorPosition
causou cintilação notável que eu não observei com nenhuma das alternativas. Portanto, a moral é usar backspaces ou retornos de carro quando possível , e obrigado por me ensinar uma maneira mais rápida de fazer isso, ASSIM!Atualização : nos comentários, Joel sugere que SetCursorPosition seja constante em relação à distância movida enquanto os outros métodos são lineares. Testes adicionais confirmam que esse é o caso, porém o tempo constante e lento ainda são lentos. Nos meus testes, gravar uma longa seqüência de backspaces no console é mais rápido que o SetCursorPosition até cerca de 60 caracteres. Portanto, o backspace é mais rápido para substituir partes da linha com menos de 60 caracteres (mais ou menos), e não pisca, por isso vou defender meu endosso inicial de \ b over \ re e
SetCursorPosition
.fonte
Você pode usar a sequência de escape \ b (backspace) para fazer backup de um número específico de caracteres na linha atual. Isso apenas move a localização atual, não remove os caracteres.
Por exemplo:
Aqui, linha é a linha de porcentagem a ser gravada no console. O truque é gerar o número correto de caracteres \ b para a saída anterior.
A vantagem deste sobre o \ r abordagem é que, se funciona mesmo se a sua saída percentual não é no início da linha.
fonte
\r
é usado para esses cenários.\r
representa um retorno de carro, o que significa que o cursor retorna ao início da linha.É por isso que o Windows usa
\n\r
como seu novo marcador de linha.\n
move você para baixo de uma linha e\r
retorna para o início da linha.fonte
Eu só tive que brincar com a
ConsoleSpinner
classe do divo . O meu não é nem de longe tão conciso, mas simplesmente não me agradou que os usuários dessa classe tivessem que escrever seu própriowhile(true)
loop. Estou filmando para uma experiência mais como esta:E eu percebi isso com o código abaixo. Como não quero que meu
Start()
método bloqueie, não quero que o usuário tenha que se preocupar em escrever umwhile(spinFlag)
loop semelhante e quero permitir vários giradores ao mesmo tempo em que tive que gerar um thread separado para lidar com o fiação. E isso significa que o código precisa ser muito mais complicado.Além disso, eu não fiz muito multiencadeamento, então é possível (provavelmente até) que eu tenha deixado um bug sutil ou três lá. Mas parece funcionar muito bem até agora:
fonte
Usar explicitamente um retorno de carrage (\ r) no início da linha, em vez de (implicitamente ou explicitamente) usar uma nova linha (\ n) no final, deve ser o que você deseja. Por exemplo:
fonte
fonte
Nos documentos do console no MSDN:
Então - eu fiz isso:
Então eu sou capaz de controlar a saída sozinho;
Outra maneira de chegar lá.
fonte
Isso funciona se você quiser fazer a geração de arquivos parecer legal.
E este é o método que obtive de alguma resposta abaixo e a modifiquei
fonte
Aqui está outro: D
fonte
Se você deseja atualizar uma linha, mas as informações são muito longas para serem exibidas em uma linha, podem ser necessárias novas linhas. Eu encontrei esse problema, e abaixo está uma maneira de resolver isso.
fonte
Eu estava procurando a mesma solução em vb.net e encontrei este e é ótimo.
no entanto, como @JohnOdom sugeriu uma maneira melhor de lidar com o espaço em branco se o anterior for maior que o atual.
Eu faço uma função no vb.net e pensei que alguém poderia ser ajudado ..
aqui está o meu código:
fonte
Static intLastLength As Integer
.Eu estava fazendo uma pesquisa para ver se a solução que escrevi poderia ser otimizada para velocidade. O que eu queria era um cronômetro de contagem regressiva, não apenas atualizando a linha atual. Aqui está o que eu criei. Pode ser útil para alguém
fonte
Inspirado pela @ E.Lahu Solution, a implementação de uma barra progride com porcentagem.
fonte
Aqui está a minha opinião sobre as respostas de s soosh e 0xA3. Ele pode atualizar o console com mensagens do usuário enquanto atualiza o girador e também possui um indicador de tempo decorrido.
uso é algo como isto:
fonte
O
SetCursorPosition
método funciona no cenário de multiencadeamento, onde os outros dois métodos nãofonte