如何将CSV文件拆分为多个块并在Java代码中并行读取这些块

我有一个非常大的CSV文件(1GB +),它有100,000行。

我需要编写一个Java程序来解析CSV文件中的每一行,以便为HTTP请求发送一个主体。

换句话说,我需要发送100,000个HTTP请求,这些请求对应于CSV文件中的行。 如果我在一个线程中执行这些操作将会很长。

我想创建1,000个线程来执行i)从CSV文件中读取一行,ii)创建一个HTTP请求,其主体包含读取行的内容,以及iii)发送HTTP请求并接收响应。

这样,我需要将CSV文件拆分为1,000个块,并且这些块之间应该没有重叠的行。

这种分裂程序的最佳方法是什么?

同时读取多个位置的单个文件不会让你走得更快(但它可能会大大减慢你的速度)。

不是从多个线程读取文件,而是从单个线程读取文件,并并行处理这些行。 单线应该逐行读取CSV,并将每一行放入队列中。 然后,多个工作线程应从队列中获取下一行,解析它,转换为请求,并根据需要同时处理请求。 然后,通过单个线程完成工作的拆分,确保没有缺失的线或重叠。

您可以拥有一个读取CSV行的线程并构建一个读取行的列表。 当达到某个限制时,例如100行,将其传递给固定大小的线程池以作为请求发送。

我怀疑除非您的服务器有1000个内核,否则您可能会发现使用10-100个并发请求的速度更快。

通过构造Runnable Task的对象并将其传递给Executors's submit() ,可以异步执行该行,从而将该行委托给池中的一个可用Thread从而在单个线程中读取CSV文件。

  public static void main(String[] args) throws IOException { String fName = "C:\\Amit\\abc.csv"; String thisLine; FileInputStream fis = new FileInputStream(fName); DataInputStream myInput = new DataInputStream(fis); ExecutorService pool=Executors.newFixedThreadPool(1000); int count = 0; // Concurrent request to Server barrier while ((thisLine = myInput.readLine()) != null) { if (count > 150) { try { Thread.sleep(100); count = 0; } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } pool.submit(new MyTask(thisLine)); count++; } } } 

在这里你的任务:

 class MyTask implements Runnable { private String lLine; public MyTask(String line) { this.lLine=line; } public void run() { // 1) Create Request lLine // 2) send the HTTP request out and receive response } } 

让一个线程逐行读取文件并读取每一行,将任务发送到ExecutorService以对每个执行HTTP请求。

从多个线程读取文件是行不通的,因为为了读取第n行,您必须先读取所有其他行。 (如果您的文件包含固定宽度记录,则理论上可以工作,但CSV不是固定宽度格式。)

如果您希望在同一操作中解压缩和解析,请查看https://github.com/skjolber/unzip-csv 。

Java 8计划于本月发布,它将通过并行流和lambdas改进对此的支持。 Oracle关于并行流的教程可能是一个很好的起点。

请注意,这里的陷阱是并行性过多。 对于检索URL的示例,拥有少量并行调用可能是个好主意。 太多的并行性不仅会影响带宽和您连接的网站,而且还会冒着文件描述符耗尽的风险,这在大多数运行java的环境中都是一种严格限制的资源。

一些可能对你有帮助的框架是Netflix的RxJava和Akka 。 请注意,这些框架并非易事,需要付出一些努力才能学习。