【问题标题】:JAVA Sort CSV file by columns and then by a date column correctlyJAVA 按列排序 CSV 文件,然后按日期列正确排序
【发布时间】:2019-03-19 02:29:22
【问题描述】:

我想弄清楚为什么我的日期排序不起作用。

我想按一些选择列(字符串)然后按日期列对 CSV 文件进行排序。 但是它没有正确排序日期 - 它似乎只是按日期的第一部分(25/12/2018)而不是确切的日期排序。

public class MultiColumnCsvSort
{
private static final String COLUMN_SEPARATOR = ",";

public static void main(String[] args) throws Exception
{
    InputStream inputStream = new FileInputStream("order_lines_file.csv");
    List<List<String>> lines = readCsv(inputStream);

    // Create a comparator that sorts primarily by column 0,
    // and if these values are equal, by column 2
    Comparator<List<String>> comparator = createComparator(2,1,5);
    Collections.sort(lines, comparator);


    OutputStream outputStream = new FileOutputStream("output.csv");
    String header = "order id, sku, store, location, quantity, date";
    writeCsv(header, lines, outputStream);        
}
private static List<List<String>> readCsv(
    InputStream inputStream) throws IOException
{
    BufferedReader reader = new BufferedReader(
        new InputStreamReader(inputStream));
    List<List<String>> lines = new ArrayList<List<String>>();

    // Skip header
    String line = reader.readLine();

    while (true)
    {
        line = reader.readLine();
        if (line == null)
        {
            break;
        }
        List<String> list = Arrays.asList(line.split(COLUMN_SEPARATOR));
        lines.add(list);
    }
    return lines;
}
private static void writeCsv(
    String header, List<List<String>> lines, OutputStream outputStream) 
    throws IOException
{
    Writer writer = new OutputStreamWriter(outputStream);
    writer.write(header+"\n");
    for (List<String> list : lines)
    {
        for (int i = 0; i < list.size(); i++)
        {
            writer.write(list.get(i));
            if (i < list.size() - 1)
            {
                writer.write(COLUMN_SEPARATOR);
            }
        }
        writer.write("\n");
    }
    writer.close();
}

private static <T extends Comparable<? super T>> Comparator<List<T>> 
    createComparator(int... indices)
{
    return createComparator(MultiColumnCsvSort.<T>naturalOrder(), indices);
}

private static <T extends Comparable<? super T>> Comparator<T>
    naturalOrder()
{
    return new Comparator<T>()
    {
        @Override
        public int compare(T t0, T t1)
        {
            return t0.compareTo(t1);
        }
    };
}
private static <T> Comparator<List<T>> createComparator(
    final Comparator<? super T> delegate, final int... indices)
{
    return new Comparator<List<T>>()
    {
        @Override
        public int compare(List<T> list0, List<T> list1)
        {   
            for (int i = 0; i < indices.length; i++)
            {
                T element0 = list0.get(indices[i]);
                T element1 = list1.get(indices[i]);
                        int n = delegate.compare(element0, element1);
                        if (n != 0)
                        {
                            return n;
                        }
            }
            return 0;
        }
    };
}

}

我从这篇文章中摘录的:

How to sort csv file by two columns in java?

但是,当我知道这些值之间存在日期行时,输出如下所示: current sorted file

【问题讨论】:

  • 是的,naturalOrder 比较器纯粹按字符串排序。您需要将输入列从文本“25/12/2018”转换为合适的 Java 类,然后进行比较。
  • @KevinO 你能告诉我如何在我的代码中做到这一点吗?

标签: java csv sorting


【解决方案1】:

YYYY-MM-DD(ISO 8601 格式)

按日期的第一部分(25/12/2018)而不是确切日期订购。

所以将字符串变形为标准的ISO 8601 格式(YYYY-MM-DD)。按字母顺序排序的值也将按时间顺序排列。

解析输入字符串

定义格式模式以匹配您的输入。

String input = "25/12/2018" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd/MM/uuuu" ) ;
LocalDate ld = LocalDate.parse( input , f ) ;

当然,您应该在真实代码中缓存DateTimeFormatter 对象。请注意,java.time 类是 thread-safe,并使用不可变对象模式。

生成输出字符串

java.time 类在生成/解析字符串时默认使用标准 ISO 8601 格式。所以不需要指定格式模式。

String output = ld.toString() ;  // Outputs standard format: YYYY-MM-DD

【讨论】:

  • 谢谢你的建议 - 你能告诉我我应该把它放在我的代码中的什么地方吗?玩了一点,但卡住了。
猜你喜欢
  • 1970-01-01
  • 2017-03-19
  • 2015-05-02
  • 1970-01-01
  • 2014-08-14
  • 2010-12-14
  • 2014-07-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多