Печать с "\t" (вкладки) не приводит к выравниванию столбцов

У меня очень странная проблема. После написания этого:

for (File f : currentFile.listFiles()) {            
    if  (f.isDirectory()){
        System.out.println(f.getName()+"\t"+"Dir\t"+Command.getpremission(f)+"\t"+f.getTotalSpace());
    }
    else{
        System.out.println(f.getName()+"\t"+"File\t"+Command.getpremission(f)+"\t"+f.getTotalSpace());
    }

Я вижу это напечатано:

see.txt File    rw  267642728448
see1.txt    File    rw  267642728456
see2.txt    File    rw  267642728448

Почему проблема с вкладками?

8 ответов

Основываясь на этом вопросе, я использую следующий код для отступа моих сообщений:

String prefix1 = "short text:";
String prefix2 = "looooooooooooooong text:";
String msg = "indented";
/*
 * The second string begins after 40 characters. The dash means that the
 * first string is left-justified.
 */
String format = "%-40s%s%n";
System.out.printf(format, prefix1, msg);
System.out.printf(format, prefix2, msg);

Это вывод:

краткий текст: отступ
Текст "оооооооооооо": отступ

"Проблема" с вкладками заключается в том, что они имеют отступ текста от фиксированных позиций вкладок, обычно кратных 4 или 8 символам (в зависимости от того, какая консоль или редактор их отображают). Ваше первое имя файла имеет 7 символов, поэтому следующая позиция табуляции после его конца находится в позиции 8. Однако последующие имена файлов имеют длину 8 символов, поэтому следующая позиция табуляции находится в позиции 12.

Если вы хотите, чтобы столбцы были правильно смещены в одну и ту же позицию, вам необходимо принять во внимание фактическую длину предыдущих столбцов и либо изменить количество следующих вкладок, либо вместо этого заполнить нужным количеством пробелов. Последнее может быть достигнуто с помощью, например, System.out.printf с соответствующей спецификацией формата (например, "%1$13s" задает минимальную ширину 13 символов для отображения первого аргумента в виде строки).

Длина текста, который вы предоставляете в каждой строке, отличается, это проблема, поэтому, если второе слово слишком длинное (see2.txt длиной 8 символов, что соответствует длине одной вкладки), она распечатывает вкладку, которая переходит к следующей точке табуляции. Один из способов решить эту проблему - программно добавить пэд к f.getName() текст так каждый текст генерируется: see.txt или же see2.txt имеет одинаковую длину (например, see.txt_ а также see2.txt) поэтому каждая вкладка автоматически переходит к одной и той же точке табуляции.

Если вы разрабатываете с JDK 1.5, вы можете решить эту проблему с помощью java.util.Formatter:

String format = "%-20s %5d\n";
System.out.format(format, "test", 1);
System.out.format(format, "test2", 20);
System.out.format(format, "test3", 5000);

этот пример даст вам этот отпечаток:

test                     1
test2                   20
test3                 5000

В продолжение комментариев Петера и Дункана я обычно использую метод быстрого заполнения, что-то вроде -

public String rpad(String inStr, int finalLength)
{
    return (inStr + "                          " // typically a sufficient length spaces string.
        ).substring(0, finalLength);
}

Точно так же вы можете иметь lpad() также

Как упоминали другие люди, проблема заключается в переменной длине строки.

Вместо того, чтобы изобретать велосипед, у Apache Commons есть хорошее, чистое решение для этого в StringUtils.

StringUtils.rightPad("String to extend",100); //100 is the length you want to pad out to.

Проблема в длине имен файлов. Первое имя файла имеет длину всего 7 символов, поэтому вкладка отображается на 8-ом символе (после каждого 4 символа выполняется вкладка). Однако следующие имена файлов имеют длину 8 символов, поэтому следующая вкладка будет отображаться только до 12 символа. И если у вас имена файлов длиннее 11 символов, вы снова столкнетесь с той же проблемой.

Вы можете использовать этот пример для решения вашей проблемы:

System.out.printf( "%-15s %15s %n", "name", "lastname");
System.out.printf( "%-15s %15s %n", "Bill", "Smith");

Вы можете играть с "%", пока не найдете правильное выравнивание, чтобы удовлетворить ваши потребности

Вы также можете дополнить строку до необходимой длины, используя Guava's Strings.padEnd (String input, int minLength, padding)

Другие вопросы по тегам