格式化具有固定宽度列的文本表

时间:2014-04-19 02:58:27

标签: java file

我有一个包含商店信息的文件,我想在另一个文件中对它进行排序(如Excel)。

文件:

001     Tablets                        5      3
002     pens                           4      1
005     Computeres                     3      0
003     Bages                          2      1
004     USB                            4      0

我写这段代码:

import java.util.*;
import java.io.*;

public class Sort {
public static void main(String [] args) throws IOException {
    FileInputStream fileinput = new FileInputStream("input.txt");
    FileOutputStream fileoutput = new FileOutputStream("output.txt");
    Scanner infile = new Scanner(fileinput);
    PrintWriter pw = new PrintWriter(fileoutput);
    int id, quantity, soldQuantity;
    String title;
    pw.println("ID\tTitle\t\t\tQuantity\tSoldQuantity");
    pw.println("");
    while(infile.hasNext()){
        id = infile.nextInt();
        title = infile.next();
        quantity = infile.nextInt();
        soldQuantity = infile.nextInt();
        pw.printf("%6d\t%s\t\t%d\t%d%n", id , title, quantity, soldQuantity);
    }
    infile.close();
    pw.close();
}
}

我希望它看起来像这样:

Code(ID)    Name            Quantity    SoldQuantity

     001    Tablets                5               3
     002    pens                   4               1
     005    Computeres             3               0
     003    Bages                  2               1
     004    USB                    4               0

我的问题是数量和销售数量的数量,它不适合。 看起来像这样:

Code(ID)    Name            Quantity    SoldQuantity

     001    Tablets             5               3
     002    pens             4               1
     005    Computers             3               0
     003    Bags             2               1
     004    USB             4               0

如果名称大于“计算机”,名称大小不同时会出现问题,我该如何处理呢?

谢谢

4 个答案:

答案 0 :(得分:3)

不使用\t作为间距,也可以为字符串使用宽度修饰符:

pw.printf("%6d\t%30s%d\t%d%n", id, title, quantity, soldQuantity);

如果你真的想确保无论最长title有多长,所有内容都排成一行,你可以找到最长的长度,添加一个长度,并使用它将格式字符串粘贴在一起。

答案 1 :(得分:0)

根据Name列中的item长度创建一个返回空格的方法。

public String getSpaces(int len){
   int num = 23-len;
   char[] chars = new char[num];
   Arrays.fill(chars, ' ');
   return new String(chars);
}

现在执行此操作以在标题后获取空格:

getSpaces(title.length);

希望这有帮助

答案 2 :(得分:0)

请参阅doc

中的文档

样品:

Formatter formatter = new Formatter();
System.out.println(formatter.format("%10s %10s %10s", "Title1", "Title2", "Title3"));

for (int i = 0; i < 10; i++) {
        String row = "info" + i;
        System.out.println(formatter.format("%10s %10s %10s", row, row, row));
}

答案 3 :(得分:0)

uniVocity-parsers有一个固定宽度的解析器/编写器,您应该使用它而不是尝试编写自己的解析器/编写器。

您甚至可以使用带注释的java bean。这是一个例子:

class TestBean {

// if the value parsed in the quantity column is "?" or "-", it will be replaced by null.
@NullString(nulls = { "?", "-" })
// if a value resolves to null, it will be converted to the String "0".
@Parsed(defaultNullRead = "0")
private Integer quantity;   // The attribute type defines which conversion will be executed when processing the value.
// In this case, IntegerConversion will be used.
// The attribute name will be matched against the column header in the file automatically.

@Trim
@LowerCase
// the value for the comments attribute is in the column at index 4 (0 is the first column, so this means fifth column in the file)
@Parsed(index = 4)
private String comments;

// you can also explicitly give the name of a column in the file.
@Parsed(field = "amount")
private BigDecimal amount;

@Trim
@LowerCase
// values "no", "n" and "null" will be converted to false; values "yes" and "y" will be converted to true
@BooleanString(falseStrings = { "no", "n", "null" }, trueStrings = { "yes", "y" })
@Parsed
private Boolean pending;

让我们用TestBean写一个固定宽度的文件:

FixedWidthFieldLengths lengths = new FixedWidthFieldLengths(10, 10, 35, 10, 40);
FixedWidthWriterSettings settings = new FixedWidthWriterSettings(lengths);

// Any null values will be written as ?
settings.setNullValue("?");

// Creates a BeanWriterProcessor that handles annotated fields in the TestBean class.
settings.setRowWriterProcessor(new BeanWriterProcessor<TestBean>(TestBean.class));

// Sets the file headers so the writer knows the correct order when writing values taken from a TestBean instance
settings.setHeaders("amount", "pending", "date", "quantity", "comments");

// Creates a writer with the above settings;
FixedWidthWriter writer = new FixedWidthWriter(outputWriter, settings);

// Writes the headers specified in the settings
writer.writeHeaders();

// writes a fixed width row with empty values (as nothing was set in the TestBean instance).
writer.processRecord(new TestBean());

TestBean bean = new TestBean();
bean.setAmount(new BigDecimal("500.33"));
bean.setComments("Blah,blah");
bean.setPending(false);
bean.setQuantity(100);

// writes a Fixed Width row with the values set in "bean". Notice that there's no annotated
// attribute for the "date" column, so it will just be null (an then converted to ?, as we have settings.setNullValue("?");)
writer.processRecord(bean);

// you can still write rows passing in its values directly.
writer.writeRow(BigDecimal.ONE, true, "1990-01-10", 3, null);

输出:

amount    pending   date                               quantity  comments
?         ?         ?                                  ?         ?
500.33    no        ?                                  100       blah,blah
1         true      1990-01-10                         3         ?

披露:我是这个图书馆的作者。它是开源和免费的(Apache V2.0许可证)。