在java中获取csv文件维度的最快方法是什么

我在获取csv文件的维度任务时的常规过程如下:

  1. 获取它有多少行:

我使用while循环读取每一行,并通过每次成功读取计数。 缺点是读取整个文件需要花费时间来计算它有多少行。

  1. 然后得到它有多少列:我使用String[] temp = lineOfText.split(","); 然后采取临时的大小。

有更聪明的方法吗? 喜欢:
file1 = read.csv;
xDimention = file1.xDimention;
yDimention = file1.yDimention;

您的方法不适用于多行值(您将获得无效的行数)和可能恰好包含分隔符的引用值(您将获得无效的列数)。

您应该使用CSV解析器,例如univocity-parsers提供的解析器 。

使用uniVocity CSV解析器,确定尺寸的最快方法是使用以下代码。 它解析一个150MB的文件 ,在1.2秒内给出它的尺寸:

 // Let's create our own RowProcessor to analyze the rows static class CsvDimension extends AbstractRowProcessor { int lastColumn = -1; long rowCount = 0; @Override public void rowProcessed(String[] row, ParsingContext context) { rowCount++; if (lastColumn < row.length) { lastColumn = row.length; } } } public static void main(String... args) throws FileNotFoundException { // let's measure the time roughly long start = System.currentTimeMillis(); //Creates an instance of our own custom RowProcessor, defined above. CsvDimension myDimensionProcessor = new CsvDimension(); CsvParserSettings settings = new CsvParserSettings(); //This tells the parser that no row should have more than 2,000,000 columns settings.setMaxColumns(2000000); //Here you can select the column indexes you are interested in reading. //The parser will return values for the columns you selected, in the order you defined //By selecting no indexes here, no String objects will be created settings.selectIndexes(/*nothing here*/); //When you select indexes, the columns are reordered so they come in the order you defined. //By disabling column reordering, you will get the original row, with nulls in the columns you didn't select settings.setColumnReorderingEnabled(false); //We instruct the parser to send all rows parsed to your custom RowProcessor. settings.setRowProcessor(myDimensionProcessor); //Finally, we create a parser CsvParser parser = new CsvParser(settings); //And parse! All rows are sent to your custom RowProcessor (CsvDimension) //I'm using a 150MB CSV file with 1.3 million rows. parser.parse(new FileReader(new File("c:/tmp/worldcitiespop.txt"))); //Nothing else to do. The parser closes the input and does everything for you safely. Let's just get the results: System.out.println("Columns: " + myDimensionProcessor.lastColumn); System.out.println("Rows: " + myDimensionProcessor.rowCount); System.out.println("Time taken: " + (System.currentTimeMillis() - start) + " ms"); } 

输出将是:

 Columns: 7 Rows: 3173959 Time taken: 1279 ms 

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

我想这取决于结构的规律性,以及你是否需要一个确切的答案。

我可以想象查看前几行(或随机跳过文件),然后将文件大小除以平均行大小以确定粗略的行数。

如果您控制这些文件的编写方式,您可以标记它们或在它们旁边添加包含行计数的元数据文件。

严格来说,你分割线的方式并没有涵盖所有可能的情况。 "hello, world", 4, 5应该读作有3列,而不是4列。

IMO,你正在做的是一种可以接受的方式。 但是有一些方法可以让它更快:

  1. 而不是读取为每行创建一个新String对象的行,只需使用String.indexOf来查找行的边界
  2. 而不是使用line.split,再次使用indexOf来计算逗号的数量
  3. multithreading

我猜这里的选项取决于你如何使用数据:

  1. 写入文件时存储csv文件的尺寸(在第一行或在附加文件中)
  2. 使用更有效的方式来计算行数 – 也许是http://docs.oracle.com/javase/6/docs/api/java/io/LineNumberReader.html
  3. 而不是创建固定大小的数组(假设你需要的行数)使用数组列表 – 这可能会或可能不会更高效,具体取决于文件的大小。

要查找行数,您必须读取整个文件。 你在这里无能为力。 但是,找到cols数量的方法效率有点低。 而不是split只是计算多少次“,”出现在行中。 您可能还包括@Vlad所述的配额中的字段的特殊条件。

String.split方法创建一个字符串数组作为结果,并使用regexp进行拆分,这不是非常有效。

我在这里找到了这个简短而有趣的解决方案: https : //stackoverflow.com/a/5342096/4082824

 LineNumberReader lnr = new LineNumberReader(new FileReader(new File("File1"))); lnr.skip(Long.MAX_VALUE); System.out.println(lnr.getLineNumber() + 1); //Add 1 because line index starts at 0 lnr.close(); 

我的解决方案是使用多行单元格或引用值简单而正确地处理CSV。

例如我们有csv文件:

 1,"""2""","""111,222""","""234;222""","""""","1 2 3" 2,"""2""","""111,222""","""234;222""","""""","2 3" 3,"""5""","""1112""","""10;2""","""""","1 2" 

我的解决方案片段是:

 import java.io.*; public class CsvDimension { public void parse(Reader reader) throws IOException { long cells = 0; int lines = 0; int c; boolean qouted = false; while ((c = reader.read()) != -1) { if (c == '"') { qouted = !qouted; } if (!qouted) { if (c == '\n') { lines++; cells++; } if (c == ',') { cells++; } } } System.out.printf("lines : %d\n cells %d\n cols: %d\n", lines, cells, cells / lines); reader.close(); } public static void main(String args[]) throws IOException { new CsvDimension().parse(new BufferedReader(new FileReader(new File("test.csv")))); } }